Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
vanitasvitae committed Aug 5, 2024
1 parent 592aeaa commit 6356c79
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 51 deletions.
4 changes: 4 additions & 0 deletions pg/src/main/java/org/bouncycastle/bcpg/AEADEncDataPacket.java
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ public byte getVersion()
return version;
}

/**
* Return the algorithm-id of the symmetric encryption algorithm used to encrypt the data.
* @return symmetric encryption algorithm
*/
public byte getAlgorithm()
{
return algorithm;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,26 @@ public class PGPPublicKeyEncryptedData
this.keyData = keyData;
}

private boolean confirmCheckSum(
byte[][] sessionInfo)
{
byte[] sessionKey = sessionInfo[0];
byte[] checksum = sessionInfo[2];
if (checksum.length == 0)
{
// has no checksum (e.g. X25519, X448)
return true;
}

int check = 0;
for (int i = 0; i < sessionKey.length; i++)
{
check += sessionKey[i] & 0xff;
}
return checksum[0] == (byte) (check >> 8) &&
checksum[1] == (byte) (check);
}

private boolean confirmCheckSum(
byte[] sessionInfo)
{
Expand Down Expand Up @@ -111,42 +131,45 @@ public PGPSessionKey getSessionKey(
PublicKeyDataDecryptorFactory dataDecryptorFactory)
throws PGPException
{
if (encData instanceof AEADEncDataPacket)
byte[][] sessionInfo = dataDecryptorFactory.recoverSessionKey(keyData, encData);
if (!confirmCheckSum(sessionInfo))
{
return dataDecryptorFactory.recoverSessionKey(keyData, (AEADEncDataPacket) encData);
throw new PGPException("Key checksum failed.");
}

if (encData instanceof SymmetricEncDataPacket)
byte[] sessionKey = sessionInfo[0];
int algorithm;

// OCB (LibrePGP v5 style AEAD)
if (encData instanceof AEADEncDataPacket)
{
return dataDecryptorFactory.recoverSessionKey(keyData, (SymmetricEncDataPacket) encData);
algorithm = ((AEADEncDataPacket) encData).getAlgorithm();
}

return dataDecryptorFactory.recoverSessionKey(keyData, (SymmetricEncIntegrityPacket) encData);

byte[] sessionData = dataDecryptorFactory.recoverSessionData(keyData.getAlgorithm(), keyData.getEncSessionKey(), getVersion());
if (keyData.getAlgorithm() == PublicKeyAlgorithmTags.X25519 || keyData.getAlgorithm() == PublicKeyAlgorithmTags.X448)
// SEIPD (OpenPGP v4 / OpenPGP v6)
else if (encData instanceof SymmetricEncIntegrityPacket)
{
// X25519, X448 do no include checksum at the end of the session key

int cipherAlg;
byte[] sessionKey;
if (keyData.getVersion() == PublicKeyEncSessionPacket.VERSION_3)
SymmetricEncIntegrityPacket seipd = (SymmetricEncIntegrityPacket) encData;
if (seipd.getVersion() == SymmetricEncIntegrityPacket.VERSION_1)
{
cipherAlg = sessionData[0] & 0xff;
sessionKey = Arrays.copyOfRange(sessionData, 1, sessionData.length);
algorithm = sessionInfo[1][0];
}
else if (seipd.getVersion() == SymmetricEncIntegrityPacket.VERSION_2)
{
algorithm = seipd.getCipherAlgorithm();
}
else
{
cipherAlg = ((SymmetricEncIntegrityPacket) encData).getCipherAlgorithm();
sessionKey = sessionData;
throw new UnsupportedPacketVersionException("Unsupported SEIPD packet version: " + seipd.getVersion());
}
return new PGPSessionKey(cipherAlg, sessionKey);
}
if (!confirmCheckSum(sessionData))
// SED (Legacy, no integrity protection!)
else
{
throw new PGPKeyValidationException("key checksum failed");
algorithm = sessionInfo[1][0];
}
return new PGPSessionKey(sessionData[0] & 0xff, Arrays.copyOfRange(sessionData, 1, sessionData.length - 2));

return new PGPSessionKey(algorithm & 0xff, sessionKey);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,17 @@ public byte[][] recoverSessionKey(PublicKeyEncSessionPacket pkesk, InputStreamPa
{
case PublicKeyAlgorithmTags.X25519:

return recoverXSessionData(secKeyData[0], privKey, X25519PublicBCPGKey.LENGTH,
HashAlgorithmTags.SHA512, SymmetricKeyAlgorithmTags.AES_128, new X25519Agreement(),
"X25519", new PublicKeyParametersOperation()
{
@Override
public AsymmetricKeyParameter getPublicKeyParameters(byte[] pEnc, int pEncOff)
{
return new X25519PublicKeyParameters(pEnc, 0);
}
}, pkesk.getVersion());

case PublicKeyAlgorithmTags.X448:
return recoverXSessionData(secKeyData[0], privKey, X448PublicBCPGKey.LENGTH,
HashAlgorithmTags.SHA512, SymmetricKeyAlgorithmTags.AES_256, new X448Agreement(),
Expand Down Expand Up @@ -129,7 +140,12 @@ public AsymmetricKeyParameter getPublicKeyParameters(byte[] pEnc, int pEncOff)
rfc6637KDFCalculator = new RFC6637KDFCalculator(new BcPGPDigestCalculatorProvider().get(hashAlgorithm), symmetricKeyAlgorithm);
KeyParameter key = new KeyParameter(rfc6637KDFCalculator.createKey(secret, userKeyingMaterial));

return PGPPad.unpadSessionData(unwrapSessionData(keyEnc, symmetricKeyAlgorithm, key));
byte[] decrypted = PGPPad.unpadSessionData(unwrapSessionData(keyEnc, symmetricKeyAlgorithm, key));
return new byte[][] {
Arrays.copyOfRange(decrypted, 0, decrypted.length - 3),
Arrays.copyOfRange(decrypted, decrypted.length - 3, decrypted.length - 2),
Arrays.copyOfRange(decrypted, decrypted.length - 2, decrypted.length),
};
}
} catch (InvalidCipherTextException e) {
throw new RuntimeException(e);
Expand All @@ -143,44 +159,35 @@ public AsymmetricKeyParameter getPublicKeyParameters(byte[] pEnc, int pEncOff)
public byte[] recoverSessionData(int keyAlgorithm, byte[][] secKeyData, int pkeskVersion)
throws PGPException
{
if (keyAlgorithm != pgpPrivKey.getPublicKeyPacket().getAlgorithm())
{
throw new PGPException("Public-Key algorithm field of the Public-Key Encrypted Session Key Packet" +
" does not match the private keys algorithm.");
}
try
{
AsymmetricKeyParameter privKey = KEY_CONVERTER.getPrivateKey(pgpPrivKey);

if (keyAlgorithm == PublicKeyAlgorithmTags.X25519)
{
byte[] ephemeralKey = Arrays.copyOfRange(secKeyData[0], 0, X25519PublicBCPGKey.LENGTH);
int skLen = secKeyData[0][X25519PublicBCPGKey.LENGTH];
byte[] encSessionKey = containsSKAlg(pkeskVersion) ?
Arrays.copyOfRange(secKeyData[0], X25519PublicBCPGKey.LENGTH + 2, secKeyData[0].length - 1) :
Arrays.copyOfRange(secKeyData[0], X25519PublicBCPGKey.LENGTH + 1, secKeyData[0].length);
byte[] decSessionKey = recoverXSessionData2()
return recoverXSessionData(secKeyData[0], privKey, X25519PublicBCPGKey.LENGTH, HashAlgorithmTags.SHA256,
SymmetricKeyAlgorithmTags.AES_128, new X25519Agreement(), "X25519", new PublicKeyParametersOperation()
{
@Override
public AsymmetricKeyParameter getPublicKeyParameters(byte[] pEnc, int pEncOff)
byte[][] decrypted = recoverXSessionData(secKeyData[0], privKey, X25519PublicBCPGKey.LENGTH, HashAlgorithmTags.SHA256,
SymmetricKeyAlgorithmTags.AES_128, new X25519Agreement(), "X25519", new PublicKeyParametersOperation()
{
return new X25519PublicKeyParameters(pEnc, 0);
}
}, pkeskVersion);
@Override
public AsymmetricKeyParameter getPublicKeyParameters(byte[] pEnc, int pEncOff)
{
return new X25519PublicKeyParameters(pEnc, 0);
}
}, pkeskVersion);
return Arrays.concatenate(decrypted[0], decrypted[1], decrypted[2]);
}
else if (keyAlgorithm == PublicKeyAlgorithmTags.X448)
{
return recoverXSessionData(secKeyData[0], privKey, X448PublicBCPGKey.LENGTH, HashAlgorithmTags.SHA512,
SymmetricKeyAlgorithmTags.AES_256, new X448Agreement(), "X448", new PublicKeyParametersOperation()
{
@Override
public AsymmetricKeyParameter getPublicKeyParameters(byte[] pEnc, int pEncOff)
byte[][] decrypted = recoverXSessionData(secKeyData[0], privKey, X448PublicBCPGKey.LENGTH, HashAlgorithmTags.SHA512,
SymmetricKeyAlgorithmTags.AES_256, new X448Agreement(), "X448", new PublicKeyParametersOperation()
{
return new X448PublicKeyParameters(pEnc, 0);
}
}, pkeskVersion);
@Override
public AsymmetricKeyParameter getPublicKeyParameters(byte[] pEnc, int pEncOff)
{
return new X448PublicKeyParameters(pEnc, 0);
}
}, pkeskVersion);
return Arrays.concatenate(decrypted[0], decrypted[1], decrypted[2]);
}
else if (keyAlgorithm == PublicKeyAlgorithmTags.ECDH)
{
Expand Down Expand Up @@ -220,7 +227,7 @@ else if (keyAlgorithm == PublicKeyAlgorithmTags.ECDH)
ECDomainParameters ecParameters = ((ECPrivateKeyParameters)privKey).getParameters();

ECPublicKeyParameters ephPub = new ECPublicKeyParameters(ecParameters.getCurve().decodePoint(pEnc),
ecParameters);
ecParameters);

ECDHBasicAgreement agreement = new ECDHBasicAgreement();
agreement.init(privKey);
Expand All @@ -244,7 +251,7 @@ else if (keyAlgorithm == PublicKeyAlgorithmTags.ECDH)
c1.init(false, privKey);

if (keyAlgorithm == PublicKeyAlgorithmTags.RSA_ENCRYPT
|| keyAlgorithm == PublicKeyAlgorithmTags.RSA_GENERAL)
|| keyAlgorithm == PublicKeyAlgorithmTags.RSA_GENERAL)
{
byte[] bi = secKeyData[0];

Expand Down

0 comments on commit 6356c79

Please sign in to comment.