|
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 | + // BCECPublicKey uses explicit parameter encoding, so we need to find the named curve manually |
| 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 = getNamedCurveOID((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 getNamedCurveOID(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