Skip to content

Commit f857fe1

Browse files
author
gefeili
committed
Add tests for PGPKeyEncryptionMethodGenerator and related classes
1 parent 24db506 commit f857fe1

File tree

6 files changed

+353
-70
lines changed

6 files changed

+353
-70
lines changed

pg/src/main/java/org/bouncycastle/bcpg/SymmetricKeyEncSessionPacket.java

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -337,27 +337,21 @@ public void encode(
337337
pOut.write(secKeyData);
338338
}
339339
}
340-
else if (version == VERSION_5)
340+
else
341341
{
342-
pOut.write(encAlgorithm);
343-
pOut.write(aeadAlgorithm);
344-
pOut.writeObject(s2k);
345-
pOut.write(iv);
346-
347-
if (secKeyData != null && secKeyData.length > 0)
342+
int s2kLen = 0;
343+
if (version == VERSION_6)
348344
{
349-
pOut.write(secKeyData);
345+
s2kLen = s2k.getEncoded().length;
346+
int count = 1 + 1 + 1 + s2kLen + iv.length;
347+
pOut.write(count); // len of 5 following fields
350348
}
351-
pOut.write(authTag);
352-
}
353-
else if (version == VERSION_6)
354-
{
355-
int s2kLen = s2k.getEncoded().length;
356-
int count = 1 + 1 + 1 + s2kLen + iv.length;
357-
pOut.write(count); // len of 5 following fields
358349
pOut.write(encAlgorithm);
359350
pOut.write(aeadAlgorithm);
360-
pOut.write(s2kLen);
351+
if (version == VERSION_6)
352+
{
353+
pOut.write(s2kLen);
354+
}
361355
pOut.writeObject(s2k);
362356
pOut.write(iv);
363357

pg/src/main/java/org/bouncycastle/openpgp/operator/PublicKeyKeyEncryptionMethodGenerator.java

Lines changed: 16 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ public ContainedPacket generate(PGPDataEncryptorBuilder dataEncryptorBuilder, by
198198
{
199199
keyId = pubKey.getKeyID();
200200
}
201-
byte[] encryptedSessionInfo = encryptSessionInfo(pubKey, sessionKey, (byte)dataEncryptorBuilder.getAlgorithm());
201+
byte[] encryptedSessionInfo = encryptSessionInfo(pubKey, sessionKey, (byte)dataEncryptorBuilder.getAlgorithm(), true);
202202
byte[][] encodedEncSessionInfo = encodeEncryptedSessionInfo(encryptedSessionInfo);
203203
return PublicKeyEncSessionPacket.createV3PKESKPacket(keyId, pubKey.getAlgorithm(), encodedEncSessionInfo);
204204
}
@@ -218,21 +218,21 @@ public ContainedPacket generate(PGPDataEncryptorBuilder dataEncryptorBuilder, by
218218
}
219219
// In V6, do not include the symmetric-key algorithm in the session-info
220220

221-
byte[] encryptedSessionInfo = encryptSessionInfo(pubKey, sessionKey, (byte)0);
221+
byte[] encryptedSessionInfo = encryptSessionInfo(pubKey, sessionKey, (byte)dataEncryptorBuilder.getAlgorithm(), false);
222222
byte[][] encodedEncSessionInfo = encodeEncryptedSessionInfo(encryptedSessionInfo);
223223
return PublicKeyEncSessionPacket.createV6PKESKPacket(keyVersion, keyFingerprint, pubKey.getAlgorithm(), encodedEncSessionInfo);
224224
}
225225
}
226226

