Skip to content

Commit c2d388f

Browse files
committed
Merge branch 'ed_leading_zero' of https://github.com/pgpainless/bc-java into pgpainless-ed_leading_zero
2 parents 467ca1e + 7f286f8 commit c2d388f

File tree

3 files changed

+115
-11
lines changed

3 files changed

+115
-11
lines changed

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

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -367,22 +367,13 @@ else if (ecdhK.getCurveOID().equals(EdECObjectIdentifiers.id_X448))
367367
// Modern Ed25519 (1.3.6.1.4.1.11591.15.1 & 1.3.101.112)
368368
case PublicKeyAlgorithmTags.Ed25519:
369369
{
370-
BCPGKey key = publicPk.getKey();
371-
if (key instanceof Ed25519PublicBCPGKey)
372-
{
373-
return implGetPublicKeyX509(BigIntegers.asUnsignedByteArray(new BigInteger(1, publicPk.getKey().getEncoded())),
374-
0, EdECObjectIdentifiers.id_Ed25519, "EdDSA");
375-
}
376-
else
377-
{
378-
return implGetPublicKeyX509(BigIntegers.asUnsignedByteArray(((EdDSAPublicBCPGKey)publicPk.getKey()).getEncodedPoint()),
370+
return implGetPublicKeyX509(publicPk.getKey().getEncoded(),
379371
0, EdECObjectIdentifiers.id_Ed25519, "EdDSA");
380-
}
381372
}
382373
// Modern Ed448 (1.3.101.113)
383374
case PublicKeyAlgorithmTags.Ed448:
384375
{
385-
return implGetPublicKeyX509(BigIntegers.asUnsignedByteArray(new BigInteger(1, publicPk.getKey().getEncoded())),
376+
return implGetPublicKeyX509(publicPk.getKey().getEncoded(),
386377
0, EdECObjectIdentifiers.id_Ed448, "EdDSA");
387378
}
388379
case PublicKeyAlgorithmTags.ELGAMAL_ENCRYPT:
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
package org.bouncycastle.openpgp.test;
2+
3+
import org.bouncycastle.bcpg.PublicKeyAlgorithmTags;
4+
import org.bouncycastle.bcpg.test.AbstractPacketTest;
5+
import org.bouncycastle.jce.provider.BouncyCastleProvider;
6+
import org.bouncycastle.openpgp.PGPException;
7+
import org.bouncycastle.openpgp.PGPKeyPair;
8+
import org.bouncycastle.openpgp.operator.jcajce.JcaPGPKeyConverter;
9+
import org.bouncycastle.openpgp.operator.jcajce.JcaPGPKeyPair;
10+
import org.bouncycastle.util.encoders.Hex;
11+
12+
import java.security.*;
13+
import java.security.spec.*;
14+
import java.util.Date;
15+
16+
public class EdDSAKeyConversionWithLeadingZeroTest
17+
extends AbstractPacketTest
18+
{
19+
@Override
20+
public String getName()
21+
{
22+
return "EdDSALeadingZero";
23+
}
24+
25+
private static final String ED448_KEY_WITH_LEADING_ZERO = "308183020101300506032b6571043b0439fe2c82fd07b0e8b5da002ee4964e55a357bfdd2192fe43a40b150e6c5a8f8202f140dd34ede17dc10fef9a98bf8188425c14bd1a76a308cfb7813a0000728cbb07c590e2cb282834cc22d7a1f775f729986c4754e7035695dee34057403e98e94cf5012007c3236f4894af039e668acb746fcf8a00";
26+
private static final String ED448_PUB_WITH_LEADING_ZERO = "3043300506032b6571033a0000728cbb07c590e2cb282834cc22d7a1f775f729986c4754e7035695dee34057403e98e94cf5012007c3236f4894af039e668acb746fcf8a00";
27+
28+
private static final String ED25519_KEY_WITH_LEADING_ZERO = "3051020101300506032b65700422042077ee5931a6d454f85acd9cc28bb2fa8c340e10f7cbf0193f1f898a5c22e77f4281210000dcd38e8ec0978690a4bbc8ac7787d311e741c394ba839ad9cc15e9ba21deb1";
29+
private static final String ED25519_PUB_WITH_LEADING_ZERO = "302a300506032b657003210000dcd38e8ec0978690a4bbc8ac7787d311e741c394ba839ad9cc15e9ba21deb1";
30+
31+
@Override
32+
public void performTest()
33+
throws Exception
34+
{
35+
testWithEd448KeyWithLeadingZero();
36+
testWithEd25519KeyWithLeadingZero();
37+
}
38+
39+
private void testWithEd448KeyWithLeadingZero()
40+
throws NoSuchAlgorithmException, InvalidKeySpecException, PGPException, InvalidKeyException, SignatureException
41+
{
42+
JcaPGPKeyConverter jcaPGPKeyConverter = new JcaPGPKeyConverter().setProvider(new BouncyCastleProvider());
43+
44+
KeyFactory factory = KeyFactory.getInstance("EdDSA", new BouncyCastleProvider());
45+
46+
PublicKey pubKey = factory.generatePublic(new X509EncodedKeySpec(Hex.decode(ED448_PUB_WITH_LEADING_ZERO)));
47+
PrivateKey privKey = factory.generatePrivate(new PKCS8EncodedKeySpec(Hex.decode(ED448_KEY_WITH_LEADING_ZERO)));
48+
KeyPair keyPair = new KeyPair(pubKey, privKey);
49+
50+
Date creationDate = new Date();
51+
PGPKeyPair jcaPgpPair = new JcaPGPKeyPair(PublicKeyAlgorithmTags.Ed448, keyPair, creationDate);
52+
isTrue("public key encoding before conversion MUST have leading 0",
53+
jcaPgpPair.getPublicKey().getPublicKeyPacket().getKey().getEncoded()[0] == 0); // leading 0
54+
55+
PublicKey cPubKey = jcaPGPKeyConverter.getPublicKey(jcaPgpPair.getPublicKey());
56+
PrivateKey cPrivKey = jcaPGPKeyConverter.getPrivateKey(jcaPgpPair.getPrivateKey());
57+
58+
testSignature(cPrivKey, pubKey, "Ed448");
59+
testSignature(privKey, cPubKey, "Ed448");
60+
61+
jcaPgpPair = new JcaPGPKeyPair(PublicKeyAlgorithmTags.Ed448, new KeyPair(cPubKey, cPrivKey), creationDate);
62+
isTrue("public key encoding after conversion MUST have leading 0",
63+
jcaPgpPair.getPublicKey().getPublicKeyPacket().getKey().getEncoded()[0] == 0); // leading 0 is preserved
64+
}
65+
66+
67+
private void testWithEd25519KeyWithLeadingZero()
68+
throws NoSuchAlgorithmException, InvalidKeySpecException, PGPException, InvalidKeyException, SignatureException
69+
{
70+
JcaPGPKeyConverter jcaPGPKeyConverter = new JcaPGPKeyConverter().setProvider(new BouncyCastleProvider());
71+
72+
KeyFactory factory = KeyFactory.getInstance("EdDSA", new BouncyCastleProvider());
73+
74+
PublicKey pubKey = factory.generatePublic(new X509EncodedKeySpec(Hex.decode(ED25519_PUB_WITH_LEADING_ZERO)));
75+
PrivateKey privKey = factory.generatePrivate(new PKCS8EncodedKeySpec(Hex.decode(ED25519_KEY_WITH_LEADING_ZERO)));
76+
KeyPair keyPair = new KeyPair(pubKey, privKey);
77+
78+
Date creationDate = new Date();
79+
PGPKeyPair jcaPgpPair = new JcaPGPKeyPair(PublicKeyAlgorithmTags.Ed25519, keyPair, creationDate);
80+
isTrue("public key encoding before conversion MUST have leading 0",
81+
jcaPgpPair.getPublicKey().getPublicKeyPacket().getKey().getEncoded()[0] == 0); // leading 0
82+
83+
PublicKey cPubKey = jcaPGPKeyConverter.getPublicKey(jcaPgpPair.getPublicKey());
84+
PrivateKey cPrivKey = jcaPGPKeyConverter.getPrivateKey(jcaPgpPair.getPrivateKey());
85+
86+
testSignature(cPrivKey, pubKey, "Ed25519");
87+
testSignature(privKey, cPubKey, "Ed25519");
88+
89+
jcaPgpPair = new JcaPGPKeyPair(PublicKeyAlgorithmTags.Ed25519, new KeyPair(cPubKey, cPrivKey), creationDate);
90+
isTrue("public key encoding after conversion MUST have leading 0",
91+
jcaPgpPair.getPublicKey().getPublicKeyPacket().getKey().getEncoded()[0] == 0); // leading 0 is preserved
92+
}
93+
94+
private void testSignature(PrivateKey privateKey, PublicKey publicKey, String edAlgo)
95+
throws NoSuchAlgorithmException, SignatureException, InvalidKeyException
96+
{
97+
Signature signature = Signature.getInstance(edAlgo, new BouncyCastleProvider());
98+
signature.initSign(privateKey);
99+
signature.update("Hello, World!\n".getBytes());
100+
byte[] sig = signature.sign();
101+
102+
signature.initVerify(publicKey);
103+
signature.update("Hello, World!\n".getBytes());
104+
isTrue("Signature MUST verify", signature.verify(sig));
105+
}
106+
107+
public static void main(String[] args)
108+
{
109+
Security.addProvider(new BouncyCastleProvider());
110+
runTest(new EdDSAKeyConversionWithLeadingZeroTest());
111+
}
112+
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ public class RegressionTest
7575
new LegacyX448KeyPairTest(),
7676

7777
new Curve25519PrivateKeyEncodingTest(),
78+
new EdDSAKeyConversionWithLeadingZeroTest(),
7879
new ECDSAKeyPairTest()
7980
};
8081

0 commit comments

Comments
 (0)