summary refs log tree commit diff
path: root/crypto/src/openpgp/PgpPublicKeyEncryptedData.cs
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/src/openpgp/PgpPublicKeyEncryptedData.cs')
-rw-r--r--crypto/src/openpgp/PgpPublicKeyEncryptedData.cs156
1 files changed, 97 insertions, 59 deletions
diff --git a/crypto/src/openpgp/PgpPublicKeyEncryptedData.cs b/crypto/src/openpgp/PgpPublicKeyEncryptedData.cs

index 04fe3ad37..8c6fcda53 100644 --- a/crypto/src/openpgp/PgpPublicKeyEncryptedData.cs +++ b/crypto/src/openpgp/PgpPublicKeyEncryptedData.cs
@@ -1,19 +1,20 @@ using System; using System.IO; -using Org.BouncyCastle.Asn1.X9; +using Org.BouncyCastle.Asn1.Cryptlib; using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto.IO; -using Org.BouncyCastle.Crypto.Generators; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Math; -using Org.BouncyCastle.Math.EC; using Org.BouncyCastle.Security; using Org.BouncyCastle.Utilities.IO; +using Org.BouncyCastle.Crypto.Agreement; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Asn1.EdEC; namespace Org.BouncyCastle.Bcpg.OpenPgp { - /// <remarks>A public key encrypted data object.</remarks> + /// <remarks>A public key encrypted data object.</remarks> public class PgpPublicKeyEncryptedData : PgpEncryptedData { @@ -139,10 +140,9 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp { truncStream = new TruncatedStream(encStream); - string digestName = PgpUtilities.GetDigestName(HashAlgorithmTag.Sha1); - IDigest digest = DigestUtilities.GetDigest(digestName); + IDigest digest = PgpUtilities.CreateDigest(HashAlgorithmTag.Sha1); - encStream = new DigestStream(truncStream, digest, null); + encStream = new DigestStream(truncStream, digest, null); } if (Streams.ReadFully(encStream, iv, 0, iv.Length) < iv.Length) @@ -189,76 +189,114 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp { byte[][] secKeyData = keyData.GetEncSessionKey(); - if (keyData.Algorithm == PublicKeyAlgorithmTag.ECDH) + if (keyData.Algorithm != PublicKeyAlgorithmTag.ECDH) { - ECDHPublicBcpgKey ecKey = (ECDHPublicBcpgKey)privKey.PublicKeyPacket.Key; - X9ECParameters x9Params = ECKeyPairGenerator.FindECCurveByOid(ecKey.CurveOid); + IBufferedCipher cipher = GetKeyCipher(keyData.Algorithm); + + try + { + cipher.Init(false, privKey.Key); + } + catch (InvalidKeyException e) + { + throw new PgpException("error setting asymmetric cipher", e); + } + + if (keyData.Algorithm == PublicKeyAlgorithmTag.RsaEncrypt + || keyData.Algorithm == PublicKeyAlgorithmTag.RsaGeneral) + { + byte[] bi = secKeyData[0]; + + cipher.ProcessBytes(bi, 2, bi.Length - 2); + } + else + { + ElGamalPrivateKeyParameters k = (ElGamalPrivateKeyParameters)privKey.Key; + int size = (k.Parameters.P.BitLength + 7) / 8; + + ProcessEncodedMpi(cipher, size, secKeyData[0]); + ProcessEncodedMpi(cipher, size, secKeyData[1]); + } + + try + { + return cipher.DoFinal(); + } + catch (Exception e) + { + throw new PgpException("exception decrypting secret key", e); + } + } - byte[] enc = secKeyData[0]; + ECDHPublicBcpgKey ecPubKey = (ECDHPublicBcpgKey)privKey.PublicKeyPacket.Key; + byte[] enc = secKeyData[0]; - int pLen = ((((enc[0] & 0xff) << 8) + (enc[1] & 0xff)) + 7) / 8; - if ((2 + pLen + 1) > enc.Length) - throw new PgpException("encoded length out of range"); + int pLen = ((((enc[0] & 0xff) << 8) + (enc[1] & 0xff)) + 7) / 8; + if ((2 + pLen + 1) > enc.Length) + throw new PgpException("encoded length out of range"); - byte[] pEnc = new byte[pLen]; - Array.Copy(enc, 2, pEnc, 0, pLen); + byte[] pEnc = new byte[pLen]; + Array.Copy(enc, 2, pEnc, 0, pLen); - int keyLen = enc[pLen + 2]; - if ((2 + pLen + 1 + keyLen) > enc.Length) - throw new PgpException("encoded length out of range"); + int keyLen = enc[pLen + 2]; + if ((2 + pLen + 1 + keyLen) > enc.Length) + throw new PgpException("encoded length out of range"); - byte[] keyEnc = new byte[keyLen]; - Array.Copy(enc, 2 + pLen + 1, keyEnc, 0, keyEnc.Length); + byte[] keyEnc = new byte[keyLen]; + Array.Copy(enc, 2 + pLen + 1, keyEnc, 0, keyEnc.Length); - ECPoint publicPoint = x9Params.Curve.DecodePoint(pEnc); + var curveOid = ecPubKey.CurveOid; + byte[] secret; - ECPrivateKeyParameters privKeyParams = (ECPrivateKeyParameters)privKey.Key; - ECPoint S = publicPoint.Multiply(privKeyParams.D).Normalize(); + if (EdECObjectIdentifiers.id_X25519.Equals(curveOid) || + CryptlibObjectIdentifiers.curvey25519.Equals(curveOid)) + { + // skip the 0x40 header byte. + if (pEnc.Length != (1 + X25519PublicKeyParameters.KeySize) || 0x40 != pEnc[0]) + throw new ArgumentException("Invalid X25519 public key"); - KeyParameter key = new KeyParameter(Rfc6637Utilities.CreateKey(privKey.PublicKeyPacket, S)); + X25519PublicKeyParameters ephPub = new X25519PublicKeyParameters(pEnc, 1); - IWrapper w = PgpUtilities.CreateWrapper(ecKey.SymmetricKeyAlgorithm); - w.Init(false, key); + X25519Agreement agreement = new X25519Agreement(); + agreement.Init(privKey.Key); - return PgpPad.UnpadSessionData(w.Unwrap(keyEnc, 0, keyEnc.Length)); + secret = new byte[agreement.AgreementSize]; + agreement.CalculateAgreement(ephPub, secret, 0); } + else if (EdECObjectIdentifiers.id_X448.Equals(curveOid)) + { + // skip the 0x40 header byte. + if (pEnc.Length != (1 + X448PublicKeyParameters.KeySize) || 0x40 != pEnc[0]) + throw new ArgumentException("Invalid X448 public key"); - IBufferedCipher cipher = GetKeyCipher(keyData.Algorithm); + X448PublicKeyParameters ephPub = new X448PublicKeyParameters(pEnc, 1); - try - { - cipher.Init(false, privKey.Key); - } - catch (InvalidKeyException e) - { - throw new PgpException("error setting asymmetric cipher", e); - } + X448Agreement agreement = new X448Agreement(); + agreement.Init(privKey.Key); - if (keyData.Algorithm == PublicKeyAlgorithmTag.RsaEncrypt - || keyData.Algorithm == PublicKeyAlgorithmTag.RsaGeneral) - { - byte[] bi = secKeyData[0]; + secret = new byte[agreement.AgreementSize]; + agreement.CalculateAgreement(ephPub, secret, 0); + } + else + { + ECDomainParameters ecParameters = ((ECPrivateKeyParameters)privKey.Key).Parameters; - cipher.ProcessBytes(bi, 2, bi.Length - 2); - } - else - { - ElGamalPrivateKeyParameters k = (ElGamalPrivateKeyParameters)privKey.Key; - int size = (k.Parameters.P.BitLength + 7) / 8; + ECPublicKeyParameters ephPub = new ECPublicKeyParameters(ecParameters.Curve.DecodePoint(pEnc), + ecParameters); - ProcessEncodedMpi(cipher, size, secKeyData[0]); - ProcessEncodedMpi(cipher, size, secKeyData[1]); - } + ECDHBasicAgreement agreement = new ECDHBasicAgreement(); + agreement.Init(privKey.Key); + BigInteger S = agreement.CalculateAgreement(ephPub); + secret = BigIntegers.AsUnsignedByteArray(agreement.GetFieldSize(), S); + } - try - { - return cipher.DoFinal(); - } - catch (Exception e) - { - throw new PgpException("exception decrypting secret key", e); - } - } + KeyParameter key = new KeyParameter(Rfc6637Utilities.CreateKey(privKey.PublicKeyPacket, secret)); + + IWrapper w = PgpUtilities.CreateWrapper(ecPubKey.SymmetricKeyAlgorithm); + w.Init(false, key); + + return PgpPad.UnpadSessionData(w.Unwrap(keyEnc, 0, keyEnc.Length)); + } private static void ProcessEncodedMpi(IBufferedCipher cipher, int size, byte[] mpiEnc) {