src/java.base/share/classes/java/security/SignedObject.java
branchJDK-8145252-TLS13-branch
changeset 56542 56aaa6cb3693
parent 47216 71c04702a3d5
child 56548 208b4e9365cd
equal deleted inserted replaced
56541:92cbbfc996f3 56542:56aaa6cb3693
     1 /*
     1 /*
     2  * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
    24  */
    24  */
    25 
    25 
    26 package java.security;
    26 package java.security;
    27 
    27 
    28 import java.io.*;
    28 import java.io.*;
       
    29 import java.security.spec.AlgorithmParameterSpec;
    29 
    30 
    30 /**
    31 /**
    31  * <p> SignedObject is a class for the purpose of creating authentic
    32  * <p> SignedObject is a class for the purpose of creating authentic
    32  * runtime objects whose integrity cannot be compromised without being
    33  * runtime objects whose integrity cannot be compromised without being
    33  * detected.
    34  * detected.
    45  *
    46  *
    46  * <pre>{@code
    47  * <pre>{@code
    47  * Signature signingEngine = Signature.getInstance(algorithm,
    48  * Signature signingEngine = Signature.getInstance(algorithm,
    48  *                                                 provider);
    49  *                                                 provider);
    49  * SignedObject so = new SignedObject(myobject, signingKey,
    50  * SignedObject so = new SignedObject(myobject, signingKey,
    50  *                                    signingEngine);
    51  *                                    signingParams, signingEngine);
    51  * }</pre>
    52  * }</pre>
    52  *
    53  *
    53  * <p> A typical usage for verification is the following (having
    54  * <p> A typical usage for verification is the following (having
    54  * received SignedObject {@code so}):
    55  * received SignedObject {@code so}):
    55  *
    56  *
    56  * <pre>{@code
    57  * <pre>{@code
    57  * Signature verificationEngine =
    58  * Signature verificationEngine =
    58  *     Signature.getInstance(algorithm, provider);
    59  *     Signature.getInstance(algorithm, provider);
    59  * if (so.verify(publickey, verificationEngine))
    60  * if (so.verify(verificationKey, verificationParams, verificationEngine))
    60  *     try {
    61  *     try {
    61  *         Object myobj = so.getObject();
    62  *         Object myobj = so.getObject();
    62  *     } catch (java.lang.ClassNotFoundException e) {};
    63  *     } catch (java.lang.ClassNotFoundException e) {};
    63  * }</pre>
    64  * }</pre>
    64  *
    65  *
    65  * <p> Several points are worth noting.  First, there is no need to
    66  * <p> Several points are worth noting.  First, there is no need to
    66  * initialize the signing or verification engine, as it will be
    67  * initialize the signing or verification engine, as it will be
    67  * re-initialized inside the constructor and the {@code verify}
    68  * re-initialized inside the constructor and the {@code verify}
    68  * method. Secondly, for verification to succeed, the specified
    69  * method. Secondly, for verification to succeed, the specified
    69  * public key must be the public key corresponding to the private key
    70  * public key must be the public key corresponding to the private key
    70  * used to generate the SignedObject.
    71  * used to generate the SignedObject. If signing parameters are used,
       
    72  * the same parameters must be specified when calling {@code verify}
       
    73  * method for verification to succeed.
    71  *
    74  *
    72  * <p> More importantly, for flexibility reasons, the
    75  * <p> More importantly, for flexibility reasons, the
    73  * constructor and {@code verify} method allow for
    76  * constructor and {@code verify} method allow for
    74  * customized signature engines, which can implement signature
    77  * customized signature engines, which can implement signature
    75  * algorithms that are not installed formally as part of a crypto
    78  * algorithms that are not installed formally as part of a crypto
   130     private byte[] signature;
   133     private byte[] signature;
   131     private String thealgorithm;
   134     private String thealgorithm;
   132 
   135 
   133     /**
   136     /**
   134      * Constructs a SignedObject from any Serializable object.
   137      * Constructs a SignedObject from any Serializable object.
   135      * The given object is signed with the given signing key, using the
   138      * The given object is signed with the given signing key with
   136      * designated signature engine.
   139      * no signature parameters, using the designated signature engine.
   137      *
   140      *
   138      * @param object the object to be signed.
   141      * @param object the object to be signed.
   139      * @param signingKey the private key for signing.
   142      * @param signingKey the private key for signing.
   140      * @param signingEngine the signature signing engine.
   143      * @param signingEngine the signature signing engine.
   141      *
   144      *
   144      * @exception SignatureException if signing fails.
   147      * @exception SignatureException if signing fails.
   145      */
   148      */
   146     public SignedObject(Serializable object, PrivateKey signingKey,
   149     public SignedObject(Serializable object, PrivateKey signingKey,
   147                         Signature signingEngine)
   150                         Signature signingEngine)
   148         throws IOException, InvalidKeyException, SignatureException {
   151         throws IOException, InvalidKeyException, SignatureException {
   149             // creating a stream pipe-line, from a to b
   152         // creating a stream pipe-line, from a to b
   150             ByteArrayOutputStream b = new ByteArrayOutputStream();
   153         ByteArrayOutputStream b = new ByteArrayOutputStream();
   151             ObjectOutput a = new ObjectOutputStream(b);
   154         ObjectOutput a = new ObjectOutputStream(b);
   152 
   155 
   153             // write and flush the object content to byte array
   156         // write and flush the object content to byte array
   154             a.writeObject(object);
   157         a.writeObject(object);
   155             a.flush();
   158         a.flush();
   156             a.close();
   159         a.close();
   157             this.content = b.toByteArray();
   160         this.content = b.toByteArray();
   158             b.close();
   161         b.close();
   159 
   162 
   160             // now sign the encapsulated object
   163         // now sign the encapsulated object
   161             this.sign(signingKey, signingEngine);
   164         try {
       
   165             this.sign(signingKey, null, signingEngine);
       
   166         } catch (InvalidAlgorithmParameterException e) {
       
   167             // should not happen, re-throw just in case
       
   168             throw new SignatureException(e);
       
   169         }
       
   170     }
       
   171 
       
   172     /**
       
   173      * Constructs a SignedObject from any Serializable object.
       
   174      * The given object is signed with the given signing key and
       
   175      * signature parameters, using the designated signature engine.
       
   176      * If the signature algorithm does not use any signature parameters,
       
   177      * {@code signingParams} should be null.
       
   178      *
       
   179      * @param object the object to be signed.
       
   180      * @param signingKey the private key for signing.
       
   181      * @param signingParams the signature parameters used for signing,
       
   182      * may be null.
       
   183      * @param signingEngine the signature signing engine.
       
   184      *
       
   185      * @exception IOException if an error occurs during serialization
       
   186      * @exception InvalidKeyException if the key is invalid.
       
   187      * @exception InvalidAlgorithmParameterException if the given signature
       
   188      * parameters is invalid.
       
   189      * @exception SignatureException if signing fails.
       
   190      * @since 11
       
   191      */
       
   192     public SignedObject(Serializable object, PrivateKey signingKey,
       
   193                         AlgorithmParameterSpec signingParams,
       
   194                         Signature signingEngine)
       
   195         throws IOException, InvalidKeyException,
       
   196         InvalidAlgorithmParameterException, SignatureException {
       
   197         // creating a stream pipe-line, from a to b
       
   198         ByteArrayOutputStream b = new ByteArrayOutputStream();
       
   199         ObjectOutput a = new ObjectOutputStream(b);
       
   200 
       
   201         // write and flush the object content to byte array
       
   202         a.writeObject(object);
       
   203         a.flush();
       
   204         a.close();
       
   205         this.content = b.toByteArray();
       
   206         b.close();
       
   207 
       
   208         // now sign the encapsulated object
       
   209         this.sign(signingKey, signingParams, signingEngine);
   162     }
   210     }
   163 
   211 
   164     /**
   212     /**
   165      * Retrieves the encapsulated object.
   213      * Retrieves the encapsulated object.
   166      * The encapsulated object is de-serialized before it is returned.
   214      * The encapsulated object is de-serialized before it is returned.
   170      * @exception IOException if an error occurs during de-serialization
   218      * @exception IOException if an error occurs during de-serialization
   171      * @exception ClassNotFoundException if an error occurs during
   219      * @exception ClassNotFoundException if an error occurs during
   172      * de-serialization
   220      * de-serialization
   173      */
   221      */
   174     public Object getObject()
   222     public Object getObject()
   175         throws IOException, ClassNotFoundException
   223         throws IOException, ClassNotFoundException {
   176     {
       
   177         // creating a stream pipe-line, from b to a
   224         // creating a stream pipe-line, from b to a
   178         ByteArrayInputStream b = new ByteArrayInputStream(this.content);
   225         ByteArrayInputStream b = new ByteArrayInputStream(this.content);
   179         ObjectInput a = new ObjectInputStream(b);
   226         ObjectInput a = new ObjectInputStream(b);
   180         Object obj = a.readObject();
   227         Object obj = a.readObject();
   181         b.close();
   228         b.close();
   204     }
   251     }
   205 
   252 
   206     /**
   253     /**
   207      * Verifies that the signature in this SignedObject is the valid
   254      * Verifies that the signature in this SignedObject is the valid
   208      * signature for the object stored inside, with the given
   255      * signature for the object stored inside, with the given
   209      * verification key, using the designated verification engine.
   256      * verification key with no signature parameters, using the designated
       
   257      * verification engine.
   210      *
   258      *
   211      * @param verificationKey the public key for verification.
   259      * @param verificationKey the public key for verification.
   212      * @param verificationEngine the signature verification engine.
   260      * @param verificationEngine the signature verification engine.
   213      *
   261      *
   214      * @exception SignatureException if signature verification failed (an
   262      * @exception SignatureException if signature verification failed (an
   220      * is valid, {@code false} otherwise
   268      * is valid, {@code false} otherwise
   221      */
   269      */
   222     public boolean verify(PublicKey verificationKey,
   270     public boolean verify(PublicKey verificationKey,
   223                           Signature verificationEngine)
   271                           Signature verificationEngine)
   224          throws InvalidKeyException, SignatureException {
   272          throws InvalidKeyException, SignatureException {
   225              verificationEngine.initVerify(verificationKey);
   273          try {
   226              verificationEngine.update(this.content.clone());
   274              return verify(verificationKey, null, verificationEngine);
   227              return verificationEngine.verify(this.signature.clone());
   275          } catch (InvalidAlgorithmParameterException e) {
       
   276             // should not happen, re-throw just in case
       
   277             throw new SignatureException(e);
       
   278          }
       
   279     }
       
   280 
       
   281     /**
       
   282      * Verifies that the signature in this SignedObject is the valid
       
   283      * signature for the object stored inside, with the given
       
   284      * verification key and signature parameters, using the designated
       
   285      * verification engine. If the signature algorithm does not use any
       
   286      * signature parameters, {@code verificationParams} should be null.
       
   287      * When signature parameters are used in signing, the same parameters
       
   288      * must be specified when calling {@code verify} method for the
       
   289      * verification to succeed.
       
   290      *
       
   291      * @param verificationKey the public key for verification.
       
   292      * @param verificationParams the signature parameters for verification.
       
   293      * @param verificationEngine the signature verification engine.
       
   294      *
       
   295      * @exception SignatureException if signature verification failed (an
       
   296      *     exception prevented the signature verification engine from completing
       
   297      *     normally).
       
   298      * @exception InvalidKeyException if the verification key is invalid.
       
   299      * @exception InvalidAlgorithmParameterException if the given signature
       
   300      * parameters is invalid
       
   301      * @return {@code true} if the signature is valid, {@code false} otherwise
       
   302      * @since 11
       
   303      */
       
   304     public boolean verify(PublicKey verificationKey,
       
   305                           AlgorithmParameterSpec verificationParams,
       
   306                           Signature verificationEngine)
       
   307          throws InvalidKeyException, InvalidAlgorithmParameterException,
       
   308          SignatureException {
       
   309          // set parameteres before Signature.initSign/initVerify call,
       
   310          // so key can be checked when it's set
       
   311          try {
       
   312              verificationEngine.setParameter(verificationParams);
       
   313          } catch (UnsupportedOperationException e) {
       
   314              // for backward compatibility, only re-throw when
       
   315              // parameters is not null 
       
   316              if (verificationParams != null) throw e;
       
   317          }
       
   318          verificationEngine.initVerify(verificationKey);
       
   319          verificationEngine.update(this.content.clone());
       
   320          return verificationEngine.verify(this.signature.clone());
   228     }
   321     }
   229 
   322 
   230     /*
   323     /*
   231      * Signs the encapsulated object with the given signing key, using the
   324      * Signs the encapsulated object with the given signing key, using the
   232      * designated signature engine.
   325      * designated signature engine.
   233      *
   326      *
   234      * @param signingKey the private key for signing.
   327      * @param signingKey the private key for signing.
       
   328      * @param signingParams the signature parameters for signing.
   235      * @param signingEngine the signature signing engine.
   329      * @param signingEngine the signature signing engine.
   236      *
   330      *
   237      * @exception InvalidKeyException if the key is invalid.
   331      * @exception InvalidKeyException if the key is invalid.
       
   332      * @exception InvalidAlgorithmParameterException if the given signature
       
   333      * parameters is invalid
   238      * @exception SignatureException if signing fails.
   334      * @exception SignatureException if signing fails.
   239      */
   335      */
   240     private void sign(PrivateKey signingKey, Signature signingEngine)
   336     private void sign(PrivateKey signingKey,
   241         throws InvalidKeyException, SignatureException {
   337                       AlgorithmParameterSpec signingParams,
   242             // initialize the signing engine
   338                       Signature signingEngine)
   243             signingEngine.initSign(signingKey);
   339         throws InvalidKeyException, InvalidAlgorithmParameterException,
   244             signingEngine.update(this.content.clone());
   340         SignatureException {
   245             this.signature = signingEngine.sign().clone();
   341         // set parameteres before Signature.initSign/initVerify call,
   246             this.thealgorithm = signingEngine.getAlgorithm();
   342         // so key can be checked when it's set
       
   343         try {
       
   344             signingEngine.setParameter(signingParams);
       
   345         } catch (UnsupportedOperationException e) {
       
   346             // for backward compatibility, only re-throw when
       
   347             // parameters is not null
       
   348             if (signingParams != null) throw e;
       
   349         }
       
   350         signingEngine.initSign(signingKey);
       
   351         signingEngine.update(this.content.clone());
       
   352         this.signature = signingEngine.sign().clone();
       
   353         this.thealgorithm = signingEngine.getAlgorithm();
   247     }
   354     }
   248 
   355 
   249     /**
   356     /**
   250      * readObject is called to restore the state of the SignedObject from
   357      * readObject is called to restore the state of the SignedObject from
   251      * a stream.
   358      * a stream.
   252      */
   359      */
   253     private void readObject(java.io.ObjectInputStream s)
   360     private void readObject(java.io.ObjectInputStream s)
   254         throws java.io.IOException, ClassNotFoundException {
   361         throws java.io.IOException, ClassNotFoundException {
   255             java.io.ObjectInputStream.GetField fields = s.readFields();
   362         java.io.ObjectInputStream.GetField fields = s.readFields();
   256             content = ((byte[])fields.get("content", null)).clone();
   363         content = ((byte[])fields.get("content", null)).clone();
   257             signature = ((byte[])fields.get("signature", null)).clone();
   364         signature = ((byte[])fields.get("signature", null)).clone();
   258             thealgorithm = (String)fields.get("thealgorithm", null);
   365         thealgorithm = (String)fields.get("thealgorithm", null);
   259     }
   366     }
   260 }
   367 }