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