1package org.bouncycastle.jcajce.provider.asymmetric.dsa; 2 3import java.io.IOException; 4import java.math.BigInteger; 5import java.security.InvalidKeyException; 6import java.security.PrivateKey; 7import java.security.PublicKey; 8import java.security.SecureRandom; 9import java.security.SignatureException; 10import java.security.SignatureSpi; 11import java.security.spec.AlgorithmParameterSpec; 12 13import org.bouncycastle.asn1.ASN1Encoding; 14import org.bouncycastle.asn1.ASN1Integer; 15import org.bouncycastle.asn1.ASN1Primitive; 16import org.bouncycastle.asn1.ASN1Sequence; 17import org.bouncycastle.asn1.DERSequence; 18import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; 19import org.bouncycastle.asn1.x509.X509ObjectIdentifiers; 20import org.bouncycastle.crypto.CipherParameters; 21import org.bouncycastle.crypto.DSA; 22import org.bouncycastle.crypto.Digest; 23import org.bouncycastle.crypto.digests.NullDigest; 24// Android-added: Check DSA keys when generated 25import org.bouncycastle.crypto.params.DSAKeyParameters; 26import org.bouncycastle.crypto.params.DSAParameters; 27import org.bouncycastle.crypto.params.ParametersWithRandom; 28// Android-removed: Unsupported algorithm 29// import org.bouncycastle.crypto.signers.HMacDSAKCalculator; 30// Android-changed: Use Android digests 31// import org.bouncycastle.crypto.util.DigestFactory; 32import org.bouncycastle.crypto.digests.AndroidDigestFactory; 33import org.bouncycastle.util.Arrays; 34 35public class DSASigner 36 extends SignatureSpi 37 implements PKCSObjectIdentifiers, X509ObjectIdentifiers 38{ 39 private Digest digest; 40 private DSA signer; 41 private SecureRandom random; 42 43 protected DSASigner( 44 Digest digest, 45 DSA signer) 46 { 47 this.digest = digest; 48 this.signer = signer; 49 } 50 51 protected void engineInitVerify( 52 PublicKey publicKey) 53 throws InvalidKeyException 54 { 55 CipherParameters param = DSAUtil.generatePublicKeyParameter(publicKey); 56 57 digest.reset(); 58 signer.init(false, param); 59 } 60 61 protected void engineInitSign( 62 PrivateKey privateKey, 63 SecureRandom random) 64 throws InvalidKeyException 65 { 66 this.random = random; 67 engineInitSign(privateKey); 68 } 69 70 protected void engineInitSign( 71 PrivateKey privateKey) 72 throws InvalidKeyException 73 { 74 CipherParameters param = DSAUtil.generatePrivateKeyParameter(privateKey); 75 76 // Android-added: Check DSA keys when generated 77 DSAParameters dsaParam = ((DSAKeyParameters) param).getParameters(); 78 checkKey(dsaParam); 79 80 if (random != null) 81 { 82 param = new ParametersWithRandom(param, random); 83 } 84 85 digest.reset(); 86 signer.init(true, param); 87 } 88 89 protected void engineUpdate( 90 byte b) 91 throws SignatureException 92 { 93 digest.update(b); 94 } 95 96 protected void engineUpdate( 97 byte[] b, 98 int off, 99 int len) 100 throws SignatureException 101 { 102 digest.update(b, off, len); 103 } 104 105 protected byte[] engineSign() 106 throws SignatureException 107 { 108 byte[] hash = new byte[digest.getDigestSize()]; 109 110 digest.doFinal(hash, 0); 111 112 try 113 { 114 BigInteger[] sig = signer.generateSignature(hash); 115 116 return derEncode(sig[0], sig[1]); 117 } 118 catch (Exception e) 119 { 120 throw new SignatureException(e.toString()); 121 } 122 } 123 124 protected boolean engineVerify( 125 byte[] sigBytes) 126 throws SignatureException 127 { 128 byte[] hash = new byte[digest.getDigestSize()]; 129 130 digest.doFinal(hash, 0); 131 132 BigInteger[] sig; 133 134 try 135 { 136 sig = derDecode(sigBytes); 137 } 138 catch (Exception e) 139 { 140 throw new SignatureException("error decoding signature bytes."); 141 } 142 143 return signer.verifySignature(hash, sig[0], sig[1]); 144 } 145 146 protected void engineSetParameter( 147 AlgorithmParameterSpec params) 148 { 149 throw new UnsupportedOperationException("engineSetParameter unsupported"); 150 } 151 152 // BEGIN Android-added: Check DSA keys when generated 153 protected void checkKey(DSAParameters params) throws InvalidKeyException { 154 int valueL = params.getP().bitLength(); 155 int valueN = params.getQ().bitLength(); 156 int digestSize = digest.getDigestSize(); 157 158 // The checks are consistent with DSAParametersGenerator's init method. 159 if ((valueL < 1024 || valueL > 3072) || valueL % 1024 != 0) { 160 throw new InvalidKeyException("valueL values must be between 1024 and 3072 and a multiple of 1024"); 161 } else if (valueL == 1024 && valueN != 160) { 162 throw new InvalidKeyException("valueN must be 160 for valueL = 1024"); 163 } else if (valueL == 2048 && (valueN != 224 && valueN != 256)) { 164 throw new InvalidKeyException("valueN must be 224 or 256 for valueL = 2048"); 165 } else if (valueL == 3072 && valueN != 256) { 166 throw new InvalidKeyException("valueN must be 256 for valueL = 3072"); 167 } 168 if (!(digest instanceof NullDigest) && valueN > digestSize * 8) { 169 throw new InvalidKeyException("Key is too strong for this signature algorithm"); 170 } 171 } 172 173 // END Android-added: Check DSA keys when generated 174 /** 175 * @deprecated replaced with <a href = "#engineSetParameter(java.security.spec.AlgorithmParameterSpec)"> 176 */ 177 protected void engineSetParameter( 178 String param, 179 Object value) 180 { 181 throw new UnsupportedOperationException("engineSetParameter unsupported"); 182 } 183 184 /** 185 * @deprecated 186 */ 187 protected Object engineGetParameter( 188 String param) 189 { 190 throw new UnsupportedOperationException("engineSetParameter unsupported"); 191 } 192 193 private byte[] derEncode( 194 BigInteger r, 195 BigInteger s) 196 throws IOException 197 { 198 ASN1Integer[] rs = new ASN1Integer[]{ new ASN1Integer(r), new ASN1Integer(s) }; 199 return new DERSequence(rs).getEncoded(ASN1Encoding.DER); 200 } 201 202 private BigInteger[] derDecode( 203 byte[] encoding) 204 throws IOException 205 { 206 ASN1Sequence s = (ASN1Sequence)ASN1Primitive.fromByteArray(encoding); 207 if (s.size() != 2) 208 { 209 throw new IOException("malformed signature"); 210 } 211 if (!Arrays.areEqual(encoding, s.getEncoded(ASN1Encoding.DER))) 212 { 213 throw new IOException("malformed signature"); 214 } 215 216 return new BigInteger[]{ 217 ((ASN1Integer)s.getObjectAt(0)).getValue(), 218 ((ASN1Integer)s.getObjectAt(1)).getValue() 219 }; 220 } 221 222 static public class stdDSA 223 extends DSASigner 224 { 225 public stdDSA() 226 { 227 // Android-changed: Use Android digests 228 // super(DigestFactory.createSHA1(), new org.bouncycastle.crypto.signers.DSASigner()); 229 super(AndroidDigestFactory.getSHA1(), new org.bouncycastle.crypto.signers.DSASigner()); 230 } 231 } 232 233 // BEGIN Android-removed: Unsupported algorithm 234 /* 235 static public class detDSA 236 extends DSASigner 237 { 238 public detDSA() 239 { 240 super(DigestFactory.createSHA1(), new org.bouncycastle.crypto.signers.DSASigner(new HMacDSAKCalculator(DigestFactory.createSHA1()))); 241 } 242 } 243 */ 244 // END Android-removed: Unsupported algorithm 245 246 static public class dsa224 247 extends DSASigner 248 { 249 public dsa224() 250 { 251 // Android-changed: Use Android digests 252 // super(DigestFactory.createSHA224(), new org.bouncycastle.crypto.signers.DSASigner()); 253 super(AndroidDigestFactory.getSHA224(), new org.bouncycastle.crypto.signers.DSASigner()); 254 } 255 } 256 257 // BEGIN Android-removed: Unsupported algorithm 258 /* 259 static public class detDSA224 260 extends DSASigner 261 { 262 public detDSA224() 263 { 264 super(DigestFactory.createSHA224(), new org.bouncycastle.crypto.signers.DSASigner(new HMacDSAKCalculator(DigestFactory.createSHA224()))); 265 } 266 } 267 */ 268 // END Android-removed: Unsupported algorithm 269 270 static public class dsa256 271 extends DSASigner 272 { 273 public dsa256() 274 { 275 // Android-changed: Use Android digests 276 // super(DigestFactory.createSHA256(), new org.bouncycastle.crypto.signers.DSASigner()); 277 super(AndroidDigestFactory.getSHA256(), new org.bouncycastle.crypto.signers.DSASigner()); 278 } 279 } 280 281 // BEGIN Android-removed: Unsupported algorithms 282 /* 283 static public class detDSA256 284 extends DSASigner 285 { 286 public detDSA256() 287 { 288 super(DigestFactory.createSHA256(), new org.bouncycastle.crypto.signers.DSASigner(new HMacDSAKCalculator(DigestFactory.createSHA256()))); 289 } 290 } 291 292 static public class dsa384 293 extends DSASigner 294 { 295 public dsa384() 296 { 297 super(DigestFactory.createSHA384(), new org.bouncycastle.crypto.signers.DSASigner()); 298 } 299 } 300 301 static public class detDSA384 302 extends DSASigner 303 { 304 public detDSA384() 305 { 306 super(DigestFactory.createSHA384(), new org.bouncycastle.crypto.signers.DSASigner(new HMacDSAKCalculator(DigestFactory.createSHA384()))); 307 } 308 } 309 310 static public class dsa512 311 extends DSASigner 312 { 313 public dsa512() 314 { 315 super(DigestFactory.createSHA512(), new org.bouncycastle.crypto.signers.DSASigner()); 316 } 317 } 318 319 static public class detDSA512 320 extends DSASigner 321 { 322 public detDSA512() 323 { 324 super(DigestFactory.createSHA512(), new org.bouncycastle.crypto.signers.DSASigner(new HMacDSAKCalculator(DigestFactory.createSHA512()))); 325 } 326 } 327 328 static public class dsaSha3_224 329 extends DSASigner 330 { 331 public dsaSha3_224() 332 { 333 super(DigestFactory.createSHA3_224(), new org.bouncycastle.crypto.signers.DSASigner()); 334 } 335 } 336 337 static public class detDSASha3_224 338 extends DSASigner 339 { 340 public detDSASha3_224() 341 { 342 super(DigestFactory.createSHA3_224(), new org.bouncycastle.crypto.signers.DSASigner(new HMacDSAKCalculator(DigestFactory.createSHA3_224()))); 343 } 344 } 345 346 static public class dsaSha3_256 347 extends DSASigner 348 { 349 public dsaSha3_256() 350 { 351 super(DigestFactory.createSHA3_256(), new org.bouncycastle.crypto.signers.DSASigner()); 352 } 353 } 354 355 static public class detDSASha3_256 356 extends DSASigner 357 { 358 public detDSASha3_256() 359 { 360 super(DigestFactory.createSHA3_256(), new org.bouncycastle.crypto.signers.DSASigner(new HMacDSAKCalculator(DigestFactory.createSHA3_256()))); 361 } 362 } 363 364 static public class dsaSha3_384 365 extends DSASigner 366 { 367 public dsaSha3_384() 368 { 369 super(DigestFactory.createSHA3_384(), new org.bouncycastle.crypto.signers.DSASigner()); 370 } 371 } 372 373 static public class detDSASha3_384 374 extends DSASigner 375 { 376 public detDSASha3_384() 377 { 378 super(DigestFactory.createSHA3_384(), new org.bouncycastle.crypto.signers.DSASigner(new HMacDSAKCalculator(DigestFactory.createSHA3_384()))); 379 } 380 } 381 382 static public class dsaSha3_512 383 extends DSASigner 384 { 385 public dsaSha3_512() 386 { 387 super(DigestFactory.createSHA3_512(), new org.bouncycastle.crypto.signers.DSASigner()); 388 } 389 } 390 391 static public class detDSASha3_512 392 extends DSASigner 393 { 394 public detDSASha3_512() 395 { 396 super(DigestFactory.createSHA3_512(), new org.bouncycastle.crypto.signers.DSASigner(new HMacDSAKCalculator(DigestFactory.createSHA3_512()))); 397 } 398 } 399 */ 400 // END Android-removed: Unsupported algorithms 401 402 static public class noneDSA 403 extends DSASigner 404 { 405 public noneDSA() 406 { 407 super(new NullDigest(), new org.bouncycastle.crypto.signers.DSASigner()); 408 } 409 } 410} 411