Skip to content

Commit 1e12a50

Browse files
committed
updated Kyber private key encoding.
1 parent 01844f3 commit 1e12a50

File tree

7 files changed

+83
-49
lines changed

7 files changed

+83
-49
lines changed

core/src/main/java/org/bouncycastle/pqc/crypto/crystals/kyber/KyberEngine.java

Lines changed: 3 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,10 @@
33
import java.security.SecureRandom;
44
import java.util.Arrays;
55

6-
import org.bouncycastle.crypto.digests.SHA3Digest;
7-
import org.bouncycastle.crypto.digests.SHAKEDigest;
8-
9-
106
class KyberEngine
117
{
12-
138
private SecureRandom random;
149
private KyberIndCpa indCpa;
15-
private SHA3Digest sha3Digest256 = new SHA3Digest(256);
16-
private SHA3Digest sha3Digest512 = new SHA3Digest(512);
17-
private SHAKEDigest shakeDigest = new SHAKEDigest(256);
18-
1910

2011
// constant parameters
2112
public final static int KyberN = 256;
@@ -195,15 +186,6 @@ public KyberEngine(int k, boolean usingAes)
195186
}
196187

197188
this.indCpa = new KyberIndCpa(this);
198-
199-
200-
201-
// Testing Random
202-
// byte[] b = new byte[48];
203-
204-
// random.nextBytes(b);
205-
206-
// Helper.printByteArray(b);
207189
}
208190

209191
public void init(SecureRandom random)
@@ -215,24 +197,20 @@ public byte[][] generateKemKeyPair()
215197
{
216198
byte[][] indCpaKeyPair = indCpa.generateKeyPair();
217199

218-
byte[] secretKey = new byte[KyberSecretKeyBytes];
200+
byte[] s = new byte[KyberIndCpaSecretKeyBytes];
219201

220-
System.arraycopy(indCpaKeyPair[1], 0, secretKey, 0, KyberIndCpaSecretKeyBytes);
221-
System.arraycopy(indCpaKeyPair[0], 0, secretKey, KyberIndCpaSecretKeyBytes, KyberIndCpaPublicKeyBytes);
202+
System.arraycopy(indCpaKeyPair[1], 0, s, 0, KyberIndCpaSecretKeyBytes);
222203

223204
byte[] hashedPublicKey = new byte[32];
224205

225206
symmetric.hash_h(hashedPublicKey, indCpaKeyPair[0], 0);
226207

227-
System.arraycopy(hashedPublicKey, 0, secretKey, KyberSecretKeyBytes - 2 * KyberSymBytes, KyberSymBytes);
228-
229208
byte[] z = new byte[KyberSymBytes];
230209
random.nextBytes(z);
231-
System.arraycopy(z, 0, secretKey, KyberSecretKeyBytes - KyberSymBytes, KyberSymBytes);
232210

233211
byte[] outputPublicKey = new byte[KyberIndCpaPublicKeyBytes];
234212
System.arraycopy(indCpaKeyPair[0], 0, outputPublicKey, 0, KyberIndCpaPublicKeyBytes);
235-
return new byte[][]{outputPublicKey, secretKey};
213+
return new byte[][]{ Arrays.copyOfRange(outputPublicKey, 0, outputPublicKey.length - 32), Arrays.copyOfRange(outputPublicKey, outputPublicKey.length - 32, outputPublicKey.length), s, hashedPublicKey, z };
236214
}
237215

238216
public byte[][] kemEncrypt(byte[] publicKeyInput)
@@ -278,7 +256,6 @@ public byte[] kemDecrypt(byte[] cipherText, byte[] secretKey)
278256
byte[] buf = new byte[2 * KyberSymBytes],
279257
kr = new byte[2 * KyberSymBytes];
280258

281-
int i;
282259
byte[] publicKey = Arrays.copyOfRange(secretKey, KyberIndCpaSecretKeyBytes, secretKey.length);
283260

284261
System.arraycopy(indCpa.decrypt(cipherText, secretKey), 0, buf, 0, KyberSymBytes);
@@ -320,5 +297,4 @@ public void getRandomBytes(byte[] buf)
320297
{
321298
this.random.nextBytes(buf);
322299
}
323-
324300
}

