DSA.java revision 15134:714224061029
1/* 2 * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26package sun.security.provider; 27 28import java.io.*; 29import java.util.*; 30import java.math.BigInteger; 31import java.nio.ByteBuffer; 32 33import java.security.*; 34import java.security.SecureRandom; 35import java.security.interfaces.*; 36 37import sun.security.util.Debug; 38import sun.security.util.DerValue; 39import sun.security.util.DerInputStream; 40import sun.security.util.DerOutputStream; 41import sun.security.jca.JCAUtil; 42 43/** 44 * The Digital Signature Standard (using the Digital Signature 45 * Algorithm), as described in fips186-3 of the National Instute of 46 * Standards and Technology (NIST), using SHA digest algorithms 47 * from FIPS180-3. 48 * 49 * This file contains both the signature implementation for the 50 * commonly used SHA1withDSA (DSS), SHA224withDSA, SHA256withDSA, 51 * as well as RawDSA, used by TLS among others. RawDSA expects 52 * the 20 byte SHA-1 digest as input via update rather than the 53 * original data like other signature implementations. 54 * 55 * @author Benjamin Renaud 56 * 57 * @since 1.1 58 * 59 * @see DSAPublicKey 60 * @see DSAPrivateKey 61 */ 62abstract class DSA extends SignatureSpi { 63 64 /* Are we debugging? */ 65 private static final boolean debug = false; 66 67 /* The parameter object */ 68 private DSAParams params; 69 70 /* algorithm parameters */ 71 private BigInteger presetP, presetQ, presetG; 72 73 /* The public key, if any */ 74 private BigInteger presetY; 75 76 /* The private key, if any */ 77 private BigInteger presetX; 78 79 /* The RNG used to output a seed for generating k */ 80 private SecureRandom signingRandom; 81 82 /* The message digest object used */ 83 private final MessageDigest md; 84 85 /* The format. true for the IEEE P1363 format. false (default) for ASN.1 */ 86 private final boolean p1363Format; 87 88 /** 89 * Construct a blank DSA object. It must be 90 * initialized before being usable for signing or verifying. 91 */ 92 DSA(MessageDigest md) { 93 this(md, false); 94 } 95 96 /** 97 * Construct a blank DSA object that will use the specified 98 * signature format. {@code p1363Format} should be {@code true} to 99 * use the IEEE P1363 format. If {@code p1363Format} is {@code false}, 100 * the DER-encoded ASN.1 format will used. The DSA object must be 101 * initialized before being usable for signing or verifying. 102 */ 103 DSA(MessageDigest md, boolean p1363Format) { 104 super(); 105 this.md = md; 106 this.p1363Format = p1363Format; 107 } 108 109 private static void checkKey(DSAParams params, int digestLen, String mdAlgo) 110 throws InvalidKeyException { 111 // FIPS186-3 states in sec4.2 that a hash function which provides 112 // a lower security strength than the (L, N) pair ordinarily should 113 // not be used. 114 int valueN = params.getQ().bitLength(); 115 if (valueN > digestLen) { 116 throw new InvalidKeyException("The security strength of " + 117 mdAlgo + " digest algorithm is not sufficient for this key size"); 118 } 119 } 120 121 /** 122 * Initialize the DSA object with a DSA private key. 123 * 124 * @param privateKey the DSA private key 125 * 126 * @exception InvalidKeyException if the key is not a valid DSA private 127 * key. 128 */ 129 protected void engineInitSign(PrivateKey privateKey) 130 throws InvalidKeyException { 131 if (!(privateKey instanceof java.security.interfaces.DSAPrivateKey)) { 132 throw new InvalidKeyException("not a DSA private key: " + 133 privateKey); 134 } 135 136 java.security.interfaces.DSAPrivateKey priv = 137 (java.security.interfaces.DSAPrivateKey)privateKey; 138 139 // check for algorithm specific constraints before doing initialization 140 DSAParams params = priv.getParams(); 141 if (params == null) { 142 throw new InvalidKeyException("DSA private key lacks parameters"); 143 } 144 145 // check key size against hash output size for signing 146 // skip this check for verification to minimize impact on existing apps 147 if (md.getAlgorithm() != "NullDigest20") { 148 checkKey(params, md.getDigestLength()*8, md.getAlgorithm()); 149 } 150 151 this.params = params; 152 this.presetX = priv.getX(); 153 this.presetY = null; 154 this.presetP = params.getP(); 155 this.presetQ = params.getQ(); 156 this.presetG = params.getG(); 157 this.md.reset(); 158 } 159 /** 160 * Initialize the DSA object with a DSA public key. 161 * 162 * @param publicKey the DSA public key. 163 * 164 * @exception InvalidKeyException if the key is not a valid DSA public 165 * key. 166 */ 167 protected void engineInitVerify(PublicKey publicKey) 168 throws InvalidKeyException { 169 if (!(publicKey instanceof java.security.interfaces.DSAPublicKey)) { 170 throw new InvalidKeyException("not a DSA public key: " + 171 publicKey); 172 } 173 java.security.interfaces.DSAPublicKey pub = 174 (java.security.interfaces.DSAPublicKey)publicKey; 175 176 // check for algorithm specific constraints before doing initialization 177 DSAParams params = pub.getParams(); 178 if (params == null) { 179 throw new InvalidKeyException("DSA public key lacks parameters"); 180 } 181 this.params = params; 182 this.presetY = pub.getY(); 183 this.presetX = null; 184 this.presetP = params.getP(); 185 this.presetQ = params.getQ(); 186 this.presetG = params.getG(); 187 this.md.reset(); 188 } 189 190 /** 191 * Update a byte to be signed or verified. 192 */ 193 protected void engineUpdate(byte b) { 194 md.update(b); 195 } 196 197 /** 198 * Update an array of bytes to be signed or verified. 199 */ 200 protected void engineUpdate(byte[] data, int off, int len) { 201 md.update(data, off, len); 202 } 203 204 protected void engineUpdate(ByteBuffer b) { 205 md.update(b); 206 } 207 208 209 /** 210 * Sign all the data thus far updated. The signature format is 211 * determined by {@code p1363Format}. If {@code p1363Format} is 212 * {@code false} (the default), then the signature is formatted 213 * according to the Canonical Encoding Rules, returned as a DER 214 * sequence of Integers, r and s. If {@code p1363Format} is 215 * {@code false}, the signature is returned in the IEEE P1363 216 * format, which is the concatenation or r and s. 217 * 218 * @return a signature block formatted according to the format 219 * indicated by {@code p1363Format} 220 * 221 * @exception SignatureException if the signature object was not 222 * properly initialized, or if another exception occurs. 223 * 224 * @see sun.security.DSA#engineUpdate 225 * @see sun.security.DSA#engineVerify 226 */ 227 protected byte[] engineSign() throws SignatureException { 228 BigInteger k = generateK(presetQ); 229 BigInteger r = generateR(presetP, presetQ, presetG, k); 230 BigInteger s = generateS(presetX, presetQ, r, k); 231 232 if (p1363Format) { 233 // Return the concatenation of r and s 234 byte[] rBytes = r.toByteArray(); 235 byte[] sBytes = s.toByteArray(); 236 237 int size = presetQ.bitLength() / 8; 238 byte[] outseq = new byte[size * 2]; 239 240 int rLength = rBytes.length; 241 int sLength = sBytes.length; 242 int i; 243 for (i = rLength; i > 0 && rBytes[rLength - i] == 0; i--); 244 245 int j; 246 for (j = sLength; 247 j > 0 && sBytes[sLength - j] == 0; j--); 248 249 System.arraycopy(rBytes, rLength - i, outseq, size - i, i); 250 System.arraycopy(sBytes, sLength - j, outseq, size * 2 - j, j); 251 252 return outseq; 253 } else { 254 // Return the DER-encoded ASN.1 form 255 try { 256 DerOutputStream outseq = new DerOutputStream(100); 257 outseq.putInteger(r); 258 outseq.putInteger(s); 259 DerValue result = new DerValue(DerValue.tag_Sequence, 260 outseq.toByteArray()); 261 262 return result.toByteArray(); 263 264 } catch (IOException e) { 265 throw new SignatureException("error encoding signature"); 266 } 267 } 268 } 269 270 /** 271 * Verify all the data thus far updated. 272 * 273 * @param signature the alleged signature, encoded using the 274 * Canonical Encoding Rules, as a sequence of integers, r and s. 275 * 276 * @exception SignatureException if the signature object was not 277 * properly initialized, or if another exception occurs. 278 * 279 * @see sun.security.DSA#engineUpdate 280 * @see sun.security.DSA#engineSign 281 */ 282 protected boolean engineVerify(byte[] signature) 283 throws SignatureException { 284 return engineVerify(signature, 0, signature.length); 285 } 286 287 /** 288 * Verify all the data thus far updated. 289 * 290 * @param signature the alleged signature, encoded using the 291 * format indicated by {@code p1363Format}. If {@code p1363Format} 292 * is {@code false} (the default), then the signature is formatted 293 * according to the Canonical Encoding Rules, as a DER sequence of 294 * Integers, r and s. If {@code p1363Format} is {@code false}, 295 * the signature is in the IEEE P1363 format, which is the 296 * concatenation or r and s. 297 * 298 * @param offset the offset to start from in the array of bytes. 299 * 300 * @param length the number of bytes to use, starting at offset. 301 * 302 * @exception SignatureException if the signature object was not 303 * properly initialized, or if another exception occurs. 304 * 305 * @see sun.security.DSA#engineUpdate 306 * @see sun.security.DSA#engineSign 307 */ 308 protected boolean engineVerify(byte[] signature, int offset, int length) 309 throws SignatureException { 310 311 BigInteger r = null; 312 BigInteger s = null; 313 314 if (p1363Format) { 315 if ((length & 1) == 1) { 316 // length of signature byte array should be even 317 throw new SignatureException("invalid signature format"); 318 } 319 int mid = length/2; 320 r = new BigInteger(Arrays.copyOfRange(signature, 0, mid)); 321 s = new BigInteger(Arrays.copyOfRange(signature, mid, length)); 322 } else { 323 // first decode the signature. 324 try { 325 DerInputStream in = new DerInputStream(signature, offset, 326 length); 327 DerValue[] values = in.getSequence(2); 328 329 r = values[0].getBigInteger(); 330 s = values[1].getBigInteger(); 331 332 // Check for trailing signature data 333 if (in.available() != 0) { 334 throw new IOException("Incorrect signature length"); 335 } 336 } catch (IOException e) { 337 throw new SignatureException("invalid encoding for signature"); 338 } 339 } 340 341 // some implementations do not correctly encode values in the ASN.1 342 // 2's complement format. force r and s to be positive in order to 343 // to validate those signatures 344 if (r.signum() < 0) { 345 r = new BigInteger(1, r.toByteArray()); 346 } 347 if (s.signum() < 0) { 348 s = new BigInteger(1, s.toByteArray()); 349 } 350 351 if ((r.compareTo(presetQ) == -1) && (s.compareTo(presetQ) == -1)) { 352 BigInteger w = generateW(presetP, presetQ, presetG, s); 353 BigInteger v = generateV(presetY, presetP, presetQ, presetG, w, r); 354 return v.equals(r); 355 } else { 356 throw new SignatureException("invalid signature: out of range values"); 357 } 358 } 359 360 @Deprecated 361 protected void engineSetParameter(String key, Object param) { 362 throw new InvalidParameterException("No parameter accepted"); 363 } 364 365 @Deprecated 366 protected Object engineGetParameter(String key) { 367 return null; 368 } 369 370 private BigInteger generateR(BigInteger p, BigInteger q, BigInteger g, 371 BigInteger k) { 372 BigInteger temp = g.modPow(k, p); 373 return temp.mod(q); 374 } 375 376 private BigInteger generateS(BigInteger x, BigInteger q, 377 BigInteger r, BigInteger k) throws SignatureException { 378 379 byte[] s2; 380 try { 381 s2 = md.digest(); 382 } catch (RuntimeException re) { 383 // Only for RawDSA due to its 20-byte length restriction 384 throw new SignatureException(re.getMessage()); 385 } 386 // get the leftmost min(N, outLen) bits of the digest value 387 int nBytes = q.bitLength()/8; 388 if (nBytes < s2.length) { 389 s2 = Arrays.copyOfRange(s2, 0, nBytes); 390 } 391 BigInteger z = new BigInteger(1, s2); 392 BigInteger k1 = k.modInverse(q); 393 394 return x.multiply(r).add(z).multiply(k1).mod(q); 395 } 396 397 private BigInteger generateW(BigInteger p, BigInteger q, 398 BigInteger g, BigInteger s) { 399 return s.modInverse(q); 400 } 401 402 private BigInteger generateV(BigInteger y, BigInteger p, 403 BigInteger q, BigInteger g, BigInteger w, BigInteger r) 404 throws SignatureException { 405 406 byte[] s2; 407 try { 408 s2 = md.digest(); 409 } catch (RuntimeException re) { 410 // Only for RawDSA due to its 20-byte length restriction 411 throw new SignatureException(re.getMessage()); 412 } 413 // get the leftmost min(N, outLen) bits of the digest value 414 int nBytes = q.bitLength()/8; 415 if (nBytes < s2.length) { 416 s2 = Arrays.copyOfRange(s2, 0, nBytes); 417 } 418 BigInteger z = new BigInteger(1, s2); 419 420 BigInteger u1 = z.multiply(w).mod(q); 421 BigInteger u2 = (r.multiply(w)).mod(q); 422 423 BigInteger t1 = g.modPow(u1,p); 424 BigInteger t2 = y.modPow(u2,p); 425 BigInteger t3 = t1.multiply(t2); 426 BigInteger t5 = t3.mod(p); 427 return t5.mod(q); 428 } 429 430 // NOTE: This following impl is defined in FIPS 186-4 AppendixB.2.1. 431 protected BigInteger generateK(BigInteger q) { 432 SecureRandom random = getSigningRandom(); 433 byte[] kValue = new byte[(q.bitLength() + 7)/8 + 8]; 434 435 random.nextBytes(kValue); 436 return new BigInteger(1, kValue).mod(q.subtract(BigInteger.ONE)).add(BigInteger.ONE); 437 } 438 439 // Use the application-specified SecureRandom Object if provided. 440 // Otherwise, use our default SecureRandom Object. 441 protected SecureRandom getSigningRandom() { 442 if (signingRandom == null) { 443 if (appRandom != null) { 444 signingRandom = appRandom; 445 } else { 446 signingRandom = JCAUtil.getSecureRandom(); 447 } 448 } 449 return signingRandom; 450 } 451 452 /** 453 * Return a human readable rendition of the engine. 454 */ 455 public String toString() { 456 String printable = "DSA Signature"; 457 if (presetP != null && presetQ != null && presetG != null) { 458 printable += "\n\tp: " + Debug.toHexString(presetP); 459 printable += "\n\tq: " + Debug.toHexString(presetQ); 460 printable += "\n\tg: " + Debug.toHexString(presetG); 461 } else { 462 printable += "\n\t P, Q or G not initialized."; 463 } 464 if (presetY != null) { 465 printable += "\n\ty: " + Debug.toHexString(presetY); 466 } 467 if (presetY == null && presetX == null) { 468 printable += "\n\tUNINIIALIZED"; 469 } 470 return printable; 471 } 472 473 private static void debug(Exception e) { 474 if (debug) { 475 e.printStackTrace(); 476 } 477 } 478 479 private static void debug(String s) { 480 if (debug) { 481 System.err.println(s); 482 } 483 } 484 485 /** 486 * Standard SHA224withDSA implementation as defined in FIPS186-3. 487 */ 488 public static final class SHA224withDSA extends DSA { 489 public SHA224withDSA() throws NoSuchAlgorithmException { 490 super(MessageDigest.getInstance("SHA-224")); 491 } 492 } 493 494 /** 495 * SHA224withDSA implementation that uses the IEEE P1363 format. 496 */ 497 public static final class SHA224withDSAinP1363Format extends DSA { 498 public SHA224withDSAinP1363Format() throws NoSuchAlgorithmException { 499 super(MessageDigest.getInstance("SHA-224"), true); 500 } 501 } 502 503 /** 504 * Standard SHA256withDSA implementation as defined in FIPS186-3. 505 */ 506 public static final class SHA256withDSA extends DSA { 507 public SHA256withDSA() throws NoSuchAlgorithmException { 508 super(MessageDigest.getInstance("SHA-256")); 509 } 510 } 511 512 /** 513 * SHA256withDSA implementation that uses the IEEE P1363 format. 514 */ 515 public static final class SHA256withDSAinP1363Format extends DSA { 516 public SHA256withDSAinP1363Format() throws NoSuchAlgorithmException { 517 super(MessageDigest.getInstance("SHA-256"), true); 518 } 519 } 520 521 /** 522 * Standard SHA1withDSA implementation. 523 */ 524 public static final class SHA1withDSA extends DSA { 525 public SHA1withDSA() throws NoSuchAlgorithmException { 526 super(MessageDigest.getInstance("SHA-1")); 527 } 528 } 529 530 /** 531 * SHA1withDSA implementation that uses the IEEE P1363 format. 532 */ 533 public static final class SHA1withDSAinP1363Format extends DSA { 534 public SHA1withDSAinP1363Format() throws NoSuchAlgorithmException { 535 super(MessageDigest.getInstance("SHA-1"), true); 536 } 537 } 538 539 /** 540 * Raw DSA. 541 * 542 * Raw DSA requires the data to be exactly 20 bytes long. If it is 543 * not, a SignatureException is thrown when sign()/verify() is called 544 * per JCA spec. 545 */ 546 static class Raw extends DSA { 547 // Internal special-purpose MessageDigest impl for RawDSA 548 // Only override whatever methods used 549 // NOTE: no clone support 550 public static final class NullDigest20 extends MessageDigest { 551 // 20 byte digest buffer 552 private final byte[] digestBuffer = new byte[20]; 553 554 // offset into the buffer; use Integer.MAX_VALUE to indicate 555 // out-of-bound condition 556 private int ofs = 0; 557 558 protected NullDigest20() { 559 super("NullDigest20"); 560 } 561 protected void engineUpdate(byte input) { 562 if (ofs == digestBuffer.length) { 563 ofs = Integer.MAX_VALUE; 564 } else { 565 digestBuffer[ofs++] = input; 566 } 567 } 568 protected void engineUpdate(byte[] input, int offset, int len) { 569 if (ofs + len > digestBuffer.length) { 570 ofs = Integer.MAX_VALUE; 571 } else { 572 System.arraycopy(input, offset, digestBuffer, ofs, len); 573 ofs += len; 574 } 575 } 576 protected final void engineUpdate(ByteBuffer input) { 577 int inputLen = input.remaining(); 578 if (ofs + inputLen > digestBuffer.length) { 579 ofs = Integer.MAX_VALUE; 580 } else { 581 input.get(digestBuffer, ofs, inputLen); 582 ofs += inputLen; 583 } 584 } 585 protected byte[] engineDigest() throws RuntimeException { 586 if (ofs != digestBuffer.length) { 587 throw new RuntimeException 588 ("Data for RawDSA must be exactly 20 bytes long"); 589 } 590 reset(); 591 return digestBuffer; 592 } 593 protected int engineDigest(byte[] buf, int offset, int len) 594 throws DigestException { 595 if (ofs != digestBuffer.length) { 596 throw new DigestException 597 ("Data for RawDSA must be exactly 20 bytes long"); 598 } 599 if (len < digestBuffer.length) { 600 throw new DigestException 601 ("Output buffer too small; must be at least 20 bytes"); 602 } 603 System.arraycopy(digestBuffer, 0, buf, offset, digestBuffer.length); 604 reset(); 605 return digestBuffer.length; 606 } 607 608 protected void engineReset() { 609 ofs = 0; 610 } 611 protected final int engineGetDigestLength() { 612 return digestBuffer.length; 613 } 614 } 615 616 private Raw(boolean p1363Format) throws NoSuchAlgorithmException { 617 super(new NullDigest20(), p1363Format); 618 } 619 620 } 621 622 /** 623 * Standard Raw DSA implementation. 624 */ 625 public static final class RawDSA extends Raw { 626 public RawDSA() throws NoSuchAlgorithmException { 627 super(false); 628 } 629 } 630 631 /** 632 * Raw DSA implementation that uses the IEEE P1363 format. 633 */ 634 public static final class RawDSAinP1363Format extends Raw { 635 public RawDSAinP1363Format() throws NoSuchAlgorithmException { 636 super(true); 637 } 638 } 639} 640