< prev index next >

src/jdk.crypto.ec/share/classes/sun/security/ec/ECDSASignature.java

Print this page
rev 51879 : 8208698: Improved ECC Implementation
Summary: New implementation of ECDH and ECDSA forsome prime-order curves
Reviewed-by: ascarpino


  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.ec;
  27 
  28 import java.io.IOException;
  29 import java.nio.ByteBuffer;
  30 import java.math.BigInteger;
  31 
  32 import java.security.*;
  33 import java.security.interfaces.*;
  34 import java.security.spec.*;

  35 
  36 import sun.security.jca.JCAUtil;
  37 import sun.security.util.*;

  38 
  39 /**
  40  * ECDSA signature implementation. This class currently supports the
  41  * following algorithm names:
  42  *
  43  *   . "NONEwithECDSA"
  44  *   . "SHA1withECDSA"
  45  *   . "SHA224withECDSA"
  46  *   . "SHA256withECDSA"
  47  *   . "SHA384withECDSA"
  48  *   . "SHA512withECDSA"
  49  *   . "NONEwithECDSAinP1363Format"
  50  *   . "SHA1withECDSAinP1363Format"
  51  *   . "SHA224withECDSAinP1363Format"
  52  *   . "SHA256withECDSAinP1363Format"
  53  *   . "SHA384withECDSAinP1363Format"
  54  *   . "SHA512withECDSAinP1363Format"
  55  *
  56  * @since   1.7
  57  */


 130         private int offset = 0;
 131 
 132         RawECDSA(boolean p1363Format) {
 133             super(p1363Format);
 134             precomputedDigest = new byte[RAW_ECDSA_MAX];
 135         }
 136 
 137         // Stores the precomputed message digest value.
 138         @Override
 139         protected void engineUpdate(byte b) throws SignatureException {
 140             if (offset >= precomputedDigest.length) {
 141                 offset = RAW_ECDSA_MAX + 1;
 142                 return;
 143             }
 144             precomputedDigest[offset++] = b;
 145         }
 146 
 147         // Stores the precomputed message digest value.
 148         @Override
 149         protected void engineUpdate(byte[] b, int off, int len)
 150                 throws SignatureException {
 151             if (offset >= precomputedDigest.length) {
 152                 offset = RAW_ECDSA_MAX + 1;
 153                 return;
 154             }
 155             System.arraycopy(b, off, precomputedDigest, offset, len);
 156             offset += len;
 157         }
 158 
 159         // Stores the precomputed message digest value.
 160         @Override
 161         protected void engineUpdate(ByteBuffer byteBuffer) {
 162             int len = byteBuffer.remaining();
 163             if (len <= 0) {
 164                 return;
 165             }
 166             if (offset + len >= precomputedDigest.length) {
 167                 offset = RAW_ECDSA_MAX + 1;
 168                 return;
 169             }
 170             byteBuffer.get(precomputedDigest, offset, len);
 171             offset += len;
 172         }
 173 
 174         @Override
 175         protected void resetDigest(){
 176             offset = 0;
 177         }
 178 
 179         // Returns the precomputed message digest value.
 180         @Override
 181         protected byte[] getDigestValue() throws SignatureException {
 182             if (offset > RAW_ECDSA_MAX) {
 183                 throw new SignatureException("Message digest is too long");
 184 
 185             }
 186             byte[] result = new byte[offset];
 187             System.arraycopy(precomputedDigest, 0, result, 0, offset);
 188             offset = 0;
 189 
 190             return result;
 191         }
 192     }
 193 
 194     // Nested class for NONEwithECDSA signatures
 195     public static final class Raw extends RawECDSA {


 205         }
 206     }
 207 
 208     // Nested class for SHA1withECDSA signatures
 209     public static final class SHA1 extends ECDSASignature {
 210         public SHA1() {
 211             super("SHA1");
 212         }
 213     }
 214 
 215     // Nested class for SHA1withECDSAinP1363Format signatures
 216     public static final class SHA1inP1363Format extends ECDSASignature {
 217         public SHA1inP1363Format() {
 218             super("SHA1", true);
 219         }
 220     }
 221 
 222     // Nested class for SHA224withECDSA signatures
 223     public static final class SHA224 extends ECDSASignature {
 224         public SHA224() {
 225            super("SHA-224");
 226         }
 227     }
 228 
 229     // Nested class for SHA224withECDSAinP1363Format signatures
 230     public static final class SHA224inP1363Format extends ECDSASignature {
 231         public SHA224inP1363Format() {
 232            super("SHA-224", true);
 233         }
 234     }
 235 
 236     // Nested class for SHA256withECDSA signatures
 237     public static final class SHA256 extends ECDSASignature {
 238         public SHA256() {
 239             super("SHA-256");
 240         }
 241     }
 242 
 243     // Nested class for SHA256withECDSAinP1363Format signatures
 244     public static final class SHA256inP1363Format extends ECDSASignature {
 245         public SHA256inP1363Format() {
 246             super("SHA-256", true);
 247         }
 248     }
 249 
 250     // Nested class for SHA384withECDSA signatures
 251     public static final class SHA384 extends ECDSASignature {
 252         public SHA384() {


 261         }
 262     }
 263 
 264     // Nested class for SHA512withECDSA signatures
 265     public static final class SHA512 extends ECDSASignature {
 266         public SHA512() {
 267             super("SHA-512");
 268         }
 269     }
 270 
 271     // Nested class for SHA512withECDSAinP1363Format signatures
 272     public static final class SHA512inP1363Format extends ECDSASignature {
 273         public SHA512inP1363Format() {
 274             super("SHA-512", true);
 275         }
 276     }
 277 
 278     // initialize for verification. See JCA doc
 279     @Override
 280     protected void engineInitVerify(PublicKey publicKey)
 281             throws InvalidKeyException {
 282         this.publicKey = (ECPublicKey) ECKeyFactory.toECKey(publicKey);
 283 
 284         // Should check that the supplied key is appropriate for signature
 285         // algorithm (e.g. P-256 for SHA256withECDSA)
 286         this.privateKey = null;
 287         resetDigest();
 288     }
 289 
 290     // initialize for signing. See JCA doc
 291     @Override
 292     protected void engineInitSign(PrivateKey privateKey)
 293             throws InvalidKeyException {
 294         engineInitSign(privateKey, null);
 295     }
 296 
 297     // initialize for signing. See JCA doc
 298     @Override
 299     protected void engineInitSign(PrivateKey privateKey, SecureRandom random)
 300             throws InvalidKeyException {
 301         this.privateKey = (ECPrivateKey) ECKeyFactory.toECKey(privateKey);
 302 
 303         // Should check that the supplied key is appropriate for signature
 304         // algorithm (e.g. P-256 for SHA256withECDSA)
 305         this.publicKey = null;
 306         this.random = random;
 307         resetDigest();
 308     }
 309 
 310     /**
 311      * Resets the message digest if needed.
 312      */
 313     protected void resetDigest() {
 314         if (needsReset) {
 315             if (messageDigest != null) {
 316                 messageDigest.reset();
 317             }
 318             needsReset = false;
 319         }
 320     }
 321 
 322     /**
 323      * Returns the message digest value.
 324      */
 325     protected byte[] getDigestValue() throws SignatureException {
 326         needsReset = false;
 327         return messageDigest.digest();
 328     }
 329 
 330     // update the signature with the plaintext data. See JCA doc
 331     @Override
 332     protected void engineUpdate(byte b) throws SignatureException {
 333         messageDigest.update(b);
 334         needsReset = true;
 335     }
 336 
 337     // update the signature with the plaintext data. See JCA doc
 338     @Override
 339     protected void engineUpdate(byte[] b, int off, int len)
 340             throws SignatureException {
 341         messageDigest.update(b, off, len);
 342         needsReset = true;
 343     }
 344 
 345     // update the signature with the plaintext data. See JCA doc
 346     @Override
 347     protected void engineUpdate(ByteBuffer byteBuffer) {
 348         int len = byteBuffer.remaining();
 349         if (len <= 0) {
 350             return;
 351         }
 352 
 353         messageDigest.update(byteBuffer);
 354         needsReset = true;
 355     }
 356 
 357     // sign the data and return the signature. See JCA doc
 358     @Override
 359     protected byte[] engineSign() throws SignatureException {
















































 360         byte[] s = privateKey.getS().toByteArray();
 361         ECParameterSpec params = privateKey.getParams();

 362         // DER OID
 363         byte[] encodedParams = ECUtil.encodeECParameterSpec(null, params);
 364         int keySize = params.getCurve().getField().getFieldSize();
 365 
 366         // seed is twice the key size (in bytes) plus 1
 367         byte[] seed = new byte[(((keySize + 7) >> 3) + 1) * 2];
 368         if (random == null) {
 369             random = JCAUtil.getSecureRandom();
 370         }
 371         random.nextBytes(seed);
 372 
 373         // random bits needed for timing countermeasures
 374         int timingArgument = random.nextInt();
 375         // values must be non-zero to enable countermeasures
 376         timingArgument |= 1;
 377 
 378         byte[] sig;
 379         try {
 380             sig = signDigest(getDigestValue(), s, encodedParams, seed,
 381                 timingArgument);
 382         } catch (GeneralSecurityException e) {
 383             throw new SignatureException("Could not sign data", e);
 384         }
 385 



















 386         if (p1363Format) {
 387             return sig;
 388         } else {
 389             return encodeSignature(sig);
 390         }
 391     }
 392 
 393     // verify the data and return the result. See JCA doc
 394     @Override
 395     protected boolean engineVerify(byte[] signature) throws SignatureException {
 396 
 397         byte[] w;
 398         ECParameterSpec params = publicKey.getParams();
 399         // DER OID
 400         byte[] encodedParams = ECUtil.encodeECParameterSpec(null, params);
 401 
 402         if (publicKey instanceof ECPublicKeyImpl) {
 403             w = ((ECPublicKeyImpl)publicKey).getEncodedPublicValue();
 404         } else { // instanceof ECPublicKey
 405             w = ECUtil.encodePoint(publicKey.getW(), params.getCurve());
 406         }
 407 
 408         byte[] sig;
 409         if (p1363Format) {
 410             sig = signature;
 411         } else {
 412             sig = decodeSignature(signature);
 413         }
 414 
 415         try {
 416             return verifySignedDigest(sig, getDigestValue(), w, encodedParams);
 417         } catch (GeneralSecurityException e) {
 418             throw new SignatureException("Could not verify signature", e);
 419         }
 420     }
 421 
 422     // set parameter, not supported. See JCA doc
 423     @Override
 424     @Deprecated
 425     protected void engineSetParameter(String param, Object value)
 426             throws InvalidParameterException {
 427         throw new UnsupportedOperationException("setParameter() not supported");
 428     }
 429 
 430     @Override
 431     protected void engineSetParameter(AlgorithmParameterSpec params)
 432             throws InvalidAlgorithmParameterException {
 433         if (params != null) {
 434             throw new InvalidAlgorithmParameterException("No parameter accepted");
 435         }
 436     }
 437 
 438     // get parameter, not supported. See JCA doc
 439     @Override
 440     @Deprecated
 441     protected Object engineGetParameter(String param)
 442             throws InvalidParameterException {
 443         throw new UnsupportedOperationException("getParameter() not supported");
 444     }
 445 
 446     @Override
 447     protected AlgorithmParameters engineGetParameters() {
 448         return null;
 449     }
 450 
 451     // Convert the concatenation of R and S into their DER encoding
 452     private byte[] encodeSignature(byte[] signature) throws SignatureException {
 453 
 454         try {
 455 
 456             int n = signature.length >> 1;
 457             byte[] bytes = new byte[n];
 458             System.arraycopy(signature, 0, bytes, 0, n);
 459             BigInteger r = new BigInteger(1, bytes);
 460             System.arraycopy(signature, n, bytes, 0, n);
 461             BigInteger s = new BigInteger(1, bytes);
 462 
 463             DerOutputStream out = new DerOutputStream(signature.length + 10);
 464             out.putInteger(r);
 465             out.putInteger(s);
 466             DerValue result =
 467                 new DerValue(DerValue.tag_Sequence, out.toByteArray());
 468 
 469             return result.toByteArray();
 470 
 471         } catch (Exception e) {
 472             throw new SignatureException("Could not encode signature", e);
 473         }
 474     }
 475 
 476     // Convert the DER encoding of R and S into a concatenation of R and S
 477     private byte[] decodeSignature(byte[] sig) throws SignatureException {
 478 
 479         try {
 480             // Enforce strict DER checking for signatures
 481             DerInputStream in = new DerInputStream(sig, 0, sig.length, false);
 482             DerValue[] values = in.getSequence(2);
 483 
 484             // check number of components in the read sequence
 485             // and trailing data
 486             if ((values.length != 2) || (in.available() != 0)) {
 487                 throw new IOException("Invalid encoding for signature");
 488             }
 489 
 490             BigInteger r = values[0].getPositiveBigInteger();
 491             BigInteger s = values[1].getPositiveBigInteger();
 492 
 493             // trim leading zeroes
 494             byte[] rBytes = trimZeroes(r.toByteArray());
 495             byte[] sBytes = trimZeroes(s.toByteArray());
 496             int k = Math.max(rBytes.length, sBytes.length);
 497             // r and s each occupy half the array
 498             byte[] result = new byte[k << 1];
 499             System.arraycopy(rBytes, 0, result, k - rBytes.length,
 500                 rBytes.length);
 501             System.arraycopy(sBytes, 0, result, result.length - sBytes.length,
 502                 sBytes.length);
 503             return result;
 504 
 505         } catch (Exception e) {
 506             throw new SignatureException("Invalid encoding for signature", e);
 507         }
 508     }
 509 
 510     // trim leading (most significant) zeroes from the result
 511     private static byte[] trimZeroes(byte[] b) {
 512         int i = 0;
 513         while ((i < b.length - 1) && (b[i] == 0)) {
 514             i++;
 515         }
 516         if (i == 0) {
 517             return b;
 518         }
 519         byte[] t = new byte[b.length - i];
 520         System.arraycopy(b, i, t, 0, t.length);
 521         return t;
 522     }
 523 
 524     /**
 525      * Signs the digest using the private key.
 526      *
 527      * @param digest the digest to be signed.
 528      * @param s the private key's S value.
 529      * @param encodedParams the curve's DER encoded object identifier.
 530      * @param seed the random seed.
 531      * @param timing When non-zero, the implmentation will use timing
 532      *     countermeasures to hide secrets from timing channels. The EC
 533      *     implementation will disable the countermeasures when this value is
 534      *     zero, because the underlying EC functions are shared by several
 535      *     crypto operations, some of which do not use the countermeasures.
 536      *     The high-order 31 bits must be uniformly random. The entropy from
 537      *     these bits is used by the countermeasures.
 538      *
 539      * @return byte[] the signature.
 540      */
 541     private static native byte[] signDigest(byte[] digest, byte[] s,
 542         byte[] encodedParams, byte[] seed, int timing)
 543             throws GeneralSecurityException;
 544 
 545     /**
 546      * Verifies the signed digest using the public key.
 547      *
 548      * @param signedDigest the signature to be verified. It is encoded
 549      *        as a concatenation of the key's R and S values.
 550      * @param digest the digest to be used.
 551      * @param w the public key's W point (in uncompressed form).
 552      * @param encodedParams the curve's DER encoded object identifier.
 553      *
 554      * @return boolean true if the signature is successfully verified.
 555      */
 556     private static native boolean verifySignedDigest(byte[] signature,
 557         byte[] digest, byte[] w, byte[] encodedParams)
 558             throws GeneralSecurityException;
 559 }


  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.ec;
  27 
  28 import java.io.IOException;
  29 import java.nio.ByteBuffer;
  30 import java.math.BigInteger;
  31 
  32 import java.security.*;
  33 import java.security.interfaces.*;
  34 import java.security.spec.*;
  35 import java.util.Optional;
  36 
  37 import sun.security.jca.JCAUtil;
  38 import sun.security.util.*;
  39 import static sun.security.ec.ECOperations.IntermediateValueException;
  40 
  41 /**
  42  * ECDSA signature implementation. This class currently supports the
  43  * following algorithm names:
  44  *
  45  *   . "NONEwithECDSA"
  46  *   . "SHA1withECDSA"
  47  *   . "SHA224withECDSA"
  48  *   . "SHA256withECDSA"
  49  *   . "SHA384withECDSA"
  50  *   . "SHA512withECDSA"
  51  *   . "NONEwithECDSAinP1363Format"
  52  *   . "SHA1withECDSAinP1363Format"
  53  *   . "SHA224withECDSAinP1363Format"
  54  *   . "SHA256withECDSAinP1363Format"
  55  *   . "SHA384withECDSAinP1363Format"
  56  *   . "SHA512withECDSAinP1363Format"
  57  *
  58  * @since   1.7
  59  */


 132         private int offset = 0;
 133 
 134         RawECDSA(boolean p1363Format) {
 135             super(p1363Format);
 136             precomputedDigest = new byte[RAW_ECDSA_MAX];
 137         }
 138 
 139         // Stores the precomputed message digest value.
 140         @Override
 141         protected void engineUpdate(byte b) throws SignatureException {
 142             if (offset >= precomputedDigest.length) {
 143                 offset = RAW_ECDSA_MAX + 1;
 144                 return;
 145             }
 146             precomputedDigest[offset++] = b;
 147         }
 148 
 149         // Stores the precomputed message digest value.
 150         @Override
 151         protected void engineUpdate(byte[] b, int off, int len)
 152         throws SignatureException {
 153             if (offset >= precomputedDigest.length) {
 154                 offset = RAW_ECDSA_MAX + 1;
 155                 return;
 156             }
 157             System.arraycopy(b, off, precomputedDigest, offset, len);
 158             offset += len;
 159         }
 160 
 161         // Stores the precomputed message digest value.
 162         @Override
 163         protected void engineUpdate(ByteBuffer byteBuffer) {
 164             int len = byteBuffer.remaining();
 165             if (len <= 0) {
 166                 return;
 167             }
 168             if (offset + len >= precomputedDigest.length) {
 169                 offset = RAW_ECDSA_MAX + 1;
 170                 return;
 171             }
 172             byteBuffer.get(precomputedDigest, offset, len);
 173             offset += len;
 174         }
 175 
 176         @Override
 177         protected void resetDigest() {
 178             offset = 0;
 179         }
 180 
 181         // Returns the precomputed message digest value.
 182         @Override
 183         protected byte[] getDigestValue() throws SignatureException {
 184             if (offset > RAW_ECDSA_MAX) {
 185                 throw new SignatureException("Message digest is too long");
 186 
 187             }
 188             byte[] result = new byte[offset];
 189             System.arraycopy(precomputedDigest, 0, result, 0, offset);
 190             offset = 0;
 191 
 192             return result;
 193         }
 194     }
 195 
 196     // Nested class for NONEwithECDSA signatures
 197     public static final class Raw extends RawECDSA {


 207         }
 208     }
 209 
 210     // Nested class for SHA1withECDSA signatures
 211     public static final class SHA1 extends ECDSASignature {
 212         public SHA1() {
 213             super("SHA1");
 214         }
 215     }
 216 
 217     // Nested class for SHA1withECDSAinP1363Format signatures
 218     public static final class SHA1inP1363Format extends ECDSASignature {
 219         public SHA1inP1363Format() {
 220             super("SHA1", true);
 221         }
 222     }
 223 
 224     // Nested class for SHA224withECDSA signatures
 225     public static final class SHA224 extends ECDSASignature {
 226         public SHA224() {
 227             super("SHA-224");
 228         }
 229     }
 230 
 231     // Nested class for SHA224withECDSAinP1363Format signatures
 232     public static final class SHA224inP1363Format extends ECDSASignature {
 233         public SHA224inP1363Format() {
 234             super("SHA-224", true);
 235         }
 236     }
 237 
 238     // Nested class for SHA256withECDSA signatures
 239     public static final class SHA256 extends ECDSASignature {
 240         public SHA256() {
 241             super("SHA-256");
 242         }
 243     }
 244 
 245     // Nested class for SHA256withECDSAinP1363Format signatures
 246     public static final class SHA256inP1363Format extends ECDSASignature {
 247         public SHA256inP1363Format() {
 248             super("SHA-256", true);
 249         }
 250     }
 251 
 252     // Nested class for SHA384withECDSA signatures
 253     public static final class SHA384 extends ECDSASignature {
 254         public SHA384() {


 263         }
 264     }
 265 
 266     // Nested class for SHA512withECDSA signatures
 267     public static final class SHA512 extends ECDSASignature {
 268         public SHA512() {
 269             super("SHA-512");
 270         }
 271     }
 272 
 273     // Nested class for SHA512withECDSAinP1363Format signatures
 274     public static final class SHA512inP1363Format extends ECDSASignature {
 275         public SHA512inP1363Format() {
 276             super("SHA-512", true);
 277         }
 278     }
 279 
 280     // initialize for verification. See JCA doc
 281     @Override
 282     protected void engineInitVerify(PublicKey publicKey)
 283     throws InvalidKeyException {
 284         this.publicKey = (ECPublicKey) ECKeyFactory.toECKey(publicKey);
 285 
 286         // Should check that the supplied key is appropriate for signature
 287         // algorithm (e.g. P-256 for SHA256withECDSA)
 288         this.privateKey = null;
 289         resetDigest();
 290     }
 291 
 292     // initialize for signing. See JCA doc
 293     @Override
 294     protected void engineInitSign(PrivateKey privateKey)
 295     throws InvalidKeyException {
 296         engineInitSign(privateKey, null);
 297     }
 298 
 299     // initialize for signing. See JCA doc
 300     @Override
 301     protected void engineInitSign(PrivateKey privateKey, SecureRandom random)
 302     throws InvalidKeyException {
 303         this.privateKey = (ECPrivateKey) ECKeyFactory.toECKey(privateKey);
 304 
 305         // Should check that the supplied key is appropriate for signature
 306         // algorithm (e.g. P-256 for SHA256withECDSA)
 307         this.publicKey = null;
 308         this.random = random;
 309         resetDigest();
 310     }
 311 
 312     /**
 313      * Resets the message digest if needed.
 314      */
 315     protected void resetDigest() {
 316         if (needsReset) {
 317             if (messageDigest != null) {
 318                 messageDigest.reset();
 319             }
 320             needsReset = false;
 321         }
 322     }
 323 
 324     /**
 325      * Returns the message digest value.
 326      */
 327     protected byte[] getDigestValue() throws SignatureException {
 328         needsReset = false;
 329         return messageDigest.digest();
 330     }
 331 
 332     // update the signature with the plaintext data. See JCA doc
 333     @Override
 334     protected void engineUpdate(byte b) throws SignatureException {
 335         messageDigest.update(b);
 336         needsReset = true;
 337     }
 338 
 339     // update the signature with the plaintext data. See JCA doc
 340     @Override
 341     protected void engineUpdate(byte[] b, int off, int len)
 342     throws SignatureException {
 343         messageDigest.update(b, off, len);
 344         needsReset = true;
 345     }
 346 
 347     // update the signature with the plaintext data. See JCA doc
 348     @Override
 349     protected void engineUpdate(ByteBuffer byteBuffer) {
 350         int len = byteBuffer.remaining();
 351         if (len <= 0) {
 352             return;
 353         }
 354 
 355         messageDigest.update(byteBuffer);
 356         needsReset = true;
 357     }
 358 
 359     private byte[] signDigestImpl(ECDSAOperations ops, int seedBits,
 360         byte[] digest, ECPrivateKeyImpl privImpl, SecureRandom random)
 361         throws SignatureException {
 362 
 363         byte[] seedBytes = new byte[(seedBits + 7) / 8];
 364         byte[] s = privImpl.getArrayS();
 365 
 366         // Attempt to create the signature in a loop that uses new random input
 367         // each time. The chance of failure is very small assuming the
 368         // implementation derives the nonce using extra bits
 369         int numAttempts = 128;
 370         for (int i = 0; i < numAttempts; i++) {
 371             random.nextBytes(seedBytes);
 372             ECDSAOperations.Seed seed = new ECDSAOperations.Seed(seedBytes);
 373             try {
 374                 return ops.signDigest(s, digest, seed);
 375             } catch (IntermediateValueException ex) {
 376                 // try again in the next iteration
 377             }
 378         }
 379 
 380         throw new SignatureException("Unable to produce signature after "
 381             + numAttempts + " attempts");
 382     }
 383 
 384 
 385     private Optional<byte[]> signDigestImpl(ECPrivateKey privateKey,
 386         byte[] digest, SecureRandom random) throws SignatureException {
 387 
 388         if (! (privateKey instanceof ECPrivateKeyImpl)) {
 389             return Optional.empty();
 390         }
 391         ECPrivateKeyImpl privImpl = (ECPrivateKeyImpl) privateKey;
 392         ECParameterSpec params = privateKey.getParams();
 393 
 394         // seed is the key size + 64 bits
 395         int seedBits = params.getOrder().bitLength() + 64;
 396         Optional<ECDSAOperations> opsOpt =
 397             ECDSAOperations.forParameters(params);
 398         if (opsOpt.isEmpty()) {
 399             return Optional.empty();
 400         } else {
 401             byte[] sig = signDigestImpl(opsOpt.get(), seedBits, digest,
 402                 privImpl, random);
 403             return Optional.of(sig);
 404         }
 405     }
 406 
 407     private byte[] signDigestNative(ECPrivateKey privateKey, byte[] digest,
 408         SecureRandom random) throws SignatureException {
 409 
 410         byte[] s = privateKey.getS().toByteArray();
 411         ECParameterSpec params = privateKey.getParams();
 412 
 413         // DER OID
 414         byte[] encodedParams = ECUtil.encodeECParameterSpec(null, params);
 415         int keySize = params.getCurve().getField().getFieldSize();
 416 
 417         // seed is twice the key size (in bytes) plus 1
 418         byte[] seed = new byte[(((keySize + 7) >> 3) + 1) * 2];
 419 


 420         random.nextBytes(seed);
 421 
 422         // random bits needed for timing countermeasures
 423         int timingArgument = random.nextInt();
 424         // values must be non-zero to enable countermeasures
 425         timingArgument |= 1;
 426 

 427         try {
 428             return signDigest(digest, s, encodedParams, seed,
 429                 timingArgument);
 430         } catch (GeneralSecurityException e) {
 431             throw new SignatureException("Could not sign data", e);
 432         }
 433 
 434     }
 435 
 436     // sign the data and return the signature. See JCA doc
 437     @Override
 438     protected byte[] engineSign() throws SignatureException {
 439 
 440         if (random == null) {
 441             random = JCAUtil.getSecureRandom();
 442         }
 443 
 444         byte[] digest = getDigestValue();
 445         Optional<byte[]> sigOpt = signDigestImpl(privateKey, digest, random);
 446         byte[] sig;
 447         if (sigOpt.isPresent()) {
 448             sig = sigOpt.get();
 449         } else {
 450             sig = signDigestNative(privateKey, digest, random);
 451         }
 452 
 453         if (p1363Format) {
 454             return sig;
 455         } else {
 456             return encodeSignature(sig);
 457         }
 458     }
 459 
 460     // verify the data and return the result. See JCA doc
 461     @Override
 462     protected boolean engineVerify(byte[] signature) throws SignatureException {
 463 
 464         byte[] w;
 465         ECParameterSpec params = publicKey.getParams();
 466         // DER OID
 467         byte[] encodedParams = ECUtil.encodeECParameterSpec(null, params);
 468 
 469         if (publicKey instanceof ECPublicKeyImpl) {
 470             w = ((ECPublicKeyImpl) publicKey).getEncodedPublicValue();
 471         } else { // instanceof ECPublicKey
 472             w = ECUtil.encodePoint(publicKey.getW(), params.getCurve());
 473         }
 474 
 475         byte[] sig;
 476         if (p1363Format) {
 477             sig = signature;
 478         } else {
 479             sig = decodeSignature(signature);
 480         }
 481 
 482         try {
 483             return verifySignedDigest(sig, getDigestValue(), w, encodedParams);
 484         } catch (GeneralSecurityException e) {
 485             throw new SignatureException("Could not verify signature", e);
 486         }
 487     }
 488 
 489     // set parameter, not supported. See JCA doc
 490     @Override
 491     @Deprecated
 492     protected void engineSetParameter(String param, Object value)
 493     throws InvalidParameterException {
 494         throw new UnsupportedOperationException("setParameter() not supported");
 495     }
 496 
 497     @Override
 498     protected void engineSetParameter(AlgorithmParameterSpec params)
 499     throws InvalidAlgorithmParameterException {
 500         if (params != null) {
 501             throw new InvalidAlgorithmParameterException("No parameter accepted");
 502         }
 503     }
 504 
 505     // get parameter, not supported. See JCA doc
 506     @Override
 507     @Deprecated
 508     protected Object engineGetParameter(String param)
 509     throws InvalidParameterException {
 510         throw new UnsupportedOperationException("getParameter() not supported");
 511     }
 512 
 513     @Override
 514     protected AlgorithmParameters engineGetParameters() {
 515         return null;
 516     }
 517 
 518     // Convert the concatenation of R and S into their DER encoding
 519     private byte[] encodeSignature(byte[] signature) throws SignatureException {
 520 
 521         try {
 522 
 523             int n = signature.length >> 1;
 524             byte[] bytes = new byte[n];
 525             System.arraycopy(signature, 0, bytes, 0, n);
 526             BigInteger r = new BigInteger(1, bytes);
 527             System.arraycopy(signature, n, bytes, 0, n);
 528             BigInteger s = new BigInteger(1, bytes);
 529 
 530             DerOutputStream out = new DerOutputStream(signature.length + 10);
 531             out.putInteger(r);
 532             out.putInteger(s);
 533             DerValue result =
 534             new DerValue(DerValue.tag_Sequence, out.toByteArray());
 535 
 536             return result.toByteArray();
 537 
 538         } catch (Exception e) {
 539             throw new SignatureException("Could not encode signature", e);
 540         }
 541     }
 542 
 543     // Convert the DER encoding of R and S into a concatenation of R and S
 544     private byte[] decodeSignature(byte[] sig) throws SignatureException {
 545 
 546         try {
 547             // Enforce strict DER checking for signatures
 548             DerInputStream in = new DerInputStream(sig, 0, sig.length, false);
 549             DerValue[] values = in.getSequence(2);
 550 
 551             // check number of components in the read sequence
 552             // and trailing data
 553             if ((values.length != 2) || (in.available() != 0)) {
 554                 throw new IOException("Invalid encoding for signature");
 555             }
 556 
 557             BigInteger r = values[0].getPositiveBigInteger();
 558             BigInteger s = values[1].getPositiveBigInteger();
 559 
 560             // trim leading zeroes
 561             byte[] rBytes = trimZeroes(r.toByteArray());
 562             byte[] sBytes = trimZeroes(s.toByteArray());
 563             int k = Math.max(rBytes.length, sBytes.length);
 564             // r and s each occupy half the array
 565             byte[] result = new byte[k << 1];
 566             System.arraycopy(rBytes, 0, result, k - rBytes.length,
 567             rBytes.length);
 568             System.arraycopy(sBytes, 0, result, result.length - sBytes.length,
 569             sBytes.length);
 570             return result;
 571 
 572         } catch (Exception e) {
 573             throw new SignatureException("Invalid encoding for signature", e);
 574         }
 575     }
 576 
 577     // trim leading (most significant) zeroes from the result
 578     private static byte[] trimZeroes(byte[] b) {
 579         int i = 0;
 580         while ((i < b.length - 1) && (b[i] == 0)) {
 581             i++;
 582         }
 583         if (i == 0) {
 584             return b;
 585         }
 586         byte[] t = new byte[b.length - i];
 587         System.arraycopy(b, i, t, 0, t.length);
 588         return t;
 589     }
 590 
 591     /**
 592      * Signs the digest using the private key.
 593      *
 594      * @param digest the digest to be signed.
 595      * @param s the private key's S value.
 596      * @param encodedParams the curve's DER encoded object identifier.
 597      * @param seed the random seed.
 598      * @param timing When non-zero, the implmentation will use timing
 599      *     countermeasures to hide secrets from timing channels. The EC
 600      *     implementation will disable the countermeasures when this value is
 601      *     zero, because the underlying EC functions are shared by several
 602      *     crypto operations, some of which do not use the countermeasures.
 603      *     The high-order 31 bits must be uniformly random. The entropy from
 604      *     these bits is used by the countermeasures.
 605      *
 606      * @return byte[] the signature.
 607      */
 608     private static native byte[] signDigest(byte[] digest, byte[] s,
 609                                             byte[] encodedParams, byte[] seed, int timing)
 610         throws GeneralSecurityException;
 611 
 612     /**
 613      * Verifies the signed digest using the public key.
 614      *
 615      * @param signature the signature to be verified. It is encoded
 616      *        as a concatenation of the key's R and S values.
 617      * @param digest the digest to be used.
 618      * @param w the public key's W point (in uncompressed form).
 619      * @param encodedParams the curve's DER encoded object identifier.
 620      *
 621      * @return boolean true if the signature is successfully verified.
 622      */
 623     private static native boolean verifySignedDigest(byte[] signature,
 624                                                      byte[] digest, byte[] w, byte[] encodedParams)
 625         throws GeneralSecurityException;
 626 }
< prev index next >