core/src/main/java/org/bouncycastle/pqc/crypto/crystals/kyber/KyberKEMExtractor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ private void initCipher(AsymmetricKeyParameter recipientKey)
2626
public byte[] extractSecret(byte[] encapsulation)
2727
{
2828
// Decryption
29-
byte[] sharedSecret = engine.kemDecrypt(encapsulation, key.privateKey);
29+
byte[] sharedSecret = engine.kemDecrypt(encapsulation, key.getPrivateKey());
3030
return sharedSecret;
3131
}
3232

core/src/main/java/org/bouncycastle/pqc/crypto/crystals/kyber/KyberKeyPairGenerator.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ private AsymmetricCipherKeyPair genKeyPair()
2929

3030
byte[][] keyPair = engine.generateKemKeyPair();
3131

32-
KyberPublicKeyParameters pubKey = new KyberPublicKeyParameters(kyberParams, keyPair[0]);
33-
KyberPrivateKeyParameters privKey = new KyberPrivateKeyParameters(kyberParams, keyPair[1], keyPair[0]);
32+
KyberPublicKeyParameters pubKey = new KyberPublicKeyParameters(kyberParams, keyPair[0], keyPair[1]);
33+
KyberPrivateKeyParameters privKey = new KyberPrivateKeyParameters(kyberParams, keyPair[2], keyPair[3], keyPair[4], keyPair[0], keyPair[1]);
3434

3535
return new AsymmetricCipherKeyPair(pubKey, privKey);
3636
}

core/src/main/java/org/bouncycastle/pqc/crypto/crystals/kyber/KyberPrivateKeyParameters.java

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,28 +5,59 @@
55
public class KyberPrivateKeyParameters
66
extends KyberKeyParameters
77
{
8-
final byte[] privateKey;
9-
final byte[] publicKey;
8+
final byte[] s;
9+
final byte[] hpk;
10+
final byte[] nonce;
11+
final byte[] t;
12+
final byte[] rho;
1013

11-
public KyberPrivateKeyParameters(KyberParameters params, byte[] privateKey, byte[] publicKey)
14+
public KyberPrivateKeyParameters(KyberParameters params, byte[] s, byte[] hpk, byte[] nonce, byte[] t, byte[] rho)
1215
{
1316
super(true, params);
14-
this.privateKey = Arrays.clone(privateKey);
15-
this.publicKey = publicKey;
17+
this.s = Arrays.clone(s);
18+
this.hpk = Arrays.clone(hpk);
19+
this.nonce = Arrays.clone(nonce);
20+
this.t = Arrays.clone(t);
21+
this.rho = Arrays.clone(rho);
22+
}
23+
24+
public byte[] getT()
25+
{
26+
return Arrays.clone(t);
27+
}
28+
29+
public byte[] getRho()
30+
{
31+
return Arrays.clone(rho);
1632
}
1733

1834
public byte[] getPrivateKey()
1935
{
20-
return Arrays.clone(privateKey);
36+
return Arrays.concatenate(s, getPublicKey(), hpk, nonce);
2137
}
2238

2339
public byte[] getEncoded()
2440
{
25-
return Arrays.clone(privateKey);
41+
return getPrivateKey();
2642
}
2743

2844
public byte[] getPublicKey()
2945
{
30-
return Arrays.clone(publicKey);
46+
return Arrays.concatenate(t, rho);
47+
}
48+
49+
public byte[] getS()
50+
{
51+
return Arrays.clone(s);
52+
}
53+
54+
public byte[] getHPK()
55+
{
56+
return Arrays.clone(hpk);
57+
}
58+
59+
public byte[] getNonce()
60+
{
61+
return Arrays.clone(nonce);
3162
}
3263
}

core/src/main/java/org/bouncycastle/pqc/crypto/crystals/kyber/KyberPublicKeyParameters.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ public KyberPublicKeyParameters(KyberParameters params, byte[] t, byte[] rho)
2828
public KyberPublicKeyParameters(KyberParameters params, byte[] encoding)
2929
{
3030
super(false, params);
31-
this.t = Arrays.copyOfRange(encoding,0, encoding.length - KyberEngine.KyberSymBytes);
31+
this.t = Arrays.copyOfRange(encoding, 0, encoding.length - KyberEngine.KyberSymBytes);
3232
this.rho = Arrays.copyOfRange(encoding, encoding.length - KyberEngine.KyberSymBytes, encoding.length);
3333
}
3434