227227
protected byte[] createSessionInfo(
228-
int algorithm,
228+
byte algorithm,
229229
byte[] keyBytes)
230230
{
231231
byte[] sessionInfo;
232232
if (algorithm != 0)
233233
{
234234
sessionInfo = new byte[keyBytes.length + 3];
235-
sessionInfo[0] = (byte)algorithm;
235+
sessionInfo[0] = algorithm;
236236
System.arraycopy(keyBytes, 0, sessionInfo, 1, keyBytes.length);
237237
addCheckSum(sessionInfo, 1);
238238
}
@@ -245,7 +245,7 @@ protected byte[] createSessionInfo(
245245
return sessionInfo;
246246
}
247247

248-
protected void addCheckSum(byte[] sessionInfo, int pos)
248+
private void addCheckSum(byte[] sessionInfo, int pos)
249249
{
250250
int check = 0;
251251

@@ -261,43 +261,33 @@ protected void addCheckSum(byte[] sessionInfo, int pos)
261261
/**
262262
* Encrypt a session key using the recipients public key.
263263
*
264-
* @param pubKey recipients public key
265-
// * @param fullSessionInfo full session info (sym-alg-id + session-key + 2 octet checksum)
266-
// * @param sessionInfoToEncrypt for v3: full session info; for v6: just the session-key
267-
* @param optSymAlgId for v3: session key algorithm ID; for v6: empty array
264+
* @param pubKey recipients public key
265+
* @param sessionKey session-key
266+
* @param symAlgId for v3: session key algorithm ID; for v6: 0
268267
* @return encrypted session info
269268
* @throws PGPException
270269
*/
271270
protected abstract byte[] encryptSessionInfo(PGPPublicKey pubKey,
272271
byte[] sessionKey,
273-
byte optSymAlgId)
272+
byte symAlgId,
273+
boolean isV3)
274274
throws PGPException;
275275

276276
protected static byte[] getSessionInfo(byte[] ephPubEncoding, byte optSymKeyAlgorithm, byte[] wrappedSessionKey)
277277
{
278-
int len = ephPubEncoding.length + wrappedSessionKey.length + 2;
278+
int len = ephPubEncoding.length + wrappedSessionKey.length + (optSymKeyAlgorithm == 0 ? 1 : 2);
279279
byte[] out = new byte[len];
280280
// ephemeral pub key
281281
System.arraycopy(ephPubEncoding, 0, out, 0, ephPubEncoding.length);
282282
// len of two/one next fields
283-
out[ephPubEncoding.length] = (byte)(wrappedSessionKey.length + 1);
283+
out[ephPubEncoding.length] = (byte)(len - ephPubEncoding.length - 1);
284284
// sym key alg
285-
out[ephPubEncoding.length + 1] = optSymKeyAlgorithm;
285+
if (optSymKeyAlgorithm != 0)
286+
{
287+
out[ephPubEncoding.length + 1] = optSymKeyAlgorithm;
288+
}
286289
// wrapped session key
287290
System.arraycopy(wrappedSessionKey, 0, out, len - wrappedSessionKey.length, wrappedSessionKey.length);
288291
return out;
289292
}
290-
291-
protected static byte[] getSessionInfo(byte[] ephPubEncoding, byte[] wrappedSessionKey)
292-
{
293-
int len = ephPubEncoding.length + wrappedSessionKey.length + 1;
294-
byte[] out = new byte[len];
295-
// ephemeral pub key
296-
System.arraycopy(ephPubEncoding, 0, out, 0, ephPubEncoding.length);
297-
// len of two/one next fields
298-
out[ephPubEncoding.length] = (byte)wrappedSessionKey.length;
299-
// wrapped session key
300-
System.arraycopy(wrappedSessionKey, 0, out, ephPubEncoding.length + 1, wrappedSessionKey.length);
301-
return out;
302-
}
303293
}

pg/src/main/java/org/bouncycastle/openpgp/operator/bc/BcPublicKeyKeyEncryptionMethodGenerator.java

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ public BcPublicKeyKeyEncryptionMethodGenerator setSecureRandom(SecureRandom rand
7575
}
7676

7777
@Override
78-
protected byte[] encryptSessionInfo(PGPPublicKey pubKey, byte[] sessionKey, byte optSymAlgId)
78+
protected byte[] encryptSessionInfo(PGPPublicKey pubKey, byte[] sessionKey, byte symAlgId, boolean isV3)
7979
throws PGPException
8080
{
8181
try
@@ -87,7 +87,7 @@ protected byte[] encryptSessionInfo(PGPPublicKey pubKey, byte[] sessionKey, byte
8787
if (pubKey.getAlgorithm() == PublicKeyAlgorithmTags.ECDH)
8888
{
8989
ECDHPublicBCPGKey ecPubKey = (ECDHPublicBCPGKey)pubKeyPacket.getKey();
90-
byte[] sessionInfo = createSessionInfo(optSymAlgId, sessionKey);
90+
byte[] sessionInfo = createSessionInfo(isV3 ? symAlgId : (byte)0, sessionKey);
9191
byte[] userKeyingMaterial = RFC6637Utils.createUserKeyingMaterial(pubKeyPacket, new BcKeyFingerprintCalculator());
9292

9393
// Legacy X25519
@@ -146,7 +146,7 @@ public void getEphPubEncoding(AsymmetricKeyParameter publicKey, byte[] ephPubEnc
146146
((X25519PublicKeyParameters)publicKey).encode(ephPubEncoding, 0);
147147
}
148148
},
149-
optSymAlgId);
149+
isV3 ? symAlgId : (byte)0);
150150
}
151151

