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

KeyAgreeRecipientInformation

using Org.BouncyCastle.Asn1; using Org.BouncyCastle.Asn1.Cms; using Org.BouncyCastle.Asn1.Cms.Ecc; using Org.BouncyCastle.Asn1.CryptoPro; 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.Pkcs; using Org.BouncyCastle.Security; using System; using System.Collections.Generic; using System.IO; namespace Org.BouncyCastle.Cms { public class KeyAgreeRecipientInformation : RecipientInformation { private readonly KeyAgreeRecipientInfo m_info; private readonly Asn1OctetString m_encryptedKey; internal static void ReadRecipientInfo(IList<RecipientInformation> infos, KeyAgreeRecipientInfo info, CmsSecureReadable secureReadable) { try { foreach (Asn1Encodable recipientEncryptedKey in info.RecipientEncryptedKeys) { RecipientEncryptedKey instance = RecipientEncryptedKey.GetInstance(recipientEncryptedKey); KeyAgreeRecipientIdentifier identifier = instance.Identifier; IssuerAndSerialNumber issuerAndSerialNumber = identifier.IssuerAndSerialNumber; RecipientID recipientID = new RecipientID(); if (issuerAndSerialNumber != null) { recipientID.Issuer = issuerAndSerialNumber.Issuer; recipientID.SerialNumber = issuerAndSerialNumber.SerialNumber.Value; } else recipientID.SubjectKeyIdentifier = identifier.RKeyID.SubjectKeyIdentifier.GetEncoded("DER"); infos.Add(new KeyAgreeRecipientInformation(info, recipientID, instance.EncryptedKey, secureReadable)); } } catch (IOException innerException) { throw new ArgumentException("invalid rid in KeyAgreeRecipientInformation", innerException); } } internal KeyAgreeRecipientInformation(KeyAgreeRecipientInfo info, RecipientID rid, Asn1OctetString encryptedKey, CmsSecureReadable secureReadable) : base(info.KeyEncryptionAlgorithm, secureReadable) { m_info = info; base.rid = rid; m_encryptedKey = encryptedKey; } private AsymmetricKeyParameter GetSenderPublicKey(AsymmetricKeyParameter receiverPrivateKey, OriginatorIdentifierOrKey originator) { OriginatorPublicKey originatorPublicKey = originator.OriginatorPublicKey; if (originatorPublicKey != null) return GetPublicKeyFromOriginatorPublicKey(receiverPrivateKey, originatorPublicKey); OriginatorID originatorID = new OriginatorID(); IssuerAndSerialNumber issuerAndSerialNumber = originator.IssuerAndSerialNumber; if (issuerAndSerialNumber != null) { originatorID.Issuer = issuerAndSerialNumber.Issuer; originatorID.SerialNumber = issuerAndSerialNumber.SerialNumber.Value; } else originatorID.SubjectKeyIdentifier = originator.SubjectKeyIdentifier.GetEncoded("DER"); return GetPublicKeyFromOriginatorID(originatorID); } private AsymmetricKeyParameter GetPublicKeyFromOriginatorPublicKey(AsymmetricKeyParameter receiverPrivateKey, OriginatorPublicKey originatorPublicKey) { return PublicKeyFactory.CreateKey(new SubjectPublicKeyInfo(PrivateKeyInfoFactory.CreatePrivateKeyInfo(receiverPrivateKey).PrivateKeyAlgorithm, originatorPublicKey.PublicKey)); } private AsymmetricKeyParameter GetPublicKeyFromOriginatorID(OriginatorID origID) { throw new CmsException("No support for 'originator' as IssuerAndSerialNumber or SubjectKeyIdentifier"); } private KeyParameter CalculateAgreedWrapKey(DerObjectIdentifier wrapAlgOid, AsymmetricKeyParameter senderPublicKey, AsymmetricKeyParameter receiverPrivateKey) { DerObjectIdentifier algorithm = keyEncAlg.Algorithm; ICipherParameters cipherParameters = senderPublicKey; ICipherParameters cipherParameters2 = receiverPrivateKey; if (algorithm.Id.Equals(CmsEnvelopedGenerator.ECMqvSha1Kdf)) { MQVuserKeyingMaterial instance = MQVuserKeyingMaterial.GetInstance(m_info.UserKeyingMaterial.GetOctets()); AsymmetricKeyParameter publicKeyFromOriginatorPublicKey = GetPublicKeyFromOriginatorPublicKey(receiverPrivateKey, instance.EphemeralPublicKey); cipherParameters = new MqvPublicParameters((ECPublicKeyParameters)cipherParameters, (ECPublicKeyParameters)publicKeyFromOriginatorPublicKey); cipherParameters2 = new MqvPrivateParameters((ECPrivateKeyParameters)cipherParameters2, (ECPrivateKeyParameters)cipherParameters2); } IBasicAgreement basicAgreementWithKdf = AgreementUtilities.GetBasicAgreementWithKdf(algorithm, wrapAlgOid); basicAgreementWithKdf.Init(cipherParameters2); BigInteger s = basicAgreementWithKdf.CalculateAgreement(cipherParameters); int qLength = GeneratorUtilities.GetDefaultKeySize(wrapAlgOid) / 8; byte[] keyBytes = X9IntegerConverter.IntegerToBytes(s, qLength); return ParameterUtilities.CreateKeyParameter(wrapAlgOid, keyBytes); } private KeyParameter UnwrapSessionKey(DerObjectIdentifier wrapAlgOid, KeyParameter agreedKey) { byte[] octets = m_encryptedKey.GetOctets(); IWrapper wrapper = WrapperUtilities.GetWrapper(wrapAlgOid); wrapper.Init(false, agreedKey); byte[] keyBytes = wrapper.Unwrap(octets, 0, octets.Length); return ParameterUtilities.CreateKeyParameter(GetContentAlgorithmName(), keyBytes); } internal KeyParameter GetSessionKey(AsymmetricKeyParameter receiverPrivateKey) { try { DerObjectIdentifier instance = DerObjectIdentifier.GetInstance(Asn1Sequence.GetInstance(keyEncAlg.Parameters)[0]); AsymmetricKeyParameter senderPublicKey = GetSenderPublicKey(receiverPrivateKey, m_info.Originator); KeyParameter agreedKey = CalculateAgreedWrapKey(instance, senderPublicKey, receiverPrivateKey); if (!CryptoProObjectIdentifiers.id_Gost28147_89_None_KeyWrap.Equals(instance)) CryptoProObjectIdentifiers.id_Gost28147_89_CryptoPro_KeyWrap.Equals(instance); return UnwrapSessionKey(instance, agreedKey); } catch (SecurityUtilityException innerException) { throw new CmsException("couldn't create cipher.", innerException); } catch (InvalidKeyException innerException2) { throw new CmsException("key invalid in message.", innerException2); } catch (Exception innerException3) { throw new CmsException("originator key invalid.", innerException3); } } public override CmsTypedStream GetContentStream(ICipherParameters key) { AsymmetricKeyParameter asymmetricKeyParameter = key as AsymmetricKeyParameter; if (asymmetricKeyParameter == null) throw new ArgumentException("KeyAgreement requires asymmetric key", "key"); if (!asymmetricKeyParameter.IsPrivate) throw new ArgumentException("Expected private key", "key"); KeyParameter sessionKey = GetSessionKey(asymmetricKeyParameter); return GetContentFromSessionKey(sessionKey); } } }