src/java.base/share/classes/sun/security/rsa/RSASignature.java
changeset 47216 71c04702a3d5
parent 43214 3dd7af9b9e05
child 50204 3195a713e24d
child 56542 56aaa6cb3693
equal deleted inserted replaced
47215:4ebc2e2fb97c 47216:71c04702a3d5
       
     1 /*
       
     2  * Copyright (c) 2003, 2016, 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 sun.security.rsa;
       
    27 
       
    28 import java.io.IOException;
       
    29 import java.nio.ByteBuffer;
       
    30 
       
    31 import java.security.*;
       
    32 import java.security.interfaces.*;
       
    33 
       
    34 import sun.security.util.*;
       
    35 import sun.security.x509.AlgorithmId;
       
    36 
       
    37 /**
       
    38  * PKCS#1 RSA signatures with the various message digest algorithms.
       
    39  * This file contains an abstract base class with all the logic plus
       
    40  * a nested static class for each of the message digest algorithms
       
    41  * (see end of the file). We support MD2, MD5, SHA-1, SHA-224, SHA-256,
       
    42  * SHA-384, and SHA-512.
       
    43  *
       
    44  * @since   1.5
       
    45  * @author  Andreas Sterbenz
       
    46  */
       
    47 public abstract class RSASignature extends SignatureSpi {
       
    48 
       
    49     // we sign an ASN.1 SEQUENCE of AlgorithmId and digest
       
    50     // it has the form 30:xx:30:xx:[digestOID]:05:00:04:xx:[digest]
       
    51     // this means the encoded length is (8 + digestOID.length + digest.length)
       
    52     private static final int baseLength = 8;
       
    53 
       
    54     // object identifier for the message digest algorithm used
       
    55     private final ObjectIdentifier digestOID;
       
    56 
       
    57     // length of the encoded signature blob
       
    58     private final int encodedLength;
       
    59 
       
    60     // message digest implementation we use
       
    61     private final MessageDigest md;
       
    62     // flag indicating whether the digest is reset
       
    63     private boolean digestReset;
       
    64 
       
    65     // private key, if initialized for signing
       
    66     private RSAPrivateKey privateKey;
       
    67     // public key, if initialized for verifying
       
    68     private RSAPublicKey publicKey;
       
    69 
       
    70     // padding to use, set when the initSign/initVerify is called
       
    71     private RSAPadding padding;
       
    72 
       
    73     /**
       
    74      * Construct a new RSASignature. Used by subclasses.
       
    75      */
       
    76     RSASignature(String algorithm, ObjectIdentifier digestOID, int oidLength) {
       
    77         this.digestOID = digestOID;
       
    78         try {
       
    79             md = MessageDigest.getInstance(algorithm);
       
    80         } catch (NoSuchAlgorithmException e) {
       
    81             throw new ProviderException(e);
       
    82         }
       
    83         digestReset = true;
       
    84         encodedLength = baseLength + oidLength + md.getDigestLength();
       
    85     }
       
    86 
       
    87     // initialize for verification. See JCA doc
       
    88     protected void engineInitVerify(PublicKey publicKey)
       
    89             throws InvalidKeyException {
       
    90         RSAPublicKey rsaKey = (RSAPublicKey)RSAKeyFactory.toRSAKey(publicKey);
       
    91         this.privateKey = null;
       
    92         this.publicKey = rsaKey;
       
    93         initCommon(rsaKey, null);
       
    94     }
       
    95 
       
    96     // initialize for signing. See JCA doc
       
    97     protected void engineInitSign(PrivateKey privateKey)
       
    98             throws InvalidKeyException {
       
    99         engineInitSign(privateKey, null);
       
   100     }
       
   101 
       
   102     // initialize for signing. See JCA doc
       
   103     protected void engineInitSign(PrivateKey privateKey, SecureRandom random)
       
   104             throws InvalidKeyException {
       
   105         RSAPrivateKey rsaKey =
       
   106             (RSAPrivateKey)RSAKeyFactory.toRSAKey(privateKey);
       
   107         this.privateKey = rsaKey;
       
   108         this.publicKey = null;
       
   109         initCommon(rsaKey, random);
       
   110     }
       
   111 
       
   112     /**
       
   113      * Init code common to sign and verify.
       
   114      */
       
   115     private void initCommon(RSAKey rsaKey, SecureRandom random)
       
   116             throws InvalidKeyException {
       
   117         resetDigest();
       
   118         int keySize = RSACore.getByteLength(rsaKey);
       
   119         try {
       
   120             padding = RSAPadding.getInstance
       
   121                 (RSAPadding.PAD_BLOCKTYPE_1, keySize, random);
       
   122         } catch (InvalidAlgorithmParameterException iape) {
       
   123             throw new InvalidKeyException(iape.getMessage());
       
   124         }
       
   125         int maxDataSize = padding.getMaxDataSize();
       
   126         if (encodedLength > maxDataSize) {
       
   127             throw new InvalidKeyException
       
   128                 ("Key is too short for this signature algorithm");
       
   129         }
       
   130     }
       
   131 
       
   132     /**
       
   133      * Reset the message digest if it is not already reset.
       
   134      */
       
   135     private void resetDigest() {
       
   136         if (digestReset == false) {
       
   137             md.reset();
       
   138             digestReset = true;
       
   139         }
       
   140     }
       
   141 
       
   142     /**
       
   143      * Return the message digest value.
       
   144      */
       
   145     private byte[] getDigestValue() {
       
   146         digestReset = true;
       
   147         return md.digest();
       
   148     }
       
   149 
       
   150     // update the signature with the plaintext data. See JCA doc
       
   151     protected void engineUpdate(byte b) throws SignatureException {
       
   152         md.update(b);
       
   153         digestReset = false;
       
   154     }
       
   155 
       
   156     // update the signature with the plaintext data. See JCA doc
       
   157     protected void engineUpdate(byte[] b, int off, int len)
       
   158             throws SignatureException {
       
   159         md.update(b, off, len);
       
   160         digestReset = false;
       
   161     }
       
   162 
       
   163     // update the signature with the plaintext data. See JCA doc
       
   164     protected void engineUpdate(ByteBuffer b) {
       
   165         md.update(b);
       
   166         digestReset = false;
       
   167     }
       
   168 
       
   169     // sign the data and return the signature. See JCA doc
       
   170     protected byte[] engineSign() throws SignatureException {
       
   171         byte[] digest = getDigestValue();
       
   172         try {
       
   173             byte[] encoded = encodeSignature(digestOID, digest);
       
   174             byte[] padded = padding.pad(encoded);
       
   175             byte[] encrypted = RSACore.rsa(padded, privateKey, true);
       
   176             return encrypted;
       
   177         } catch (GeneralSecurityException e) {
       
   178             throw new SignatureException("Could not sign data", e);
       
   179         } catch (IOException e) {
       
   180             throw new SignatureException("Could not encode data", e);
       
   181         }
       
   182     }
       
   183 
       
   184     // verify the data and return the result. See JCA doc
       
   185     // should be reset to the state after engineInitVerify call.
       
   186     protected boolean engineVerify(byte[] sigBytes) throws SignatureException {
       
   187         try {
       
   188             if (sigBytes.length != RSACore.getByteLength(publicKey)) {
       
   189                 throw new SignatureException("Signature length not correct: got " +
       
   190                     sigBytes.length + " but was expecting " +
       
   191                     RSACore.getByteLength(publicKey));
       
   192             }
       
   193             byte[] digest = getDigestValue();
       
   194             byte[] decrypted = RSACore.rsa(sigBytes, publicKey);
       
   195             byte[] unpadded = padding.unpad(decrypted);
       
   196             byte[] decodedDigest = decodeSignature(digestOID, unpadded);
       
   197             return MessageDigest.isEqual(digest, decodedDigest);
       
   198         } catch (javax.crypto.BadPaddingException e) {
       
   199             // occurs if the app has used the wrong RSA public key
       
   200             // or if sigBytes is invalid
       
   201             // return false rather than propagating the exception for
       
   202             // compatibility/ease of use
       
   203             return false;
       
   204         } catch (IOException e) {
       
   205             throw new SignatureException("Signature encoding error", e);
       
   206         } finally {
       
   207             resetDigest();
       
   208         }
       
   209     }
       
   210 
       
   211     /**
       
   212      * Encode the digest, return the to-be-signed data.
       
   213      * Also used by the PKCS#11 provider.
       
   214      */
       
   215     public static byte[] encodeSignature(ObjectIdentifier oid, byte[] digest)
       
   216             throws IOException {
       
   217         DerOutputStream out = new DerOutputStream();
       
   218         new AlgorithmId(oid).encode(out);
       
   219         out.putOctetString(digest);
       
   220         DerValue result =
       
   221             new DerValue(DerValue.tag_Sequence, out.toByteArray());
       
   222         return result.toByteArray();
       
   223     }
       
   224 
       
   225     /**
       
   226      * Decode the signature data. Verify that the object identifier matches
       
   227      * and return the message digest.
       
   228      */
       
   229     public static byte[] decodeSignature(ObjectIdentifier oid, byte[] sig)
       
   230             throws IOException {
       
   231         // Enforce strict DER checking for signatures
       
   232         DerInputStream in = new DerInputStream(sig, 0, sig.length, false);
       
   233         DerValue[] values = in.getSequence(2);
       
   234         if ((values.length != 2) || (in.available() != 0)) {
       
   235             throw new IOException("SEQUENCE length error");
       
   236         }
       
   237         AlgorithmId algId = AlgorithmId.parse(values[0]);
       
   238         if (algId.getOID().equals(oid) == false) {
       
   239             throw new IOException("ObjectIdentifier mismatch: "
       
   240                 + algId.getOID());
       
   241         }
       
   242         if (algId.getEncodedParams() != null) {
       
   243             throw new IOException("Unexpected AlgorithmId parameters");
       
   244         }
       
   245         byte[] digest = values[1].getOctetString();
       
   246         return digest;
       
   247     }
       
   248 
       
   249     // set parameter, not supported. See JCA doc
       
   250     @Deprecated
       
   251     protected void engineSetParameter(String param, Object value)
       
   252             throws InvalidParameterException {
       
   253         throw new UnsupportedOperationException("setParameter() not supported");
       
   254     }
       
   255 
       
   256     // get parameter, not supported. See JCA doc
       
   257     @Deprecated
       
   258     protected Object engineGetParameter(String param)
       
   259             throws InvalidParameterException {
       
   260         throw new UnsupportedOperationException("getParameter() not supported");
       
   261     }
       
   262 
       
   263     // Nested class for MD2withRSA signatures
       
   264     public static final class MD2withRSA extends RSASignature {
       
   265         public MD2withRSA() {
       
   266             super("MD2", AlgorithmId.MD2_oid, 10);
       
   267         }
       
   268     }
       
   269 
       
   270     // Nested class for MD5withRSA signatures
       
   271     public static final class MD5withRSA extends RSASignature {
       
   272         public MD5withRSA() {
       
   273             super("MD5", AlgorithmId.MD5_oid, 10);
       
   274         }
       
   275     }
       
   276 
       
   277     // Nested class for SHA1withRSA signatures
       
   278     public static final class SHA1withRSA extends RSASignature {
       
   279         public SHA1withRSA() {
       
   280             super("SHA-1", AlgorithmId.SHA_oid, 7);
       
   281         }
       
   282     }
       
   283 
       
   284     // Nested class for SHA224withRSA signatures
       
   285     public static final class SHA224withRSA extends RSASignature {
       
   286         public SHA224withRSA() {
       
   287             super("SHA-224", AlgorithmId.SHA224_oid, 11);
       
   288         }
       
   289     }
       
   290 
       
   291     // Nested class for SHA256withRSA signatures
       
   292     public static final class SHA256withRSA extends RSASignature {
       
   293         public SHA256withRSA() {
       
   294             super("SHA-256", AlgorithmId.SHA256_oid, 11);
       
   295         }
       
   296     }
       
   297 
       
   298     // Nested class for SHA384withRSA signatures
       
   299     public static final class SHA384withRSA extends RSASignature {
       
   300         public SHA384withRSA() {
       
   301             super("SHA-384", AlgorithmId.SHA384_oid, 11);
       
   302         }
       
   303     }
       
   304 
       
   305     // Nested class for SHA512withRSA signatures
       
   306     public static final class SHA512withRSA extends RSASignature {
       
   307         public SHA512withRSA() {
       
   308             super("SHA-512", AlgorithmId.SHA512_oid, 11);
       
   309         }
       
   310     }
       
   311 
       
   312 }