<PackageReference Include="BouncyCastle.Cryptography" Version="2.5.1" />

KeyAgreeRecipientInfoGenerator

using Org.BouncyCastle.Asn1; using Org.BouncyCastle.Asn1.Cms; using Org.BouncyCastle.Asn1.Cms.Ecc; using Org.BouncyCastle.Asn1.X509; using Org.BouncyCastle.Asn1.X9; using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Math; using Org.BouncyCastle.Security; using Org.BouncyCastle.X509; using System.Collections.Generic; using System.IO; namespace Org.BouncyCastle.Cms { internal class KeyAgreeRecipientInfoGenerator : RecipientInfoGenerator { private readonly List<KeyAgreeRecipientIdentifier> m_recipientIDs = new List<KeyAgreeRecipientIdentifier>(); private readonly List<AsymmetricKeyParameter> m_recipientKeys = new List<AsymmetricKeyParameter>(); private DerObjectIdentifier m_keyAgreementOid; private DerObjectIdentifier m_keyEncryptionOid; private AsymmetricCipherKeyPair m_senderKeyPair; internal DerObjectIdentifier KeyAgreementOid { set { m_keyAgreementOid = value; } } internal DerObjectIdentifier KeyEncryptionOid { set { m_keyEncryptionOid = value; } } internal AsymmetricCipherKeyPair SenderKeyPair { set { m_senderKeyPair = value; } } internal KeyAgreeRecipientInfoGenerator(IEnumerable<X509Certificate> recipientCerts) { foreach (X509Certificate recipientCert in recipientCerts) { m_recipientIDs.Add(new KeyAgreeRecipientIdentifier(CmsUtilities.GetIssuerAndSerialNumber(recipientCert))); m_recipientKeys.Add(recipientCert.GetPublicKey()); } } internal KeyAgreeRecipientInfoGenerator(byte[] subjectKeyID, AsymmetricKeyParameter publicKey) { m_recipientIDs.Add(new KeyAgreeRecipientIdentifier(new RecipientKeyIdentifier(subjectKeyID))); m_recipientKeys.Add(publicKey); } public RecipientInfo Generate(KeyParameter contentEncryptionKey, SecureRandom random) { byte[] key = contentEncryptionKey.GetKey(); AsymmetricKeyParameter public = m_senderKeyPair.Public; ICipherParameters cipherParameters = m_senderKeyPair.Private; OriginatorIdentifierOrKey originator; try { originator = new OriginatorIdentifierOrKey(CreateOriginatorPublicKey(public)); } catch (IOException ex) { throw new InvalidKeyException("cannot extract originator public key: " + ex?.ToString()); } Asn1OctetString ukm = null; if (CmsUtilities.IsMqv(m_keyAgreementOid)) try { IAsymmetricCipherKeyPairGenerator keyPairGenerator = GeneratorUtilities.GetKeyPairGenerator(m_keyAgreementOid); keyPairGenerator.Init(((ECPublicKeyParameters)public).CreateKeyGenerationParameters(random)); AsymmetricCipherKeyPair asymmetricCipherKeyPair = keyPairGenerator.GenerateKeyPair(); ukm = new DerOctetString(new MQVuserKeyingMaterial(CreateOriginatorPublicKey(asymmetricCipherKeyPair.Public), null)); cipherParameters = new MqvPrivateParameters((ECPrivateKeyParameters)cipherParameters, (ECPrivateKeyParameters)asymmetricCipherKeyPair.Private, (ECPublicKeyParameters)asymmetricCipherKeyPair.Public); } catch (IOException ex2) { throw new InvalidKeyException("cannot extract MQV ephemeral public key: " + ex2?.ToString()); } catch (SecurityUtilityException ex3) { throw new InvalidKeyException("cannot determine MQV ephemeral key pair parameters from public key: " + ex3?.ToString()); } DerSequence parameters = new DerSequence(m_keyEncryptionOid, DerNull.Instance); AlgorithmIdentifier keyEncryptionAlgorithm = new AlgorithmIdentifier(m_keyAgreementOid, parameters); Asn1EncodableVector asn1EncodableVector = new Asn1EncodableVector(m_recipientIDs.Count); for (int i = 0; i < m_recipientIDs.Count; i++) { KeyAgreeRecipientIdentifier id = m_recipientIDs[i]; ICipherParameters cipherParameters2 = m_recipientKeys[i]; if (m_keyAgreementOid.Id.Equals(CmsEnvelopedGenerator.ECMqvSha1Kdf)) cipherParameters2 = new MqvPublicParameters((ECPublicKeyParameters)cipherParameters2, (ECPublicKeyParameters)cipherParameters2); IBasicAgreement basicAgreementWithKdf = AgreementUtilities.GetBasicAgreementWithKdf(m_keyAgreementOid, m_keyEncryptionOid); basicAgreementWithKdf.Init(new ParametersWithRandom(cipherParameters, random)); BigInteger s = basicAgreementWithKdf.CalculateAgreement(cipherParameters2); int qLength = GeneratorUtilities.GetDefaultKeySize(m_keyEncryptionOid) / 8; byte[] keyBytes = X9IntegerConverter.IntegerToBytes(s, qLength); KeyParameter parameters2 = ParameterUtilities.CreateKeyParameter(m_keyEncryptionOid, keyBytes); IWrapper wrapper = WrapperUtilities.GetWrapper(m_keyEncryptionOid.Id); wrapper.Init(true, new ParametersWithRandom(parameters2, random)); Asn1OctetString encryptedKey = new DerOctetString(wrapper.Wrap(key, 0, key.Length)); asn1EncodableVector.Add(new RecipientEncryptedKey(id, encryptedKey)); } return new RecipientInfo(new KeyAgreeRecipientInfo(originator, ukm, keyEncryptionAlgorithm, new DerSequence(asn1EncodableVector))); } private static OriginatorPublicKey CreateOriginatorPublicKey(AsymmetricKeyParameter publicKey) { return CreateOriginatorPublicKey(SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(publicKey)); } private static OriginatorPublicKey CreateOriginatorPublicKey(SubjectPublicKeyInfo originatorKeyInfo) { return new OriginatorPublicKey(originatorKeyInfo.Algorithm, originatorKeyInfo.PublicKey); } } }