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