• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package org.bouncycastle.jce.provider;
2 
3 import java.io.IOException;
4 import java.security.AlgorithmParameters;
5 import java.security.InvalidKeyException;
6 import java.security.PrivateKey;
7 import java.security.PublicKey;
8 import java.security.SignatureException;
9 import java.security.SignatureSpi;
10 import java.security.interfaces.RSAPrivateKey;
11 import java.security.interfaces.RSAPublicKey;
12 import java.security.spec.AlgorithmParameterSpec;
13 
14 import org.bouncycastle.asn1.ASN1Encodable;
15 import org.bouncycastle.asn1.DERNull;
16 import org.bouncycastle.asn1.DERObjectIdentifier;
17 import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
18 import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
19 import org.bouncycastle.asn1.teletrust.TeleTrusTObjectIdentifiers;
20 import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
21 import org.bouncycastle.asn1.x509.DigestInfo;
22 import org.bouncycastle.asn1.x509.X509ObjectIdentifiers;
23 import org.bouncycastle.crypto.AsymmetricBlockCipher;
24 import org.bouncycastle.crypto.CipherParameters;
25 import org.bouncycastle.crypto.Digest;
26 // BEGIN android-removed
27 // import org.bouncycastle.crypto.digests.MD2Digest;
28 // import org.bouncycastle.crypto.digests.MD4Digest;
29 // END android-removed
30 import org.bouncycastle.crypto.digests.MD5Digest;
31 // BEGIN android-removed
32 // import org.bouncycastle.crypto.digests.RIPEMD128Digest;
33 // import org.bouncycastle.crypto.digests.RIPEMD160Digest;
34 // import org.bouncycastle.crypto.digests.RIPEMD256Digest;
35 // END android-removed
36 import org.bouncycastle.crypto.digests.SHA1Digest;
37 // BEGIN android-removed
38 // import org.bouncycastle.crypto.digests.SHA224Digest;
39 // END android-removed
40 import org.bouncycastle.crypto.digests.SHA256Digest;
41 import org.bouncycastle.crypto.digests.SHA384Digest;
42 import org.bouncycastle.crypto.digests.SHA512Digest;
43 import org.bouncycastle.crypto.encodings.PKCS1Encoding;
44 import org.bouncycastle.crypto.engines.RSABlindedEngine;
45 import org.bouncycastle.jce.provider.util.NullDigest;
46 
47 public class JDKDigestSignature
48     extends SignatureSpi
49 {
50     private Digest                  digest;
51     private AsymmetricBlockCipher   cipher;
52     private AlgorithmIdentifier     algId;
53 
54     // care - this constructor is actually used by outside organisations
JDKDigestSignature( Digest digest, AsymmetricBlockCipher cipher)55     protected JDKDigestSignature(
56         Digest                  digest,
57         AsymmetricBlockCipher   cipher)
58     {
59         this.digest = digest;
60         this.cipher = cipher;
61         this.algId = null;
62     }
63 
64     // care - this constructor is actually used by outside organisations
JDKDigestSignature( DERObjectIdentifier objId, Digest digest, AsymmetricBlockCipher cipher)65     protected JDKDigestSignature(
66         DERObjectIdentifier     objId,
67         Digest                  digest,
68         AsymmetricBlockCipher   cipher)
69     {
70         this.digest = digest;
71         this.cipher = cipher;
72         this.algId = new AlgorithmIdentifier(objId, DERNull.INSTANCE);
73     }
74 
engineInitVerify( PublicKey publicKey)75     protected void engineInitVerify(
76         PublicKey   publicKey)
77         throws InvalidKeyException
78     {
79         if (!(publicKey instanceof RSAPublicKey))
80         {
81             throw new InvalidKeyException("Supplied key (" + getType(publicKey) + ") is not a RSAPublicKey instance");
82         }
83 
84         CipherParameters    param = RSAUtil.generatePublicKeyParameter((RSAPublicKey)publicKey);
85 
86         digest.reset();
87         cipher.init(false, param);
88     }
89 
engineInitSign( PrivateKey privateKey)90     protected void engineInitSign(
91         PrivateKey  privateKey)
92         throws InvalidKeyException
93     {
94         if (!(privateKey instanceof RSAPrivateKey))
95         {
96             throw new InvalidKeyException("Supplied key (" + getType(privateKey) + ") is not a RSAPrivateKey instance");
97         }
98 
99         CipherParameters    param = RSAUtil.generatePrivateKeyParameter((RSAPrivateKey)privateKey);
100 
101         digest.reset();
102 
103         cipher.init(true, param);
104     }
105 
getType( Object o)106     private String getType(
107         Object o)
108     {
109         if (o == null)
110         {
111             return null;
112         }
113 
114         return o.getClass().getName();
115     }
116 
engineUpdate( byte b)117     protected void engineUpdate(
118         byte    b)
119         throws SignatureException
120     {
121         digest.update(b);
122     }
123 
engineUpdate( byte[] b, int off, int len)124     protected void engineUpdate(
125         byte[]  b,
126         int     off,
127         int     len)
128         throws SignatureException
129     {
130         digest.update(b, off, len);
131     }
132 
engineSign()133     protected byte[] engineSign()
134         throws SignatureException
135     {
136         byte[]  hash = new byte[digest.getDigestSize()];
137 
138         digest.doFinal(hash, 0);
139 
140         try
141         {
142             byte[]  bytes = derEncode(hash);
143 
144             return cipher.processBlock(bytes, 0, bytes.length);
145         }
146         catch (ArrayIndexOutOfBoundsException e)
147         {
148             throw new SignatureException("key too small for signature type");
149         }
150         catch (Exception e)
151         {
152             throw new SignatureException(e.toString());
153         }
154     }
155 
engineVerify( byte[] sigBytes)156     protected boolean engineVerify(
157         byte[]  sigBytes)
158         throws SignatureException
159     {
160         byte[]  hash = new byte[digest.getDigestSize()];
161 
162         digest.doFinal(hash, 0);
163 
164         byte[]      sig;
165         byte[]      expected;
166 
167         try
168         {
169             sig = cipher.processBlock(sigBytes, 0, sigBytes.length);
170 
171             expected = derEncode(hash);
172         }
173         catch (Exception e)
174         {
175             return false;
176         }
177 
178         if (sig.length == expected.length)
179         {
180             for (int i = 0; i < sig.length; i++)
181             {
182                 if (sig[i] != expected[i])
183                 {
184                     return false;
185                 }
186             }
187         }
188         else if (expected.length == sig.length - 2)  // NULL left out
189         {
190             int sigOffset = sig.length - hash.length - 2;
191             int expectedOffset = expected.length - hash.length - 2;
192 
193             sig[1] -= 2;      // adjust lengths
194             sig[3] -= 2;
195 
196             for (int i = 0; i < hash.length; i++)
197             {
198                 if (sig[sigOffset + i] != expected[expectedOffset + i])  // check hash
199                 {
200                     return false;
201                 }
202             }
203 
204             for (int i = 0; i < expectedOffset; i++)
205             {
206                 if (sig[i] != expected[i])  // check header less NULL
207                 {
208                     return false;
209                 }
210             }
211         }
212         else
213         {
214             return false;
215         }
216 
217         return true;
218     }
219 
engineSetParameter( AlgorithmParameterSpec params)220     protected void engineSetParameter(
221         AlgorithmParameterSpec params)
222     {
223         throw new UnsupportedOperationException("engineSetParameter unsupported");
224     }
225 
226     /**
227      * @deprecated replaced with <a href = "#engineSetParameter(java.security.spec.AlgorithmParameterSpec)">
228      */
engineSetParameter( String param, Object value)229     protected void engineSetParameter(
230         String  param,
231         Object  value)
232     {
233         throw new UnsupportedOperationException("engineSetParameter unsupported");
234     }
235 
236     /**
237      * @deprecated
238      */
engineGetParameter( String param)239     protected Object engineGetParameter(
240         String      param)
241     {
242         return null;
243     }
244 
engineGetParameters()245     protected AlgorithmParameters engineGetParameters()
246     {
247         return null;
248     }
249 
derEncode( byte[] hash)250     private byte[] derEncode(
251         byte[]  hash)
252         throws IOException
253     {
254         if (algId == null)
255         {
256             // For raw RSA, the DigestInfo must be prepared externally
257             return hash;
258         }
259 
260         DigestInfo              dInfo = new DigestInfo(algId, hash);
261 
262         return dInfo.getEncoded(ASN1Encodable.DER);
263     }
264 
265     static public class SHA1WithRSAEncryption
266         extends JDKDigestSignature
267     {
SHA1WithRSAEncryption()268         public SHA1WithRSAEncryption()
269         {
270             super(X509ObjectIdentifiers.id_SHA1, new SHA1Digest(), new PKCS1Encoding(new RSABlindedEngine()));
271         }
272     }
273 
274     // BEGIN android-removed
275     // static public class SHA224WithRSAEncryption
276     //     extends JDKDigestSignature
277     // {
278     //     public SHA224WithRSAEncryption()
279     //     {
280     //         super(NISTObjectIdentifiers.id_sha224, new SHA224Digest(), new PKCS1Encoding(new RSABlindedEngine()));
281     //     }
282     // }
283     // END android-removed
284 
285     static public class SHA256WithRSAEncryption
286         extends JDKDigestSignature
287     {
SHA256WithRSAEncryption()288         public SHA256WithRSAEncryption()
289         {
290             super(NISTObjectIdentifiers.id_sha256, new SHA256Digest(), new PKCS1Encoding(new RSABlindedEngine()));
291         }
292     }
293 
294     static public class SHA384WithRSAEncryption
295         extends JDKDigestSignature
296     {
SHA384WithRSAEncryption()297         public SHA384WithRSAEncryption()
298         {
299             super(NISTObjectIdentifiers.id_sha384, new SHA384Digest(), new PKCS1Encoding(new RSABlindedEngine()));
300         }
301     }
302 
303     static public class SHA512WithRSAEncryption
304         extends JDKDigestSignature
305     {
SHA512WithRSAEncryption()306         public SHA512WithRSAEncryption()
307         {
308             super(NISTObjectIdentifiers.id_sha512, new SHA512Digest(), new PKCS1Encoding(new RSABlindedEngine()));
309         }
310     }
311 
312     // BEGIN android-removed
313     // static public class MD2WithRSAEncryption
314     //     extends JDKDigestSignature
315     // {
316     //     public MD2WithRSAEncryption()
317     //     {
318     //         super(PKCSObjectIdentifiers.md2, new MD2Digest(), new PKCS1Encoding(new RSABlindedEngine()));
319     //     }
320     // }
321     //
322     // static public class MD4WithRSAEncryption
323     //     extends JDKDigestSignature
324     // {
325     //     public MD4WithRSAEncryption()
326     //     {
327     //         super(PKCSObjectIdentifiers.md4, new MD4Digest(), new PKCS1Encoding(new RSABlindedEngine()));
328     //     }
329     // }
330     // END android-removed
331 
332     static public class MD5WithRSAEncryption
333         extends JDKDigestSignature
334     {
MD5WithRSAEncryption()335         public MD5WithRSAEncryption()
336         {
337             super(PKCSObjectIdentifiers.md5, new MD5Digest(), new PKCS1Encoding(new RSABlindedEngine()));
338         }
339     }
340 
341     // BEGIN android-removed
342     // static public class RIPEMD160WithRSAEncryption
343     //     extends JDKDigestSignature
344     // {
345     //     public RIPEMD160WithRSAEncryption()
346     //     {
347     //         super(TeleTrusTObjectIdentifiers.ripemd160, new RIPEMD160Digest(), new PKCS1Encoding(new RSABlindedEngine()));
348     //     }
349     // }
350     //
351     // static public class RIPEMD128WithRSAEncryption
352     //     extends JDKDigestSignature
353     // {
354     //     public RIPEMD128WithRSAEncryption()
355     //     {
356     //         super(TeleTrusTObjectIdentifiers.ripemd128, new RIPEMD128Digest(), new PKCS1Encoding(new RSABlindedEngine()));
357     //     }
358     // }
359     //
360     // static public class RIPEMD256WithRSAEncryption
361     //     extends JDKDigestSignature
362     // {
363     //     public RIPEMD256WithRSAEncryption()
364     //     {
365     //         super(TeleTrusTObjectIdentifiers.ripemd256, new RIPEMD256Digest(), new PKCS1Encoding(new RSABlindedEngine()));
366     //     }
367     // }
368     //
369     // static public class noneRSA
370     //     extends JDKDigestSignature
371     // {
372     //     public noneRSA()
373     //     {
374     //         super(new NullDigest(), new PKCS1Encoding(new RSABlindedEngine()));
375     //     }
376     // }
377     // END android-removed
378 }
379