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