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);
}
}
}