Skip to content

Commit 24db506

Browse files
author
gefeili
committed
Move checksum from PGPEncryptedDataGenerator to PublicKeyKeyEncryptionMethodGenerator
1 parent 8ff3e17 commit 24db506

File tree

6 files changed

+73
-98
lines changed

6 files changed

+73
-98
lines changed

pg/src/main/java/org/bouncycastle/openpgp/PGPEncryptedDataGenerator.java

Lines changed: 1 addition & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -139,42 +139,6 @@ public void addMethod(PGPKeyEncryptionMethodGenerator method)
139139
methods.add(method);
140140
}
141141

142-
/**
143-
* Write a checksum into the last two bytes of the array.
144-
*
145-
* @param sessionInfo byte array
146-
*/
147-
private void addCheckSum(
148-
byte[] sessionInfo)
149-
{
150-
int check = 0;
151-
152-
for (int i = 1; i != sessionInfo.length - 2; i++)
153-
{
154-
check += sessionInfo[i] & 0xff;
155-
}
156-
157-
sessionInfo[sessionInfo.length - 2] = (byte)(check >> 8);
158-
sessionInfo[sessionInfo.length - 1] = (byte)(check);
159-
}
160-
161-
/**
162-
* Create a session info array containing of the algorithm-id followed by the key and a two-byte checksum.
163-
*
164-
* @param algorithm symmetric algorithm
165-
* @param keyBytes bytes of the key
166-
* @return array of algorithm, key and checksum
167-
*/
168-
private byte[] createSessionInfo(
169-
int algorithm,
170-
byte[] keyBytes)
171-
{
172-
byte[] sessionInfo = new byte[keyBytes.length + 3];
173-
sessionInfo[0] = (byte)algorithm;
174-
System.arraycopy(keyBytes, 0, sessionInfo, 1, keyBytes.length);
175-
addCheckSum(sessionInfo);
176-
return sessionInfo;
177-
}
178142

