< prev index next >

src/java.base/share/classes/java/security/SignedObject.java

Print this page


   1 /*
   2  * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   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
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.security;
  27 
  28 import java.io.*;

  29 
  30 /**
  31  * <p> SignedObject is a class for the purpose of creating authentic
  32  * runtime objects whose integrity cannot be compromised without being
  33  * detected.
  34  *
  35  * <p> More specifically, a SignedObject contains another Serializable
  36  * object, the (to-be-)signed object and its signature.
  37  *
  38  * <p> The signed object is a "deep copy" (in serialized form) of an
  39  * original object.  Once the copy is made, further manipulation of
  40  * the original object has no side effect on the copy.
  41  *
  42  * <p> The underlying signing algorithm is designated by the Signature
  43  * object passed to the constructor and the {@code verify} method.
  44  * A typical usage for signing is the following:
  45  *
  46  * <pre>{@code
  47  * Signature signingEngine = Signature.getInstance(algorithm,
  48  *                                                 provider);
  49  * SignedObject so = new SignedObject(myobject, signingKey,
  50  *                                    signingEngine);
  51  * }</pre>
  52  *
  53  * <p> A typical usage for verification is the following (having
  54  * received SignedObject {@code so}):
  55  *
  56  * <pre>{@code
  57  * Signature verificationEngine =
  58  *     Signature.getInstance(algorithm, provider);
  59  * if (so.verify(publickey, verificationEngine))
  60  *     try {
  61  *         Object myobj = so.getObject();
  62  *     } catch (java.lang.ClassNotFoundException e) {};
  63  * }</pre>
  64  *
  65  * <p> Several points are worth noting.  First, there is no need to
  66  * initialize the signing or verification engine, as it will be
  67  * re-initialized inside the constructor and the {@code verify}
  68  * method. Secondly, for verification to succeed, the specified
  69  * public key must be the public key corresponding to the private key
  70  * used to generate the SignedObject.


  71  *
  72  * <p> More importantly, for flexibility reasons, the
  73  * constructor and {@code verify} method allow for
  74  * customized signature engines, which can implement signature
  75  * algorithms that are not installed formally as part of a crypto
  76  * provider.  However, it is crucial that the programmer writing the
  77  * verifier code be aware what {@code Signature} engine is being
  78  * used, as its own implementation of the {@code verify} method
  79  * is invoked to verify a signature.  In other words, a malicious
  80  * {@code Signature} may choose to always return true on
  81  * verification in an attempt to bypass a security check.
  82  *
  83  * <p> The signature algorithm can be, among others, the NIST standard
  84  * DSA, using DSA and SHA-256.  The algorithm is specified using the
  85  * same convention as that for signatures. The DSA algorithm using the
  86  * SHA-256 message digest algorithm can be specified, for example, as
  87  * "SHA256withDSA".  In the case of
  88  * RSA the signing algorithm could be specified as, for example,
  89  * "SHA256withRSA".  The algorithm name must be
  90  * specified, as there is no default.


 115  * @author Li Gong
 116  * @since 1.2
 117  */
 118 
 119 public final class SignedObject implements Serializable {
 120 
 121     private static final long serialVersionUID = 720502720485447167L;
 122 
 123     /*
 124      * The original content is "deep copied" in its serialized format
 125      * and stored in a byte array.  The signature field is also in the
 126      * form of byte array.
 127      */
 128 
 129     private byte[] content;
 130     private byte[] signature;
 131     private String thealgorithm;
 132 
 133     /**
 134      * Constructs a SignedObject from any Serializable object.
 135      * The given object is signed with the given signing key, using the
 136      * designated signature engine.
 137      *
 138      * @param object the object to be signed.
 139      * @param signingKey the private key for signing.
 140      * @param signingEngine the signature signing engine.
 141      *
 142      * @exception IOException if an error occurs during serialization
 143      * @exception InvalidKeyException if the key is invalid.
 144      * @exception SignatureException if signing fails.
 145      */
 146     public SignedObject(Serializable object, PrivateKey signingKey,
 147                         Signature signingEngine)
 148         throws IOException, InvalidKeyException, SignatureException {
 149             // creating a stream pipe-line, from a to b
 150             ByteArrayOutputStream b = new ByteArrayOutputStream();
 151             ObjectOutput a = new ObjectOutputStream(b);
 152 
 153             // write and flush the object content to byte array
 154             a.writeObject(object);
 155             a.flush();
 156             a.close();
 157             this.content = b.toByteArray();
 158             b.close();
 159 
 160             // now sign the encapsulated object
 161             this.sign(signingKey, signingEngine);













































 162     }
 163 
 164     /**
 165      * Retrieves the encapsulated object.
 166      * The encapsulated object is de-serialized before it is returned.
 167      *
 168      * @return the encapsulated object.
 169      *
 170      * @exception IOException if an error occurs during de-serialization
 171      * @exception ClassNotFoundException if an error occurs during
 172      * de-serialization
 173      */
 174     public Object getObject()
 175         throws IOException, ClassNotFoundException
 176     {
 177         // creating a stream pipe-line, from b to a
 178         ByteArrayInputStream b = new ByteArrayInputStream(this.content);
 179         ObjectInput a = new ObjectInputStream(b);
 180         Object obj = a.readObject();
 181         b.close();
 182         a.close();
 183         return obj;
 184     }
 185 
 186     /**
 187      * Retrieves the signature on the signed object, in the form of a
 188      * byte array.
 189      *
 190      * @return the signature. Returns a new array each time this
 191      * method is called.
 192      */
 193     public byte[] getSignature() {
 194         return this.signature.clone();
 195     }
 196 
 197     /**
 198      * Retrieves the name of the signature algorithm.
 199      *
 200      * @return the signature algorithm name.
 201      */
 202     public String getAlgorithm() {
 203         return this.thealgorithm;
 204     }
 205 
 206     /**
 207      * Verifies that the signature in this SignedObject is the valid
 208      * signature for the object stored inside, with the given
 209      * verification key, using the designated verification engine.

 210      *
 211      * @param verificationKey the public key for verification.
 212      * @param verificationEngine the signature verification engine.
 213      *
 214      * @exception SignatureException if signature verification failed (an
 215      *     exception prevented the signature verification engine from completing
 216      *     normally).
 217      * @exception InvalidKeyException if the verification key is invalid.
 218      *
 219      * @return {@code true} if the signature
 220      * is valid, {@code false} otherwise
 221      */
 222     public boolean verify(PublicKey verificationKey,
 223                           Signature verificationEngine)
 224          throws InvalidKeyException, SignatureException {













































 225              verificationEngine.initVerify(verificationKey);
 226              verificationEngine.update(this.content.clone());
 227              return verificationEngine.verify(this.signature.clone());
 228     }
 229 
 230     /*
 231      * Signs the encapsulated object with the given signing key, using the
 232      * designated signature engine.
 233      *
 234      * @param signingKey the private key for signing.

 235      * @param signingEngine the signature signing engine.
 236      *
 237      * @exception InvalidKeyException if the key is invalid.


 238      * @exception SignatureException if signing fails.
 239      */
 240     private void sign(PrivateKey signingKey, Signature signingEngine)
 241         throws InvalidKeyException, SignatureException {
 242             // initialize the signing engine











 243             signingEngine.initSign(signingKey);
 244             signingEngine.update(this.content.clone());
 245             this.signature = signingEngine.sign().clone();
 246             this.thealgorithm = signingEngine.getAlgorithm();
 247     }
 248 
 249     /**
 250      * readObject is called to restore the state of the SignedObject from
 251      * a stream.
 252      */
 253     private void readObject(java.io.ObjectInputStream s)
 254         throws java.io.IOException, ClassNotFoundException {
 255             java.io.ObjectInputStream.GetField fields = s.readFields();
 256             content = ((byte[])fields.get("content", null)).clone();
 257             signature = ((byte[])fields.get("signature", null)).clone();
 258             thealgorithm = (String)fields.get("thealgorithm", null);
 259     }
 260 }
   1 /*
   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.
   4  *
   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
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.security;
  27 
  28 import java.io.*;
  29 import java.security.spec.AlgorithmParameterSpec;
  30 
  31 /**
  32  * <p> SignedObject is a class for the purpose of creating authentic
  33  * runtime objects whose integrity cannot be compromised without being
  34  * detected.
  35  *
  36  * <p> More specifically, a SignedObject contains another Serializable
  37  * object, the (to-be-)signed object and its signature.
  38  *
  39  * <p> The signed object is a "deep copy" (in serialized form) of an
  40  * original object.  Once the copy is made, further manipulation of
  41  * the original object has no side effect on the copy.
  42  *
  43  * <p> The underlying signing algorithm is designated by the Signature
  44  * object passed to the constructor and the {@code verify} method.
  45  * A typical usage for signing is the following:
  46  *
  47  * <pre>{@code
  48  * Signature signingEngine = Signature.getInstance(algorithm,
  49  *                                                 provider);
  50  * SignedObject so = new SignedObject(myobject, signingKey,
  51  *                                    signingParams, signingEngine);
  52  * }</pre>
  53  *
  54  * <p> A typical usage for verification is the following (having
  55  * received SignedObject {@code so}):
  56  *
  57  * <pre>{@code
  58  * Signature verificationEngine =
  59  *     Signature.getInstance(algorithm, provider);
  60  * if (so.verify(verificationKey, verificationParams, verificationEngine))
  61  *     try {
  62  *         Object myobj = so.getObject();
  63  *     } catch (java.lang.ClassNotFoundException e) {};
  64  * }</pre>
  65  *
  66  * <p> Several points are worth noting.  First, there is no need to
  67  * initialize the signing or verification engine, as it will be
  68  * re-initialized inside the constructor and the {@code verify}
  69  * method. Secondly, for verification to succeed, the specified
  70  * public key must be the public key corresponding to the private key
  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.
  74  *
  75  * <p> More importantly, for flexibility reasons, the
  76  * constructor and {@code verify} method allow for
  77  * customized signature engines, which can implement signature
  78  * algorithms that are not installed formally as part of a crypto
  79  * provider.  However, it is crucial that the programmer writing the
  80  * verifier code be aware what {@code Signature} engine is being
  81  * used, as its own implementation of the {@code verify} method
  82  * is invoked to verify a signature.  In other words, a malicious
  83  * {@code Signature} may choose to always return true on
  84  * verification in an attempt to bypass a security check.
  85  *
  86  * <p> The signature algorithm can be, among others, the NIST standard
  87  * DSA, using DSA and SHA-256.  The algorithm is specified using the
  88  * same convention as that for signatures. The DSA algorithm using the
  89  * SHA-256 message digest algorithm can be specified, for example, as
  90  * "SHA256withDSA".  In the case of
  91  * RSA the signing algorithm could be specified as, for example,
  92  * "SHA256withRSA".  The algorithm name must be
  93  * specified, as there is no default.


 118  * @author Li Gong
 119  * @since 1.2
 120  */
 121 
 122 public final class SignedObject implements Serializable {
 123 
 124     private static final long serialVersionUID = 720502720485447167L;
 125 
 126     /*
 127      * The original content is "deep copied" in its serialized format
 128      * and stored in a byte array.  The signature field is also in the
 129      * form of byte array.
 130      */
 131 
 132     private byte[] content;
 133     private byte[] signature;
 134     private String thealgorithm;
 135 
 136     /**
 137      * Constructs a SignedObject from any Serializable object.
 138      * The given object is signed with the given signing key with
 139      * no signature parameters, using the designated signature engine.
 140      *
 141      * @param object the object to be signed.
 142      * @param signingKey the private key for signing.
 143      * @param signingEngine the signature signing engine.
 144      *
 145      * @exception IOException if an error occurs during serialization
 146      * @exception InvalidKeyException if the key is invalid.
 147      * @exception SignatureException if signing fails.
 148      */
 149     public SignedObject(Serializable object, PrivateKey signingKey,
 150                         Signature signingEngine)
 151         throws IOException, InvalidKeyException, SignatureException {
 152         // creating a stream pipe-line, from a to b
 153         ByteArrayOutputStream b = new ByteArrayOutputStream();
 154         ObjectOutput a = new ObjectOutputStream(b);
 155 
 156         // write and flush the object content to byte array
 157         a.writeObject(object);
 158         a.flush();
 159         a.close();
 160         this.content = b.toByteArray();
 161         b.close();
 162 
 163         // now sign the encapsulated object
 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);
 210     }
 211 
 212     /**
 213      * Retrieves the encapsulated object.
 214      * The encapsulated object is de-serialized before it is returned.
 215      *
 216      * @return the encapsulated object.
 217      *
 218      * @exception IOException if an error occurs during de-serialization
 219      * @exception ClassNotFoundException if an error occurs during
 220      * de-serialization
 221      */
 222     public Object getObject()
 223         throws IOException, ClassNotFoundException {

 224         // creating a stream pipe-line, from b to a
 225         ByteArrayInputStream b = new ByteArrayInputStream(this.content);
 226         ObjectInput a = new ObjectInputStream(b);
 227         Object obj = a.readObject();
 228         b.close();
 229         a.close();
 230         return obj;
 231     }
 232 
 233     /**
 234      * Retrieves the signature on the signed object, in the form of a
 235      * byte array.
 236      *
 237      * @return the signature. Returns a new array each time this
 238      * method is called.
 239      */
 240     public byte[] getSignature() {
 241         return this.signature.clone();
 242     }
 243 
 244     /**
 245      * Retrieves the name of the signature algorithm.
 246      *
 247      * @return the signature algorithm name.
 248      */
 249     public String getAlgorithm() {
 250         return this.thealgorithm;
 251     }
 252 
 253     /**
 254      * Verifies that the signature in this SignedObject is the valid
 255      * signature for the object stored inside, with the given
 256      * verification key with no signature parameters, using the designated
 257      * verification engine.
 258      *
 259      * @param verificationKey the public key for verification.
 260      * @param verificationEngine the signature verification engine.
 261      *
 262      * @exception SignatureException if signature verification failed (an
 263      *     exception prevented the signature verification engine from completing
 264      *     normally).
 265      * @exception InvalidKeyException if the verification key is invalid.
 266      *
 267      * @return {@code true} if the signature
 268      * is valid, {@code false} otherwise
 269      */
 270     public boolean verify(PublicKey verificationKey,
 271                           Signature verificationEngine)
 272          throws InvalidKeyException, SignatureException {
 273          try {
 274              return verify(verificationKey, null, verificationEngine);
 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());
 321     }
 322 
 323     /*
 324      * Signs the encapsulated object with the given signing key, using the
 325      * designated signature engine.
 326      *
 327      * @param signingKey the private key for signing.
 328      * @param signingParams the signature parameters for signing.
 329      * @param signingEngine the signature signing engine.
 330      *
 331      * @exception InvalidKeyException if the key is invalid.
 332      * @exception InvalidAlgorithmParameterException if the given signature
 333      * parameters is invalid
 334      * @exception SignatureException if signing fails.
 335      */
 336     private void sign(PrivateKey signingKey,
 337                       AlgorithmParameterSpec signingParams,
 338                       Signature signingEngine)
 339         throws InvalidKeyException, InvalidAlgorithmParameterException,
 340         SignatureException {
 341         // set parameteres before Signature.initSign/initVerify call,
 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();
 354     }
 355 
 356     /**
 357      * readObject is called to restore the state of the SignedObject from
 358      * a stream.
 359      */
 360     private void readObject(java.io.ObjectInputStream s)
 361         throws java.io.IOException, ClassNotFoundException {
 362         java.io.ObjectInputStream.GetField fields = s.readFields();
 363         content = ((byte[])fields.get("content", null)).clone();
 364         signature = ((byte[])fields.get("signature", null)).clone();
 365         thealgorithm = (String)fields.get("thealgorithm", null);
 366     }
 367 }
< prev index next >