core/src/main/java/org/bouncycastle/pqc/crypto/util/PrivateKeyFactory.java

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import org.bouncycastle.asn1.ASN1OctetString;
1111
import org.bouncycastle.asn1.ASN1Primitive;
1212
import org.bouncycastle.asn1.ASN1Sequence;
13+
import org.bouncycastle.asn1.DEROctetString;
1314
import org.bouncycastle.asn1.bc.BCObjectIdentifiers;
1415
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
1516
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
@@ -205,18 +206,35 @@ else if (algOID.on(BCObjectIdentifiers.pqc_kem_ntru))
205206
}
206207
else if (algOID.on(BCObjectIdentifiers.pqc_kem_kyber))
207208
{
208-
byte[] keyEnc = ASN1OctetString.getInstance(keyInfo.parsePrivateKey()).getOctets();
209+
ASN1Sequence keyEnc = ASN1Sequence.getInstance(keyInfo.parsePrivateKey());
210+
209211
KyberParameters spParams = Utils.kyberParamsLookup(keyInfo.getPrivateKeyAlgorithm().getAlgorithm());
210212

211-
ASN1BitString pubKey = keyInfo.getPublicKeyData();
212-
if (pubKey != null)
213-
{
214-
return new KyberPrivateKeyParameters(spParams, keyEnc, pubKey.getOctets());
215-
}
216-
else
213+
int version = ASN1Integer.getInstance(keyEnc.getObjectAt(0)).intValueExact();
214+
if (version != 0)
217215
{
218-
return new KyberPrivateKeyParameters(spParams, keyEnc, null);
216+
throw new IOException("unknown private key version: " + version);
219217
}
218+
219+
if (keyInfo.getPublicKeyData() != null)
220+
{
221+
ASN1Sequence pubKey = ASN1Sequence.getInstance(keyInfo.getPublicKeyData().getOctets());
222+
return new KyberPrivateKeyParameters(spParams,
223+
DEROctetString.getInstance(keyEnc.getObjectAt(1)).getOctets(),
224+
DEROctetString.getInstance(keyEnc.getObjectAt(2)).getOctets(),
225+
DEROctetString.getInstance(keyEnc.getObjectAt(3)).getOctets(),
226+
ASN1OctetString.getInstance(pubKey.getObjectAt(0)).getOctets(), // t
227+
ASN1OctetString.getInstance(pubKey.getObjectAt(1)).getOctets()); // rho
228+
}
229+
else
230+
{
231+
return new KyberPrivateKeyParameters(spParams,
232+
ASN1OctetString.getInstance(keyEnc.getObjectAt(1)).getOctets(),
233+
ASN1OctetString.getInstance(keyEnc.getObjectAt(2)).getOctets(),
234+
ASN1OctetString.getInstance(keyEnc.getObjectAt(3)).getOctets(),
235+
null,
236+
null);
237+
}
220238
}
221239
else if (algOID.on(BCObjectIdentifiers.pqc_kem_ntrulprime))
222240
{

core/src/main/java/org/bouncycastle/pqc/crypto/util/PrivateKeyInfoFactory.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -251,12 +251,21 @@ else if (privateKey instanceof FalconPrivateKeyParameters)
251251
else if (privateKey instanceof KyberPrivateKeyParameters)
252252
{
253253
KyberPrivateKeyParameters params = (KyberPrivateKeyParameters)privateKey;
254+
255+
ASN1EncodableVector v = new ASN1EncodableVector();
254256

255-
byte[] encoding = params.getEncoded();
257+
v.add(new ASN1Integer(0));
258+
v.add(new DEROctetString(params.getS()));
259+
v.add(new DEROctetString(params.getHPK()));
260+
v.add(new DEROctetString(params.getNonce()));
256261

257262
AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(Utils.kyberOidLookup(params.getParameters()));
258263

259-
return new PrivateKeyInfo(algorithmIdentifier, new DEROctetString(encoding), attributes, params.getPublicKey());
264+
ASN1EncodableVector vPub = new ASN1EncodableVector();
265+
vPub.add(new DEROctetString(params.getT()));
266+
vPub.add(new DEROctetString(params.getRho()));
267+
268+
return new PrivateKeyInfo(algorithmIdentifier, new DERSequence(v), attributes, new DERSequence(vPub).getEncoded());
260269
}
261270
else if (privateKey instanceof NTRULPRimePrivateKeyParameters)
262271
{

0 commit comments

Comments
 (0)