< prev index next >

src/java.base/share/classes/sun/security/rsa/RSAPSSSignature.java

Print this page

 28 import java.io.IOException;
 29 import java.nio.ByteBuffer;
 30 
 31 import java.security.*;
 32 import java.security.spec.AlgorithmParameterSpec;
 33 import java.security.spec.PSSParameterSpec;
 34 import java.security.spec.MGF1ParameterSpec;
 35 import java.security.interfaces.*;
 36 
 37 import java.util.Arrays;
 38 import java.util.Hashtable;
 39 
 40 import sun.security.util.*;
 41 import sun.security.jca.JCAUtil;
 42 
 43 
 44 /**
 45  * PKCS#1 v2.2 RSASSA-PSS signatures with various message digest algorithms.
 46  * RSASSA-PSS implementation takes the message digest algorithm, MGF algorithm,
 47  * and salt length values through the required signature PSS parameters.
 48  * We support SHA-1, SHA-224, SHA-256, SHA-384, SHA-512, SHA-512/224, and
 49  * SHA-512/256 message digest algorithms and MGF1 mask generation function.
 50  *
 51  * @since   11
 52  */
 53 public class RSAPSSSignature extends SignatureSpi {
 54 
 55     private static final boolean DEBUG = false;
 56 
 57     // utility method for comparing digest algorithms
 58     // NOTE that first argument is assumed to be standard digest name
 59     private boolean isDigestEqual(String stdAlg, String givenAlg) {
 60         if (stdAlg == null || givenAlg == null) return false;
 61 
 62         if (givenAlg.indexOf("-") != -1) {
 63             return stdAlg.equalsIgnoreCase(givenAlg);
 64         } else {
 65             if (stdAlg.equals("SHA-1")) {
 66                 return (givenAlg.equalsIgnoreCase("SHA")
 67                         || givenAlg.equalsIgnoreCase("SHA1"));
 68             } else {
 69                 StringBuilder sb = new StringBuilder(givenAlg);
 70                 // case-insensitive check
 71                 if (givenAlg.regionMatches(true, 0, "SHA", 0, 3)) {
 72                     givenAlg = sb.insert(3, "-").toString();
 73                     return stdAlg.equalsIgnoreCase(givenAlg);
 74                 } else {
 75                     throw new ProviderException("Unsupported digest algorithm "
 76                             + givenAlg);
 77                 }
 78             }
 79         }
 80     }
 81 
 82     private static final byte[] EIGHT_BYTES_OF_ZEROS = new byte[8];
 83 
 84     private static final Hashtable<String, Integer> DIGEST_LENGTHS =
 85         new Hashtable<String, Integer>();
 86     static {
 87         DIGEST_LENGTHS.put("SHA-1", 20);
 88         DIGEST_LENGTHS.put("SHA", 20);
 89         DIGEST_LENGTHS.put("SHA1", 20);
 90         DIGEST_LENGTHS.put("SHA-224", 28);
 91         DIGEST_LENGTHS.put("SHA224", 28);
 92         DIGEST_LENGTHS.put("SHA-256", 32);
 93         DIGEST_LENGTHS.put("SHA256", 32);
 94         DIGEST_LENGTHS.put("SHA-384", 48);
 95         DIGEST_LENGTHS.put("SHA384", 48);
 96         DIGEST_LENGTHS.put("SHA-512", 64);
 97         DIGEST_LENGTHS.put("SHA512", 64);
 98         DIGEST_LENGTHS.put("SHA-512/224", 28);
 99         DIGEST_LENGTHS.put("SHA512/224", 28);
100         DIGEST_LENGTHS.put("SHA-512/256", 32);
101         DIGEST_LENGTHS.put("SHA512/256", 32);
102     }
103 
104     // message digest implementation we use for hashing the data
105     private MessageDigest md;
106     // flag indicating whether the digest is reset
107     private boolean digestReset = true;
108 
109     // private key, if initialized for signing
110     private RSAPrivateKey privKey = null;
111     // public key, if initialized for verifying
112     private RSAPublicKey pubKey = null;
113     // PSS parameters from signatures and keys respectively
114     private PSSParameterSpec sigParams = null; // required for PSS signatures
115 
116     // PRNG used to generate salt bytes if none given
117     private SecureRandom random;
118 
119     /**
120      * Construct a new RSAPSSSignatur with arbitrary digest algorithm
121      */

202                 e.printStackTrace();
203             }
204             return false;
205         }
206     }
207 
208     /**
209      * Validate the specified RSAKey and its associated parameters against
210      * internal signature parameters.
211      */
212     private RSAKey isValid(RSAKey rsaKey) throws InvalidKeyException {
213         try {
214             AlgorithmParameterSpec keyParams = rsaKey.getParams();
215             // validate key parameters
216             if (!isCompatible(rsaKey.getParams(), this.sigParams)) {
217                 throw new InvalidKeyException
218                     ("Key contains incompatible PSS parameter values");
219             }
220             // validate key length
221             if (this.sigParams != null) {
222                 Integer hLen =
223                     DIGEST_LENGTHS.get(this.sigParams.getDigestAlgorithm());
224                 if (hLen == null) {
225                     throw new ProviderException("Unsupported digest algo: " +
226                         this.sigParams.getDigestAlgorithm());









227                 }
228                 checkKeyLength(rsaKey, hLen, this.sigParams.getSaltLength());
229             }
230             return rsaKey;
231         } catch (SignatureException e) {
232             throw new InvalidKeyException(e);
233         }
234     }
235 
236     /**
237      * Validate the specified Signature PSS parameters.
238      */
239     private PSSParameterSpec validateSigParams(AlgorithmParameterSpec p)
240             throws InvalidAlgorithmParameterException {
241         if (p == null) {
242             throw new InvalidAlgorithmParameterException
243                 ("Parameters cannot be null");
244         }
245         if (!(p instanceof PSSParameterSpec)) {
246             throw new InvalidAlgorithmParameterException
247                 ("parameters must be type PSSParameterSpec");
248         }

255         if (key != null) {
256             if (!isCompatible(key.getParams(), params)) {
257                 throw new InvalidAlgorithmParameterException
258                     ("Signature parameters does not match key parameters");
259             }
260         }
261         // now sanity check the parameter values
262         if (!(params.getMGFAlgorithm().equalsIgnoreCase("MGF1"))) {
263             throw new InvalidAlgorithmParameterException("Only supports MGF1");
264 
265         }
266         if (params.getTrailerField() != PSSParameterSpec.TRAILER_FIELD_BC) {
267             throw new InvalidAlgorithmParameterException
268                 ("Only supports TrailerFieldBC(1)");
269 
270         }
271         String digestAlgo = params.getDigestAlgorithm();
272         // check key length again
273         if (key != null) {
274             try {
275                 int hLen = DIGEST_LENGTHS.get(digestAlgo);
276                 checkKeyLength(key, hLen, params.getSaltLength());
277             } catch (SignatureException e) {
278                 throw new InvalidAlgorithmParameterException(e);
279             }
280         }
281         return params;
282     }
283 
284     /**
285      * Ensure the object is initialized with key and parameters and
286      * reset digest
287      */
288     private void ensureInit() throws SignatureException {
289         RSAKey key = (this.privKey == null? this.pubKey : this.privKey);
290         if (key == null) {
291             throw new SignatureException("Missing key");
292         }
293         if (this.sigParams == null) {
294             // Parameters are required for signature verification
295             throw new SignatureException

 28 import java.io.IOException;
 29 import java.nio.ByteBuffer;
 30 
 31 import java.security.*;
 32 import java.security.spec.AlgorithmParameterSpec;
 33 import java.security.spec.PSSParameterSpec;
 34 import java.security.spec.MGF1ParameterSpec;
 35 import java.security.interfaces.*;
 36 
 37 import java.util.Arrays;
 38 import java.util.Hashtable;
 39 
 40 import sun.security.util.*;
 41 import sun.security.jca.JCAUtil;
 42 
 43 
 44 /**
 45  * PKCS#1 v2.2 RSASSA-PSS signatures with various message digest algorithms.
 46  * RSASSA-PSS implementation takes the message digest algorithm, MGF algorithm,
 47  * and salt length values through the required signature PSS parameters.
 48  * We support SHA-1, SHA-2 family and SHA3 family of message digest algorithms,
 49  * and MGF1 mask generation function.
 50  *
 51  * @since   11
 52  */
 53 public class RSAPSSSignature extends SignatureSpi {
 54 
 55     private static final boolean DEBUG = false;
 56 
 57     // utility method for comparing digest algorithms
 58     // NOTE that first argument is assumed to be standard digest name
 59     private boolean isDigestEqual(String stdAlg, String givenAlg) {
 60         if (stdAlg == null || givenAlg == null) return false;
 61 
 62         if (givenAlg.indexOf("-") != -1) {
 63             return stdAlg.equalsIgnoreCase(givenAlg);
 64         } else {
 65             if (stdAlg.equals("SHA-1")) {
 66                 return (givenAlg.equalsIgnoreCase("SHA")
 67                         || givenAlg.equalsIgnoreCase("SHA1"));
 68             } else {
 69                 StringBuilder sb = new StringBuilder(givenAlg);
 70                 // case-insensitive check
 71                 if (givenAlg.regionMatches(true, 0, "SHA", 0, 3)) {
 72                     givenAlg = sb.insert(3, "-").toString();
 73                     return stdAlg.equalsIgnoreCase(givenAlg);
 74                 } else {
 75                     throw new ProviderException("Unsupported digest algorithm "
 76                             + givenAlg);
 77                 }
 78             }
 79         }
 80     }
 81 
 82     private static final byte[] EIGHT_BYTES_OF_ZEROS = new byte[8];
 83 
 84     private static final Hashtable<KnownOIDs, Integer> DIGEST_LENGTHS =
 85         new Hashtable<KnownOIDs, Integer>();
 86     static {
 87         DIGEST_LENGTHS.put(KnownOIDs.SHA_1, 20);
 88         DIGEST_LENGTHS.put(KnownOIDs.SHA_224, 28);
 89         DIGEST_LENGTHS.put(KnownOIDs.SHA_256, 32);
 90         DIGEST_LENGTHS.put(KnownOIDs.SHA_384, 48);
 91         DIGEST_LENGTHS.put(KnownOIDs.SHA_512, 64);
 92         DIGEST_LENGTHS.put(KnownOIDs.SHA_512$224, 28);
 93         DIGEST_LENGTHS.put(KnownOIDs.SHA_512$256, 32);
 94         DIGEST_LENGTHS.put(KnownOIDs.SHA3_224, 28);
 95         DIGEST_LENGTHS.put(KnownOIDs.SHA3_256, 32);
 96         DIGEST_LENGTHS.put(KnownOIDs.SHA3_384, 48);
 97         DIGEST_LENGTHS.put(KnownOIDs.SHA3_512, 64);




 98     }
 99 
100     // message digest implementation we use for hashing the data
101     private MessageDigest md;
102     // flag indicating whether the digest is reset
103     private boolean digestReset = true;
104 
105     // private key, if initialized for signing
106     private RSAPrivateKey privKey = null;
107     // public key, if initialized for verifying
108     private RSAPublicKey pubKey = null;
109     // PSS parameters from signatures and keys respectively
110     private PSSParameterSpec sigParams = null; // required for PSS signatures
111 
112     // PRNG used to generate salt bytes if none given
113     private SecureRandom random;
114 
115     /**
116      * Construct a new RSAPSSSignatur with arbitrary digest algorithm
117      */

198                 e.printStackTrace();
199             }
200             return false;
201         }
202     }
203 
204     /**
205      * Validate the specified RSAKey and its associated parameters against
206      * internal signature parameters.
207      */
208     private RSAKey isValid(RSAKey rsaKey) throws InvalidKeyException {
209         try {
210             AlgorithmParameterSpec keyParams = rsaKey.getParams();
211             // validate key parameters
212             if (!isCompatible(rsaKey.getParams(), this.sigParams)) {
213                 throw new InvalidKeyException
214                     ("Key contains incompatible PSS parameter values");
215             }
216             // validate key length
217             if (this.sigParams != null) {
218                 String digestAlgo = this.sigParams.getDigestAlgorithm();
219                 KnownOIDs ko = KnownOIDs.findMatch(digestAlgo);
220                 if (ko != null) {
221                     Integer hLen = DIGEST_LENGTHS.get(ko);
222                     if (hLen != null) {
223                         checkKeyLength(rsaKey, hLen,
224                                 this.sigParams.getSaltLength());
225                     } else {
226                         throw new ProviderException
227                                 ("Unsupported digest algo: " + digestAlgo);
228                     }
229                 } else {
230                     throw new ProviderException
231                             ("Unrecognized digest algo: " + digestAlgo);
232                 }

233             }
234             return rsaKey;
235         } catch (SignatureException e) {
236             throw new InvalidKeyException(e);
237         }
238     }
239 
240     /**
241      * Validate the specified Signature PSS parameters.
242      */
243     private PSSParameterSpec validateSigParams(AlgorithmParameterSpec p)
244             throws InvalidAlgorithmParameterException {
245         if (p == null) {
246             throw new InvalidAlgorithmParameterException
247                 ("Parameters cannot be null");
248         }
249         if (!(p instanceof PSSParameterSpec)) {
250             throw new InvalidAlgorithmParameterException
251                 ("parameters must be type PSSParameterSpec");
252         }

259         if (key != null) {
260             if (!isCompatible(key.getParams(), params)) {
261                 throw new InvalidAlgorithmParameterException
262                     ("Signature parameters does not match key parameters");
263             }
264         }
265         // now sanity check the parameter values
266         if (!(params.getMGFAlgorithm().equalsIgnoreCase("MGF1"))) {
267             throw new InvalidAlgorithmParameterException("Only supports MGF1");
268 
269         }
270         if (params.getTrailerField() != PSSParameterSpec.TRAILER_FIELD_BC) {
271             throw new InvalidAlgorithmParameterException
272                 ("Only supports TrailerFieldBC(1)");
273 
274         }
275         String digestAlgo = params.getDigestAlgorithm();
276         // check key length again
277         if (key != null) {
278             try {
279                 int hLen = DIGEST_LENGTHS.get(KnownOIDs.findMatch(digestAlgo));
280                 checkKeyLength(key, hLen, params.getSaltLength());
281             } catch (SignatureException e) {
282                 throw new InvalidAlgorithmParameterException(e);
283             }
284         }
285         return params;
286     }
287 
288     /**
289      * Ensure the object is initialized with key and parameters and
290      * reset digest
291      */
292     private void ensureInit() throws SignatureException {
293         RSAKey key = (this.privKey == null? this.pubKey : this.privKey);
294         if (key == null) {
295             throw new SignatureException("Missing key");
296         }
297         if (this.sigParams == null) {
298             // Parameters are required for signature verification
299             throw new SignatureException
< prev index next >