|
29 | 29 | import java.security.spec.RSAPublicKeySpec;
|
30 | 30 | import java.security.spec.X509EncodedKeySpec;
|
31 | 31 | import java.util.Date;
|
| 32 | +import java.util.Enumeration; |
32 | 33 |
|
33 | 34 | import javax.crypto.interfaces.DHPrivateKey;
|
34 | 35 | import javax.crypto.interfaces.DHPublicKey;
|
35 | 36 | import javax.crypto.spec.DHParameterSpec;
|
36 | 37 | import javax.crypto.spec.DHPrivateKeySpec;
|
37 | 38 | import javax.crypto.spec.DHPublicKeySpec;
|
38 | 39 |
|
| 40 | +import org.bouncycastle.asn1.ASN1Encodable; |
39 | 41 | import org.bouncycastle.asn1.ASN1ObjectIdentifier;
|
40 | 42 | import org.bouncycastle.asn1.ASN1OctetString;
|
41 | 43 | import org.bouncycastle.asn1.DEROctetString;
|
|
49 | 51 | import org.bouncycastle.asn1.x9.X9ECParameters;
|
50 | 52 | import org.bouncycastle.asn1.x9.X9ECParametersHolder;
|
51 | 53 | import org.bouncycastle.asn1.x9.X9ECPoint;
|
| 54 | +import org.bouncycastle.asn1.x9.X9ObjectIdentifiers; |
52 | 55 | import org.bouncycastle.bcpg.BCPGKey;
|
53 | 56 | import org.bouncycastle.bcpg.DSAPublicBCPGKey;
|
54 | 57 | import org.bouncycastle.bcpg.DSASecretBCPGKey;
|
|
72 | 75 | import org.bouncycastle.bcpg.X25519SecretBCPGKey;
|
73 | 76 | import org.bouncycastle.bcpg.X448PublicBCPGKey;
|
74 | 77 | import org.bouncycastle.bcpg.X448SecretBCPGKey;
|
| 78 | +import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey; |
75 | 79 | import org.bouncycastle.jcajce.util.DefaultJcaJceHelper;
|
76 | 80 | import org.bouncycastle.jcajce.util.NamedJcaJceHelper;
|
77 | 81 | import org.bouncycastle.jcajce.util.ProviderJcaJceHelper;
|
@@ -549,47 +553,58 @@ private BCPGKey getPublicBCPGKey(int algorithm, PGPAlgorithmParameters algorithm
|
549 | 553 | SubjectPublicKeyInfo keyInfo = SubjectPublicKeyInfo.getInstance(pubKey.getEncoded());
|
550 | 554 |
|
551 | 555 | // TODO: should probably match curve by comparison as well
|
552 |
| - ASN1ObjectIdentifier curveOid = ASN1ObjectIdentifier.getInstance(keyInfo.getAlgorithm().getParameters()); |
553 |
| - if (curveOid == null) |
| 556 | + ASN1Encodable enc = keyInfo.getAlgorithm().getAlgorithm(); |
| 557 | + ASN1ObjectIdentifier curveOid; |
| 558 | + curveOid = ASN1ObjectIdentifier.getInstance(enc); |
| 559 | + |
| 560 | + // ecPublicKey is not specific enough. Drill down to find proper OID. |
| 561 | + if (X9ObjectIdentifiers.id_ecPublicKey.equals(curveOid)) |
554 | 562 | {
|
555 |
| - // Legacy XDH on Curve25519 (legacy X25519) |
556 |
| - // 1.3.6.1.4.1.3029.1.5.1 & 1.3.101.110 |
557 |
| - if (pubKey.getAlgorithm().regionMatches(true, 0, "X2", 0, 2)) |
| 563 | + enc = getCurveOIDForBCECKey((BCECPublicKey) pubKey); |
| 564 | + ASN1ObjectIdentifier nCurveOid = ASN1ObjectIdentifier.getInstance(enc); |
| 565 | + if (nCurveOid != null) |
558 | 566 | {
|
559 |
| - PGPKdfParameters kdfParams = implGetKdfParameters(CryptlibObjectIdentifiers.curvey25519, algorithmParameters); |
| 567 | + curveOid = nCurveOid; |
| 568 | + } |
| 569 | + } |
560 | 570 |
|
561 |
| - return new ECDHPublicBCPGKey(CryptlibObjectIdentifiers.curvey25519, new BigInteger(1, getPointEncUncompressed(pubKey, X25519.SCALAR_SIZE)), |
| 571 | + // Legacy XDH on Curve25519 (legacy X25519) |
| 572 | + // 1.3.6.1.4.1.3029.1.5.1 & 1.3.101.110 |
| 573 | + if (pubKey.getAlgorithm().regionMatches(true, 0, "X2", 0, 2)) |
| 574 | + { |
| 575 | + PGPKdfParameters kdfParams = implGetKdfParameters(CryptlibObjectIdentifiers.curvey25519, algorithmParameters); |
| 576 | + |
| 577 | + return new ECDHPublicBCPGKey(CryptlibObjectIdentifiers.curvey25519, new BigInteger(1, getPointEncUncompressed(pubKey, X25519.SCALAR_SIZE)), |
562 | 578 | kdfParams.getHashAlgorithm(), kdfParams.getSymmetricWrapAlgorithm());
|
563 |
| - } |
564 |
| - // Legacy X448 (1.3.101.111) |
565 |
| - if (pubKey.getAlgorithm().regionMatches(true, 0, "X4", 0, 2)) |
566 |
| - { |
| 579 | + } |
| 580 | + // Legacy X448 (1.3.101.111) |
| 581 | + if (pubKey.getAlgorithm().regionMatches(true, 0, "X4", 0, 2)) |
| 582 | + { |
567 | 583 |
|
568 |
| - PGPKdfParameters kdfParams = implGetKdfParameters(EdECObjectIdentifiers.id_X448, algorithmParameters); |
| 584 | + PGPKdfParameters kdfParams = implGetKdfParameters(EdECObjectIdentifiers.id_X448, algorithmParameters); |
569 | 585 |
|
570 |
| - return new ECDHPublicBCPGKey(EdECObjectIdentifiers.id_X448, new BigInteger(1, getPointEncUncompressed(pubKey, X448.SCALAR_SIZE)), |
| 586 | + return new ECDHPublicBCPGKey(EdECObjectIdentifiers.id_X448, new BigInteger(1, getPointEncUncompressed(pubKey, X448.SCALAR_SIZE)), |
571 | 587 | kdfParams.getHashAlgorithm(), kdfParams.getSymmetricWrapAlgorithm());
|
572 |
| - } |
573 |
| - // sun.security.ec.XDHPublicKeyImpl returns "XDH" for getAlgorithm() |
574 |
| - // In this case we need to determine the curve by looking at the length of the encoding :/ |
575 |
| - else |
| 588 | + } |
| 589 | + // sun.security.ec.XDHPublicKeyImpl returns "XDH" for getAlgorithm() |
| 590 | + // In this case we need to determine the curve by looking at the length of the encoding :/ |
| 591 | + else if (pubKey.getAlgorithm().regionMatches(true, 0, "XDH", 0, 3)) |
| 592 | + { |
| 593 | + // Legacy X25519 (1.3.6.1.4.1.3029.1.5.1 & 1.3.101.110) |
| 594 | + if (X25519.SCALAR_SIZE + 12 == pubKey.getEncoded().length) // + 12 for some reason |
576 | 595 | {
|
577 |
| - // Legacy X25519 (1.3.6.1.4.1.3029.1.5.1 & 1.3.101.110) |
578 |
| - if (X25519.SCALAR_SIZE + 12 == pubKey.getEncoded().length) // + 12 for some reason |
579 |
| - { |
580 |
| - PGPKdfParameters kdfParams = implGetKdfParameters(CryptlibObjectIdentifiers.curvey25519, algorithmParameters); |
| 596 | + PGPKdfParameters kdfParams = implGetKdfParameters(CryptlibObjectIdentifiers.curvey25519, algorithmParameters); |
581 | 597 |
|
582 |
| - return new ECDHPublicBCPGKey(CryptlibObjectIdentifiers.curvey25519, new BigInteger(1, getPointEncUncompressed(pubKey, X25519.SCALAR_SIZE)), |
| 598 | + return new ECDHPublicBCPGKey(CryptlibObjectIdentifiers.curvey25519, new BigInteger(1, getPointEncUncompressed(pubKey, X25519.SCALAR_SIZE)), |
583 | 599 | kdfParams.getHashAlgorithm(), kdfParams.getSymmetricWrapAlgorithm());
|
584 |
| - } |
585 |
| - // Legacy X448 (1.3.101.111) |
586 |
| - else |
587 |
| - { |
588 |
| - PGPKdfParameters kdfParams = implGetKdfParameters(EdECObjectIdentifiers.id_X448, algorithmParameters); |
| 600 | + } |
| 601 | + // Legacy X448 (1.3.101.111) |
| 602 | + else |
| 603 | + { |
| 604 | + PGPKdfParameters kdfParams = implGetKdfParameters(EdECObjectIdentifiers.id_X448, algorithmParameters); |
589 | 605 |
|
590 |
| - return new ECDHPublicBCPGKey(EdECObjectIdentifiers.id_X448, new BigInteger(1, getPointEncUncompressed(pubKey, X448.SCALAR_SIZE)), |
| 606 | + return new ECDHPublicBCPGKey(EdECObjectIdentifiers.id_X448, new BigInteger(1, getPointEncUncompressed(pubKey, X448.SCALAR_SIZE)), |
591 | 607 | kdfParams.getHashAlgorithm(), kdfParams.getSymmetricWrapAlgorithm());
|
592 |
| - } |
593 | 608 | }
|
594 | 609 | }
|
595 | 610 |
|
@@ -670,6 +685,22 @@ private BCPGKey getPublicBCPGKey(int algorithm, PGPAlgorithmParameters algorithm
|
670 | 685 | }
|
671 | 686 | }
|
672 | 687 |
|
| 688 | + private ASN1Encodable getCurveOIDForBCECKey(BCECPublicKey pubKey) |
| 689 | + { |
| 690 | + // Iterate through all registered curves to find applicable OID |
| 691 | + Enumeration names = ECNamedCurveTable.getNames(); |
| 692 | + while (names.hasMoreElements()) |
| 693 | + { |
| 694 | + String name = (String) names.nextElement(); |
| 695 | + X9ECParameters parms = ECNamedCurveTable.getByName(name); |
| 696 | + if (pubKey.getParameters().getCurve().equals(parms.getCurve())) |
| 697 | + { |
| 698 | + return ECNamedCurveTable.getOID(name); |
| 699 | + } |
| 700 | + } |
| 701 | + return null; |
| 702 | + } |
| 703 | + |
673 | 704 | @FunctionalInterface
|
674 | 705 | private interface BCPGKeyOperation
|
675 | 706 | {
|
|
0 commit comments