Skip to content

Commit 7065651

Browse files
committed
Merge branch 'pgpainless-fixECKeyConversion'
2 parents 22f6fec + 8004fb3 commit 7065651

File tree

4 files changed

+335
-31
lines changed

4 files changed

+335
-31
lines changed

pg/src/main/java/org/bouncycastle/openpgp/operator/jcajce/JcaPGPKeyConverter.java

Lines changed: 60 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,15 @@
2929
import java.security.spec.RSAPublicKeySpec;
3030
import java.security.spec.X509EncodedKeySpec;
3131
import java.util.Date;
32+
import java.util.Enumeration;
3233

3334
import javax.crypto.interfaces.DHPrivateKey;
3435
import javax.crypto.interfaces.DHPublicKey;
3536
import javax.crypto.spec.DHParameterSpec;
3637
import javax.crypto.spec.DHPrivateKeySpec;
3738
import javax.crypto.spec.DHPublicKeySpec;
3839

40+
import org.bouncycastle.asn1.ASN1Encodable;
3941
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
4042
import org.bouncycastle.asn1.ASN1OctetString;
4143
import org.bouncycastle.asn1.DEROctetString;
@@ -49,6 +51,7 @@
4951
import org.bouncycastle.asn1.x9.X9ECParameters;
5052
import org.bouncycastle.asn1.x9.X9ECParametersHolder;
5153
import org.bouncycastle.asn1.x9.X9ECPoint;
54+
import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
5255
import org.bouncycastle.bcpg.BCPGKey;
5356
import org.bouncycastle.bcpg.DSAPublicBCPGKey;
5457
import org.bouncycastle.bcpg.DSASecretBCPGKey;
@@ -72,6 +75,7 @@
7275
import org.bouncycastle.bcpg.X25519SecretBCPGKey;
7376
import org.bouncycastle.bcpg.X448PublicBCPGKey;
7477
import org.bouncycastle.bcpg.X448SecretBCPGKey;
78+
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
7579
import org.bouncycastle.jcajce.util.DefaultJcaJceHelper;
7680
import org.bouncycastle.jcajce.util.NamedJcaJceHelper;
7781
import org.bouncycastle.jcajce.util.ProviderJcaJceHelper;
@@ -549,47 +553,58 @@ private BCPGKey getPublicBCPGKey(int algorithm, PGPAlgorithmParameters algorithm
549553
SubjectPublicKeyInfo keyInfo = SubjectPublicKeyInfo.getInstance(pubKey.getEncoded());
550554

551555
// 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))
554562
{
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)
558566
{
559-
PGPKdfParameters kdfParams = implGetKdfParameters(CryptlibObjectIdentifiers.curvey25519, algorithmParameters);
567+
curveOid = nCurveOid;
568+
}
569+
}
560570

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)),
562578
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+
{
567583

568-
PGPKdfParameters kdfParams = implGetKdfParameters(EdECObjectIdentifiers.id_X448, algorithmParameters);
584+
PGPKdfParameters kdfParams = implGetKdfParameters(EdECObjectIdentifiers.id_X448, algorithmParameters);
569585

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)),
571587
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
576595
{
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);
581597

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)),
583599
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);
589605

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)),
591607
kdfParams.getHashAlgorithm(), kdfParams.getSymmetricWrapAlgorithm());
592-
}
593608
}
594609
}
595610

@@ -670,6 +685,22 @@ private BCPGKey getPublicBCPGKey(int algorithm, PGPAlgorithmParameters algorithm
670685
}
671686
}
672687

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+
673704
@FunctionalInterface
674705
private interface BCPGKeyOperation
675706
{

pg/src/test/java/org/bouncycastle/openpgp/test/AbstractPgpKeyPairTest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import org.bouncycastle.bcpg.test.AbstractPacketTest;
44
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
5+
import org.bouncycastle.jce.provider.BouncyCastleProvider;
56
import org.bouncycastle.openpgp.PGPException;
67
import org.bouncycastle.openpgp.operator.bc.BcPGPKeyConverter;
78
import org.bouncycastle.openpgp.operator.bc.BcPGPKeyPair;
@@ -35,7 +36,7 @@ public BcPGPKeyPair toBcKeyPair(JcaPGPKeyPair keyPair)
3536
public JcaPGPKeyPair toJcaKeyPair(BcPGPKeyPair keyPair)
3637
throws PGPException
3738
{
38-
JcaPGPKeyConverter c = new JcaPGPKeyConverter();
39+
JcaPGPKeyConverter c = new JcaPGPKeyConverter().setProvider(new BouncyCastleProvider());
3940
return new JcaPGPKeyPair(keyPair.getPublicKey().getAlgorithm(),
4041
new KeyPair(
4142
c.getPublicKey(keyPair.getPublicKey()),

0 commit comments

Comments
 (0)