152152
// X448
@@ -162,7 +162,7 @@ public void getEphPubEncoding(AsymmetricKeyParameter publicKey, byte[] ephPubEnc
162162
((X448PublicKeyParameters)publicKey).encode(ephPubEncoding, 0);
163163
}
164164
},
165-
optSymAlgId);
165+
isV3 ? symAlgId : (byte)0);
166166
}
167167

168168
// RSA / ElGamal etc.
@@ -171,7 +171,7 @@ public void getEphPubEncoding(AsymmetricKeyParameter publicKey, byte[] ephPubEnc
171171
AsymmetricBlockCipher c = BcImplProvider.createPublicKeyCipher(pubKey.getAlgorithm());
172172

173173
c.init(true, new ParametersWithRandom(cryptoPublicKey, random));
174-
byte[] sessionInfo = createSessionInfo(optSymAlgId, sessionKey);
174+
byte[] sessionInfo = createSessionInfo(isV3 ? symAlgId : (byte)0, sessionKey);
175175

176176
return c.processBlock(sessionInfo, 0, sessionInfo.length);
177177
}
@@ -221,8 +221,8 @@ private byte[] encryptSessionInfoWithECDHKey(byte[] sessionInfo,
221221

222222
// wrap the padded session info using the shared-secret public key
223223
// https://www.rfc-editor.org/rfc/rfc9580.html#section-11.5-16
224-
return getSessionInfo(new MPInteger(new BigInteger(1, ephPubEncoding))
225-
.getEncoded(), getWrapper(symmetricKeyAlgorithm, key, paddedSessionData));
224+
return getSessionInfo(new MPInteger(new BigInteger(1, ephPubEncoding)).getEncoded(), (byte) 0,
225+
getWrapper(symmetricKeyAlgorithm, key, paddedSessionData));
226226
}
227227