179143
/**
180144
* Create an OutputStream based on the configured methods.
@@ -226,7 +190,6 @@ private OutputStream open(
226190
if (dataEncryptorBuilder.getAeadAlgorithm() != -1 && !isV5StyleAEAD)
227191
{
228192
sessionKey = PGPUtil.makeRandomKey(defAlgorithm, rand);
229-
sessionInfo = createSessionInfo(defAlgorithm, sessionKey);
230193
// In OpenPGP v6, we need an additional step to derive a message key and IV from the session info.
231194
// Since we cannot inject the IV into the data encryptor, we append it to the message key.
232195
byte[] info = SymmetricEncIntegrityPacket.createAAData(
@@ -246,8 +209,6 @@ else if (directS2K)
246209
else
247210
{
248211
sessionKey = PGPUtil.makeRandomKey(defAlgorithm, rand);
249-
// prepend algorithm, append checksum
250-
sessionInfo = createSessionInfo(defAlgorithm, sessionKey);
251212
messageKey = sessionKey;
252213
}
253214

@@ -257,7 +218,7 @@ else if (directS2K)
257218
for (int i = 0; i < methods.size(); i++)
258219
{
259220
PGPKeyEncryptionMethodGenerator method = methods.get(i);
260-
pOut.writePacket(method.generate(dataEncryptorBuilder, sessionInfo));
221+
pOut.writePacket(method.generate(dataEncryptorBuilder, sessionKey));
261222
}
262223
try
263224
{

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

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ public byte[] getKey(int encAlgorithm)
180180
* version 2 only.
181181
* A SKESKv6 packet MUST NOT precede a SEIPDv1, OED or SED packet.
182182
*
183-
* @param sessionInfo session data generated by the encrypted data generator.
183+
* @param sessionKey session data generated by the encrypted data generator.
184184
* @return a packet encoding the provided information and the configuration of this instance.
185185
* @throws PGPException if an error occurs constructing the packet.
186186
* @see <a href="https://www.rfc-editor.org/rfc/rfc9580.html#name-version-4-symmetric-key-enc">
@@ -190,26 +190,21 @@ public byte[] getKey(int encAlgorithm)
190190
* @see <a href="https://www.rfc-editor.org/rfc/rfc9580.html#name-version-6-symmetric-key-enc">
191191
* RFC9580 - Symmetric-Key Encrypted Session-Key Packet version 6</a>
192192
*/
193-
public ContainedPacket generate(PGPDataEncryptorBuilder dataEncryptorBuilder, byte[] sessionInfo)
193+
public ContainedPacket generate(PGPDataEncryptorBuilder dataEncryptorBuilder, byte[] sessionKey)
194194
throws PGPException
195195
{
196196
int kekAlgorithm = getSessionKeyWrapperAlgorithm(dataEncryptorBuilder.getAlgorithm());
197197
if (dataEncryptorBuilder.getAeadAlgorithm() <= 0)
198198
{
199-
if (sessionInfo == null)
199+
if (sessionKey == null)
200200
{
201201
return SymmetricKeyEncSessionPacket.createV4Packet(kekAlgorithm, s2k, null);
202202
}
203203

204204
byte[] key = getKey(kekAlgorithm);
205-
//
206-
// the passed in session info has the an RSA/ElGamal checksum added to it, for PBE this is not included.
207-
//
208-
byte[] nSessionInfo = new byte[sessionInfo.length - 2];
209205

210-
System.arraycopy(sessionInfo, 0, nSessionInfo, 0, nSessionInfo.length);
211-
212-
return SymmetricKeyEncSessionPacket.createV4Packet(kekAlgorithm, s2k, encryptSessionInfo(kekAlgorithm, key, nSessionInfo));
206+
return SymmetricKeyEncSessionPacket.createV4Packet(kekAlgorithm, s2k, encryptSessionInfo(kekAlgorithm, key,
207+
Arrays.prepend(sessionKey, (byte)dataEncryptorBuilder.getAlgorithm())));
213208
}
214209
else
215210
{
@@ -232,7 +227,6 @@ public ContainedPacket generate(PGPDataEncryptorBuilder dataEncryptorBuilder, by
232227
random.nextBytes(iv);
233228

234229
int tagLen = AEADUtils.getAuthTagLength(aeadAlgorithm);
235-
byte[] sessionKey = getSessionKey(sessionInfo);
236230
byte[] eskAndTag = getEskAndTag(kekAlgorithm, aeadAlgorithm, sessionKey, ikm, iv, info);
237231
byte[] esk = Arrays.copyOfRange(eskAndTag, 0, eskAndTag.length - tagLen);
238232
byte[] tag = Arrays.copyOfRange(eskAndTag, esk.length, eskAndTag.length);
@@ -248,13 +242,6 @@ public ContainedPacket generate(PGPDataEncryptorBuilder dataEncryptorBuilder, by
248242
}
249243
}
250244

251-
protected byte[] getSessionKey(byte[] sessionInfo)
252-
{
253-
byte[] sessionKey = new byte[sessionInfo.length - 3];
254-
System.arraycopy(sessionInfo, 1, sessionKey, 0, sessionKey.length);
255-
return sessionKey;
256-
}
257-
258245
abstract protected byte[] encryptSessionInfo(int encAlgorithm, byte[] key, byte[] sessionInfo)
259246
throws PGPException;
260247

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@
1010
public interface PGPKeyEncryptionMethodGenerator
1111
{
1212

13-
ContainedPacket generate(PGPDataEncryptorBuilder dataEncryptorBuilder, byte[] sessionInfo)
13+
ContainedPacket generate(PGPDataEncryptorBuilder dataEncryptorBuilder, byte[] sessionKey)
1414
throws PGPException;
1515
}

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

Lines changed: 41 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -176,15 +176,15 @@ private byte[] convertToEncodedMPI(byte[] encryptedSessionInfo)
176176
* of version 2 only.
177177
* PKESKv6 packets are used with keys that support {@link org.bouncycastle.bcpg.sig.Features#FEATURE_SEIPD_V2}.
178178
*
179-
* @param sessionInfo session-key algorithm id + session-key + checksum
179+
* @param sessionKey session-key algorithm id + session-key + checksum
180180
* @return PKESKv6 or v3 packet
181181
* @throws PGPException if the PKESK packet cannot be generated
182182
* @see <a href="https://www.rfc-editor.org/rfc/rfc9580.html#name-version-6-public-key-encryp">
183183
* RFC9580 - Version 6 Public Key Encrypted Session Key Packet</a>
184184
* @see <a href="https://www.rfc-editor.org/rfc/rfc9580.html#name-version-3-public-key-encryp">
185185
* RFC9580 - Version 3 Public Key Encrypted Session Key Packet</a>
186186
*/
187-
public ContainedPacket generate(PGPDataEncryptorBuilder dataEncryptorBuilder, byte[] sessionInfo)
187+
public ContainedPacket generate(PGPDataEncryptorBuilder dataEncryptorBuilder, byte[] sessionKey)
188188
throws PGPException
189189
{
190190
if (dataEncryptorBuilder.getAeadAlgorithm() <= 0 || dataEncryptorBuilder.isV5StyleAEAD())
@@ -198,7 +198,7 @@ public ContainedPacket generate(PGPDataEncryptorBuilder dataEncryptorBuilder, by
198198
{
199199
keyId = pubKey.getKeyID();
200200
}
201-
byte[] encryptedSessionInfo = encryptSessionInfo(pubKey, sessionInfo, sessionInfo, sessionInfo[0]);
201+
byte[] encryptedSessionInfo = encryptSessionInfo(pubKey, sessionKey, (byte)dataEncryptorBuilder.getAlgorithm());
202202
byte[][] encodedEncSessionInfo = encodeEncryptedSessionInfo(encryptedSessionInfo);
203203
return PublicKeyEncSessionPacket.createV3PKESKPacket(keyId, pubKey.getAlgorithm(), encodedEncSessionInfo);
204204
}
@@ -217,28 +217,59 @@ public ContainedPacket generate(PGPDataEncryptorBuilder dataEncryptorBuilder, by
217217
keyVersion = pubKey.getVersion();
218218
}
219219
// In V6, do not include the symmetric-key algorithm in the session-info
220-
byte[] sessionInfoWithoutAlgId = new byte[sessionInfo.length - 1];
221-
System.arraycopy(sessionInfo, 1, sessionInfoWithoutAlgId, 0, sessionInfoWithoutAlgId.length);
222220

223-
byte[] encryptedSessionInfo = encryptSessionInfo(pubKey, sessionInfo, sessionInfoWithoutAlgId, (byte)0);
221+
byte[] encryptedSessionInfo = encryptSessionInfo(pubKey, sessionKey, (byte)0);
224222
byte[][] encodedEncSessionInfo = encodeEncryptedSessionInfo(encryptedSessionInfo);
225223
return PublicKeyEncSessionPacket.createV6PKESKPacket(keyVersion, keyFingerprint, pubKey.getAlgorithm(), encodedEncSessionInfo);
226224
}
227225
}
228226

227+
protected byte[] createSessionInfo(
228+
int algorithm,
229+
byte[] keyBytes)
230+
{
231+
byte[] sessionInfo;
232+
if (algorithm != 0)
233+
{
234+
sessionInfo = new byte[keyBytes.length + 3];
235+
sessionInfo[0] = (byte)algorithm;
236+
System.arraycopy(keyBytes, 0, sessionInfo, 1, keyBytes.length);
237+
addCheckSum(sessionInfo, 1);
238+
}
239+
else
240+
{
241+
sessionInfo = new byte[keyBytes.length + 2];
242+
System.arraycopy(keyBytes, 0, sessionInfo, 0, keyBytes.length);
243+
addCheckSum(sessionInfo, 0);
244+
}
245+
return sessionInfo;
246+
}
247+
248+
protected void addCheckSum(byte[] sessionInfo, int pos)
249+
{
250+
int check = 0;
251+
252+
for (int i = pos; i != sessionInfo.length - 2; i++)
253+
{
254+
check += sessionInfo[i] & 0xff;
255+
}
256+
257+
sessionInfo[sessionInfo.length - 2] = (byte)(check >> 8);
258+
sessionInfo[sessionInfo.length - 1] = (byte)(check);
259+
}
260+
229261
/**
230262
* Encrypt a session key using the recipients public key.
231263
*
232264
* @param pubKey recipients public key
233-
* @param fullSessionInfo full session info (sym-alg-id + session-key + 2 octet checksum)
234-
* @param sessionInfoToEncrypt for v3: full session info; for v6: just the session-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
235267
* @param optSymAlgId for v3: session key algorithm ID; for v6: empty array
236268
* @return encrypted session info
237269
* @throws PGPException
238270
*/
239271
protected abstract byte[] encryptSessionInfo(PGPPublicKey pubKey,
240-
byte[] fullSessionInfo,
241-
byte[] sessionInfoToEncrypt,
272+
byte[] sessionKey,
242273
byte optSymAlgId)
243274
throws PGPException;
244275

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

Lines changed: 10 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[] fullSessionInfo, byte[] sessionInfoToEncrypt, byte optSymAlgId)
78+
protected byte[] encryptSessionInfo(PGPPublicKey pubKey, byte[] sessionKey, byte optSymAlgId)
7979
throws PGPException
8080
{
8181
try
@@ -87,6 +87,7 @@ protected byte[] encryptSessionInfo(PGPPublicKey pubKey, byte[] fullSessionInfo,
8787
if (pubKey.getAlgorithm() == PublicKeyAlgorithmTags.ECDH)
8888
{
8989
ECDHPublicBCPGKey ecPubKey = (ECDHPublicBCPGKey)pubKeyPacket.getKey();
90+
byte[] sessionInfo = createSessionInfo(optSymAlgId, sessionKey);
9091
byte[] userKeyingMaterial = RFC6637Utils.createUserKeyingMaterial(pubKeyPacket, new BcKeyFingerprintCalculator());
9192

9293
// Legacy X25519
@@ -99,7 +100,7 @@ protected byte[] encryptSessionInfo(PGPPublicKey pubKey, byte[] fullSessionInfo,
99100
byte[] ephPubEncoding = new byte[1 + X25519PublicKeyParameters.KEY_SIZE];
100101
ephPubEncoding[0] = X_HDR;
101102
((X25519PublicKeyParameters)ephKp.getPublic()).encode(ephPubEncoding, 1);
102-
return encryptSessionInfoWithECDHKey(sessionInfoToEncrypt, secret, userKeyingMaterial, ephPubEncoding, ecPubKey.getHashAlgorithm(), ecPubKey.getSymmetricKeyAlgorithm());
103+
return encryptSessionInfoWithECDHKey(sessionInfo, secret, userKeyingMaterial, ephPubEncoding, ecPubKey.getHashAlgorithm(), ecPubKey.getSymmetricKeyAlgorithm());
103104
}
104105

105106
// LegacyX448
@@ -112,7 +113,7 @@ else if (ecPubKey.getCurveOID().equals(EdECObjectIdentifiers.id_X448))
112113
byte[] ephPubEncoding = new byte[1 + X448PublicKeyParameters.KEY_SIZE];
113114
ephPubEncoding[0] = X_HDR;
114115
((X448PublicKeyParameters)ephKp.getPublic()).encode(ephPubEncoding, 1);
115-
return encryptSessionInfoWithECDHKey(sessionInfoToEncrypt, secret, userKeyingMaterial, ephPubEncoding, ecPubKey.getHashAlgorithm(), ecPubKey.getSymmetricKeyAlgorithm());
116+
return encryptSessionInfoWithECDHKey(sessionInfo, secret, userKeyingMaterial, ephPubEncoding, ecPubKey.getHashAlgorithm(), ecPubKey.getSymmetricKeyAlgorithm());
116117
}
117118

118119
// Other ECDH curves
@@ -128,14 +129,14 @@ else if (ecPubKey.getCurveOID().equals(EdECObjectIdentifiers.id_X448))
128129

129130
byte[] ephPubEncoding = ((ECPublicKeyParameters)ephKp.getPublic()).getQ().getEncoded(false);
130131

131-
return encryptSessionInfoWithECDHKey(sessionInfoToEncrypt, secret, userKeyingMaterial, ephPubEncoding, ecPubKey.getHashAlgorithm(), ecPubKey.getSymmetricKeyAlgorithm());
132+
return encryptSessionInfoWithECDHKey(sessionInfo, secret, userKeyingMaterial, ephPubEncoding, ecPubKey.getHashAlgorithm(), ecPubKey.getSymmetricKeyAlgorithm());
132133
}
133134
}
134135

135136
// X25519
136137
else if (pubKey.getAlgorithm() == PublicKeyAlgorithmTags.X25519)
137138
{
138-
return encryptSessionInfoWithX25519X448Key(pubKeyPacket, fullSessionInfo, HashAlgorithmTags.SHA256, SymmetricKeyAlgorithmTags.AES_128, "X25519",
139+
return encryptSessionInfoWithX25519X448Key(pubKeyPacket, sessionKey, HashAlgorithmTags.SHA256, SymmetricKeyAlgorithmTags.AES_128, "X25519",
139140
new X25519KeyPairGenerator(), new X25519KeyGenerationParameters(random), new X25519Agreement(), cryptoPublicKey, X25519PublicKeyParameters.KEY_SIZE,
140141
new EphPubEncodingOperation()
141142
{
@@ -151,7 +152,7 @@ public void getEphPubEncoding(AsymmetricKeyParameter publicKey, byte[] ephPubEnc
151152
// X448
152153
else if (pubKey.getAlgorithm() == PublicKeyAlgorithmTags.X448)
153154
{
154-
return encryptSessionInfoWithX25519X448Key(pubKeyPacket, fullSessionInfo, HashAlgorithmTags.SHA512, SymmetricKeyAlgorithmTags.AES_256, "X448",
155+
return encryptSessionInfoWithX25519X448Key(pubKeyPacket, sessionKey, HashAlgorithmTags.SHA512, SymmetricKeyAlgorithmTags.AES_256, "X448",
155156
new X448KeyPairGenerator(), new X448KeyGenerationParameters(random), new X448Agreement(), cryptoPublicKey, X448PublicKeyParameters.KEY_SIZE,
156157
new EphPubEncodingOperation()
157158
{
@@ -170,8 +171,9 @@ public void getEphPubEncoding(AsymmetricKeyParameter publicKey, byte[] ephPubEnc
170171
AsymmetricBlockCipher c = BcImplProvider.createPublicKeyCipher(pubKey.getAlgorithm());
171172

172173
c.init(true, new ParametersWithRandom(cryptoPublicKey, random));
174+
byte[] sessionInfo = createSessionInfo(optSymAlgId, sessionKey);
173175

174-
return c.processBlock(sessionInfoToEncrypt, 0, sessionInfoToEncrypt.length);
176+
return c.processBlock(sessionInfo, 0, sessionInfo.length);
175177
}
176178
}
177179
catch (Exception e)
@@ -224,7 +226,7 @@ private byte[] encryptSessionInfoWithECDHKey(byte[] sessionInfo,
224226
}
225227

226228
private byte[] encryptSessionInfoWithX25519X448Key(PublicKeyPacket pubKeyPacket,
227-
byte[] sessionInfo,
229+
byte[] sessionKey,
228230
int hashAlgorithm,
229231
int symmetricKeyAlgorithm,
230232
String algorithmName,
@@ -244,9 +246,6 @@ private byte[] encryptSessionInfoWithX25519X448Key(PublicKeyPacket pubKeyPacket,
244246
KeyParameter key = new KeyParameter(RFC6637KDFCalculator.createKey(hashAlgorithm, symmetricKeyAlgorithm,
245247
Arrays.concatenate(ephPubEncoding, pubKeyPacket.getKey().getEncoded(), secret), "OpenPGP " + algorithmName));
246248

247-
//No checksum and padding
248-
byte[] sessionKey = new byte[sessionInfo.length - 3];
249-
System.arraycopy(sessionInfo, 1, sessionKey, 0, sessionKey.length);
250249
if (optSymAlgId == 0)
251250
{
252251
return getSessionInfo(ephPubEncoding, getWrapper(symmetricKeyAlgorithm, key, sessionKey));

0 commit comments

Comments
 (0)