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 }
|