228228
private byte[] encryptSessionInfoWithX25519X448Key(PublicKeyPacket pubKeyPacket,
@@ -246,10 +246,6 @@ private byte[] encryptSessionInfoWithX25519X448Key(PublicKeyPacket pubKeyPacket,
246246
KeyParameter key = new KeyParameter(RFC6637KDFCalculator.createKey(hashAlgorithm, symmetricKeyAlgorithm,
247247
Arrays.concatenate(ephPubEncoding, pubKeyPacket.getKey().getEncoded(), secret), "OpenPGP " + algorithmName));
248248

249-
if (optSymAlgId == 0)
250-
{
251-
return getSessionInfo(ephPubEncoding, getWrapper(symmetricKeyAlgorithm, key, sessionKey));
252-
}
253249
return getSessionInfo(ephPubEncoding, optSymAlgId, getWrapper(symmetricKeyAlgorithm, key, sessionKey));
254250
}
255251

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

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,8 @@ public JcePublicKeyKeyEncryptionMethodGenerator setSecureRandom(SecureRandom ran
9292

9393
protected byte[] encryptSessionInfo(PGPPublicKey pubKey,
9494
byte[] sessionKey,
95-
byte optSymAlgId)
95+
byte optSymAlgId,
96+
boolean isV3)
9697
throws PGPException
9798
{
9899
try
@@ -102,7 +103,7 @@ protected byte[] encryptSessionInfo(PGPPublicKey pubKey,
102103
// ECDH
103104
if (pubKey.getAlgorithm() == PublicKeyAlgorithmTags.ECDH)
104105
{
105-
byte[] sessionInfo = createSessionInfo(optSymAlgId, sessionKey);
106+
byte[] sessionInfo = createSessionInfo(isV3 ? optSymAlgId : (byte)0, sessionKey);
106107
ECDHPublicBCPGKey ecKey = (ECDHPublicBCPGKey)pubKey.getPublicKeyPacket().getKey();
107108
String keyEncryptionOID = RFC6637Utils.getKeyEncryptionOID(ecKey.getSymmetricKeyAlgorithm()).getId();
108109
PublicKeyPacket pubKeyPacket = pubKey.getPublicKeyPacket();
@@ -111,7 +112,7 @@ protected byte[] encryptSessionInfo(PGPPublicKey pubKey,
111112
if (JcaJcePGPUtil.isX25519(ecKey.getCurveOID()))
112113
{
113114
return encryptSessionInfoWithECDHKey(pubKeyPacket, "X25519", cryptoPublicKey, keyEncryptionOID,
114-
ecKey.getSymmetricKeyAlgorithm(), sessionInfo, RFC6637Utils.getXDHAlgorithm(pubKeyPacket),
115+
ecKey.getSymmetricKeyAlgorithm(), sessionInfo, RFC6637Utils.getXDHAlgorithm(pubKeyPacket), optSymAlgId,
115116
new KeyPairGeneratorOperation()
116117
{
117118
@Override
@@ -135,7 +136,7 @@ public byte[] getEphPubEncoding(byte[] publicKeyData)
135136
else if (ecKey.getCurveOID().equals(EdECObjectIdentifiers.id_X448))
136137
{
137138
return encryptSessionInfoWithECDHKey(pubKeyPacket, "X448", cryptoPublicKey, keyEncryptionOID,
138-
ecKey.getSymmetricKeyAlgorithm(), sessionInfo, RFC6637Utils.getXDHAlgorithm(pubKeyPacket),
139+
ecKey.getSymmetricKeyAlgorithm(), sessionInfo, RFC6637Utils.getXDHAlgorithm(pubKeyPacket), optSymAlgId,
139140
new KeyPairGeneratorOperation()
140141
{
141142
@Override
@@ -159,7 +160,7 @@ public byte[] getEphPubEncoding(byte[] publicKeyData)
159160
else
160161
{
161162
return encryptSessionInfoWithECDHKey(pubKeyPacket, "EC", cryptoPublicKey, keyEncryptionOID,
162-
ecKey.getSymmetricKeyAlgorithm(), sessionInfo, RFC6637Utils.getAgreementAlgorithm(pubKeyPacket),
163+
ecKey.getSymmetricKeyAlgorithm(), sessionInfo, RFC6637Utils.getAgreementAlgorithm(pubKeyPacket), optSymAlgId,
163164
new KeyPairGeneratorOperation()
164165
{
165166
@Override
@@ -189,14 +190,14 @@ public byte[] getEphPubEncoding(byte[] ephPubEncoding)
189190
else if (pubKey.getAlgorithm() == PublicKeyAlgorithmTags.X25519)
190191
{
191192
return encryptSessionInfoWithX25519X448Key(pubKey, "X25519", cryptoPublicKey, NISTObjectIdentifiers.id_aes128_wrap.getId(),
192-
SymmetricKeyAlgorithmTags.AES_128, sessionKey, "X25519withSHA256HKDF", 255, optSymAlgId);
193+
SymmetricKeyAlgorithmTags.AES_128, sessionKey, "X25519withSHA256HKDF", 255, optSymAlgId, isV3);
193194
}
194195

195196
// X448
196197
else if (pubKey.getAlgorithm() == PublicKeyAlgorithmTags.X448)
197198
{
198199
return encryptSessionInfoWithX25519X448Key(pubKey, "X448", cryptoPublicKey, NISTObjectIdentifiers.id_aes256_wrap.getId(),
199-
SymmetricKeyAlgorithmTags.AES_256, sessionKey, "X448withSHA512HKDF", 448, optSymAlgId);
200+
SymmetricKeyAlgorithmTags.AES_256, sessionKey, "X448withSHA512HKDF", 448, optSymAlgId, isV3);
200201
}
201202

202203
// RSA / ElGamal etc.
@@ -205,7 +206,7 @@ else if (pubKey.getAlgorithm() == PublicKeyAlgorithmTags.X448)
205206
Cipher c = helper.createPublicKeyCipher(pubKey.getAlgorithm());
206207

207208
c.init(Cipher.ENCRYPT_MODE, cryptoPublicKey, random);
208-
byte[] sessionInfo = createSessionInfo(optSymAlgId, sessionKey);
209+
byte[] sessionInfo = createSessionInfo(isV3 ? optSymAlgId : (byte)0, sessionKey);
209210
return c.doFinal(sessionInfo);
210211
}
211212
}
@@ -245,7 +246,7 @@ private interface EphPubEncoding
245246
}
246247

247248
private byte[] encryptSessionInfoWithECDHKey(PublicKeyPacket pubKeyPacket, String algorithmName, PublicKey cryptoPublicKey, String keyEncryptionOID,
248-
int symmetricKeyAlgorithm, byte[] sessionInfo, String agreementName, KeyPairGeneratorOperation kpOperation,
249+
int symmetricKeyAlgorithm, byte[] sessionInfo, String agreementName, byte symAlgId, KeyPairGeneratorOperation kpOperation,
249250
EphPubEncoding getEncoding)
250251
throws GeneralSecurityException, IOException, PGPException
251252
{
@@ -264,8 +265,8 @@ private byte[] encryptSessionInfoWithECDHKey(PublicKeyPacket pubKeyPacket, Strin
264265

265266
// wrap the padded session info using the shared-secret public key
266267
// https://www.rfc-editor.org/rfc/rfc9580.html#section-11.5-16
267-
return getSessionInfo(new MPInteger(new BigInteger(1, ephPubEncoding))
268-
.getEncoded(), getWrapper(symmetricKeyAlgorithm, sessionInfo[0], secret, paddedSessionData));
268+
return getSessionInfo(new MPInteger(new BigInteger(1, ephPubEncoding)).getEncoded(),
269+
(byte)0, getWrapper(symmetricKeyAlgorithm, symAlgId, secret, paddedSessionData));
269270
}
270271

271272
/**
@@ -279,7 +280,7 @@ private byte[] encryptSessionInfoWithECDHKey(PublicKeyPacket pubKeyPacket, Strin
279280
*/
280281
private byte[] encryptSessionInfoWithX25519X448Key(PGPPublicKey pgpPublicKey, String algorithmName, PublicKey cryptoPublicKey, String keyEncryptionOID,
281282
int symmetricKeyAlgorithm, byte[] sessionKey, String agreementAlgorithmName, int keySize,
282-
byte optSymAlgId)
283+
byte optSymAlgId, boolean isV3)
283284
throws GeneralSecurityException, IOException, PGPException
284285
{
285286
KeyPairGenerator kpGen = helper.createKeyPairGenerator(algorithmName);
@@ -289,11 +290,7 @@ private byte[] encryptSessionInfoWithX25519X448Key(PGPPublicKey pgpPublicKey, St
289290
byte[] ephPubEncoding = SubjectPublicKeyInfo.getInstance(ephKP.getPublic().getEncoded()).getPublicKeyData().getBytes();
290291
HybridValueParameterSpec ukmSpec = JcaJcePGPUtil.getHybridValueParameterSpecWithPrepend(ephPubEncoding, pgpPublicKey.getPublicKeyPacket(), algorithmName);
291292
Key secret = JcaJcePGPUtil.getSecret(helper, cryptoPublicKey, keyEncryptionOID, agreementAlgorithmName, ukmSpec, ephKP.getPrivate());
292-
if (optSymAlgId == 0)
293-
{
294-
return getSessionInfo(ephPubEncoding, getWrapper(symmetricKeyAlgorithm, optSymAlgId, secret, sessionKey));
295-
}
296-
return getSessionInfo(ephPubEncoding, optSymAlgId, getWrapper(symmetricKeyAlgorithm, optSymAlgId, secret, sessionKey));
293+
return getSessionInfo(ephPubEncoding, isV3 ? optSymAlgId : (byte)0, getWrapper(symmetricKeyAlgorithm, optSymAlgId, secret, sessionKey));
297294
}
298295

299296
private byte[] getWrapper(int symmetricKeyAlgorithm, byte optSymAlgId, Key secret, byte[] sessionData)

0 commit comments

Comments
 (0)