Skip to content

Commit

Permalink
Merge branch '1809-pgp-librepgp-ocbencrypteddata' into 'main'
Browse files Browse the repository at this point in the history
1809 pgp librepgp ocbencrypteddata

See merge request root/bc-java!19
  • Loading branch information
dghgit committed Sep 12, 2024
2 parents 3c9c1fa + bb58c09 commit c005424
Show file tree
Hide file tree
Showing 8 changed files with 323 additions and 40 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package org.bouncycastle.bcpg;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.EOFException;
import java.io.IOException;
Expand All @@ -19,6 +18,7 @@ public class SymmetricKeyEncSessionPacket

/**
* Version 5 SKESK packet.
* LibrePGP only.
* Used only with {@link AEADEncDataPacket AED} packets.
*/
public static final int VERSION_5 = 5;
Expand All @@ -40,11 +40,12 @@ public class SymmetricKeyEncSessionPacket
private byte[] authTag; // V5, V6

public SymmetricKeyEncSessionPacket(
BCPGInputStream in)
throws IOException
BCPGInputStream in)
throws IOException
{
this(in, false);
}

public SymmetricKeyEncSessionPacket(
BCPGInputStream in,
boolean newPacketFormat)
Expand All @@ -63,30 +64,28 @@ public SymmetricKeyEncSessionPacket(
}
else if (version == VERSION_5 || version == VERSION_6)
{
// https://www.rfc-editor.org/rfc/rfc9580.html#section-5.3.2-3.2.1
// SymAlg + AEADAlg + S2KCount + S2K + IV
int next5Fields5Count = in.read();
int ivLen = 0;
if (version == VERSION_6)
{
// https://www.rfc-editor.org/rfc/rfc9580.html#section-5.3.2-3.2.1
// SymAlg + AEADAlg + S2KCount + S2K + IV
ivLen = in.read(); // next5Fields5Count
}
encAlgorithm = in.read();
aeadAlgorithm = in.read();
if (version == VERSION_6)
{
// https://www.rfc-editor.org/rfc/rfc9580.html#section-5.3.2-3.5.1
int s2kOctetCount = in.read();
ivLen = ivLen - 3 - s2kOctetCount;
}
else
{
ivLen = AEADUtils.getIVLength(aeadAlgorithm);
}

// https://www.rfc-editor.org/rfc/rfc9580.html#section-5.3.2-3.5.1
int s2kOctetCount = in.read();

//TODO: use this line to replace the following code?
s2k = new S2K(in);
// s2kBytes = new byte[s2kOctetCount];
// in.readFully(s2kBytes);
// try
// {
// s2k = new S2K(new ByteArrayInputStream(s2kBytes));
// }
// catch (UnsupportedPacketVersionException e)
// {
//
// // We gracefully catch the error.
// }

int ivLen = next5Fields5Count - 3 - s2kOctetCount;

iv = new byte[ivLen]; // also called nonce
if (in.read(iv) != iv.length)
{
Expand All @@ -108,7 +107,6 @@ else if (version == VERSION_5 || version == VERSION_6)
{
throw new UnsupportedPacketVersionException("Unsupported PGP symmetric-key encrypted session key packet version encountered: " + version);
}

}

/**
Expand Down Expand Up @@ -361,4 +359,4 @@ else if (version == VERSION_5 || version == VERSION_6)

out.writePacket(hasNewPacketFormat(), SYMMETRIC_KEY_ENC_SESSION, bOut.toByteArray());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ else if (publicPk.getVersion() == PublicKeyPacket.VERSION_4)
{
this.keyID = Pack.bigEndianToLong(fingerprint, fingerprint.length - 8);
}
else if (publicPk.getVersion() == PublicKeyPacket.VERSION_6)
else if (publicPk.getVersion() == PublicKeyPacket.LIBREPGP_5 || publicPk.getVersion() == PublicKeyPacket.VERSION_6)
{
this.keyID = Pack.bigEndianToLong(fingerprint, 0);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,15 @@ public static byte[] createUserKeyingMaterial(PublicKeyPacket pubKeyData, KeyFin
pOut.write(ecKey.getHashAlgorithm());
pOut.write(ecKey.getSymmetricKeyAlgorithm());
pOut.write(ANONYMOUS_SENDER);
pOut.write(fingerPrintCalculator.calculateFingerprint(pubKeyData));

byte[] fp = fingerPrintCalculator.calculateFingerprint(pubKeyData);
if (pubKeyData.getVersion() == PublicKeyPacket.LIBREPGP_5)
{
pOut.write(fp, 0, 20);
}
else
{
pOut.write(fp);
}
return pOut.toByteArray();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import org.bouncycastle.bcpg.SymmetricKeyAlgorithmTags;
import org.bouncycastle.bcpg.SymmetricKeyEncSessionPacket;
import org.bouncycastle.bcpg.SymmetricKeyUtils;
import org.bouncycastle.bcpg.UnsupportedPacketVersionException;
import org.bouncycastle.crypto.BlockCipher;
import org.bouncycastle.crypto.BufferedBlockCipher;
import org.bouncycastle.crypto.InvalidCipherTextException;
Expand Down Expand Up @@ -89,12 +90,24 @@ public byte[] recoverAEADEncryptedSessionData(SymmetricKeyEncSessionPacket keyDa
}

byte[] hkdfInfo = keyData.getAAData(); // Between v5 and v6, these bytes differ
int kekLen = SymmetricKeyUtils.getKeyLengthInOctets(keyData.getEncAlgorithm());

// HKDF
// secretKey := HKDF_sha256(ikm, hkdfInfo).generate()
byte[] kek = BcAEADUtil.generateHKDFBytes(ikm, null, hkdfInfo, kekLen);
final KeyParameter secretKey = new KeyParameter(kek);
KeyParameter secretKey;
if (keyData.getVersion() == SymmetricKeyEncSessionPacket.VERSION_5)
{
secretKey = new KeyParameter(ikm);
}
else if (keyData.getVersion() == SymmetricKeyEncSessionPacket.VERSION_6)
{
// HKDF
// secretKey := HKDF_sha256(ikm, hkdfInfo).generate()
int kekLen = SymmetricKeyUtils.getKeyLengthInOctets(keyData.getEncAlgorithm());
byte[] kek = BcAEADUtil.generateHKDFBytes(ikm, null, hkdfInfo, kekLen);
secretKey = new KeyParameter(kek);
}
else
{
throw new UnsupportedPacketVersionException("Unsupported SKESK packet version encountered: " + keyData.getVersion());
}

// AEAD
AEADBlockCipher aead = BcAEADUtil.createAEADCipher(keyData.getEncAlgorithm(), keyData.getAeadAlgorithm());
Expand Down Expand Up @@ -149,4 +162,4 @@ public PGPDataDecryptor createDataDecryptor(SymmetricEncIntegrityPacket seipd, P
{
return BcAEADUtil.createOpenPgpV6DataDecryptor(seipd, sessionKey);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import org.bouncycastle.bcpg.SymmetricEncIntegrityPacket;
import org.bouncycastle.bcpg.SymmetricKeyEncSessionPacket;
import org.bouncycastle.bcpg.SymmetricKeyUtils;
import org.bouncycastle.bcpg.UnsupportedPacketVersionException;
import org.bouncycastle.jcajce.util.DefaultJcaJceHelper;
import org.bouncycastle.jcajce.util.NamedJcaJceHelper;
import org.bouncycastle.jcajce.util.ProviderJcaJceHelper;
Expand Down Expand Up @@ -140,12 +141,24 @@ public byte[] recoverAEADEncryptedSessionData(SymmetricKeyEncSessionPacket keyDa
}

byte[] hkdfInfo = keyData.getAAData(); // between v5 and v6, these bytes differ
int kekLen = SymmetricKeyUtils.getKeyLengthInOctets(keyData.getEncAlgorithm());

// HKDF
// secretKey := HKDF_sha256(ikm, hkdfInfo).generate()
byte[] kek = JceAEADUtil.generateHKDFBytes(ikm, null, hkdfInfo, kekLen);
final SecretKey secretKey = new SecretKeySpec(kek, PGPUtil.getSymmetricCipherName(keyData.getEncAlgorithm()));
SecretKey secretKey;
if (keyData.getVersion() == SymmetricKeyEncSessionPacket.VERSION_5)
{
secretKey = new SecretKeySpec(ikm, PGPUtil.getSymmetricCipherName(keyData.getEncAlgorithm()));
}
else if (keyData.getVersion() == SymmetricKeyEncSessionPacket.VERSION_6)
{
// HKDF
// secretKey := HKDF_sha256(ikm, hkdfInfo).generate()
int kekLen = SymmetricKeyUtils.getKeyLengthInOctets(keyData.getEncAlgorithm());
byte[] kek = JceAEADUtil.generateHKDFBytes(ikm, null, hkdfInfo, kekLen);
secretKey = new SecretKeySpec(kek, PGPUtil.getSymmetricCipherName(keyData.getEncAlgorithm()));
}
else
{
throw new UnsupportedPacketVersionException("Unsupported SKESK packet version encountered: " + keyData.getVersion());
}

// AEAD
Cipher aead = aeadHelper.createAEADCipher(keyData.getEncAlgorithm(), keyData.getAeadAlgorithm());
Expand Down Expand Up @@ -201,4 +214,4 @@ public PGPDataDecryptor createDataDecryptor(SymmetricEncIntegrityPacket seipd, P
}
};
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@ private void parseAndEncodeKey()
isEncodingEqual("Fingerprint mismatch for the subkey.",
Hex.decode("E4557C2B02FFBF4B04F87401EC336AF7133D0F85BE7FD09BAEFD9CAEB8C93965"), it.next().getFingerprint());

it = secretKeys.getPublicKeys();
isEquals( "Primary key ID mismatch", 1816212655223104514L, it.next().getKeyID());
isEquals("Subkey ID mismatch", -1993550735865823413L, it.next().getKeyID());

bOut = new ByteArrayOutputStream();
BCPGOutputStream pOut = new BCPGOutputStream(bOut, PacketFormat.LEGACY);
secretKeys.encode(pOut);
Expand Down
Loading

0 comments on commit c005424

Please sign in to comment.