diff --git a/crypto/src/cms/CMSEnvelopedGenerator.cs b/crypto/src/cms/CMSEnvelopedGenerator.cs
index 22a999766..401f4d2e8 100644
--- a/crypto/src/cms/CMSEnvelopedGenerator.cs
+++ b/crypto/src/cms/CMSEnvelopedGenerator.cs
@@ -225,11 +225,10 @@ namespace Org.BouncyCastle.Cms
X509Certificate recipientCert,
string cekWrapAlgorithm)
{
- var recipientCerts = new List<X509Certificate>(1);
- recipientCerts.Add(recipientCert);
+ var recipientCerts = new List<X509Certificate>(1){ recipientCert };
- AddKeyAgreementRecipients(agreementAlgorithm, senderPrivateKey, senderPublicKey,
- recipientCerts, cekWrapAlgorithm);
+ AddKeyAgreementRecipients(agreementAlgorithm, senderPrivateKey, senderPublicKey, recipientCerts,
+ cekWrapAlgorithm);
}
/**
@@ -251,24 +250,46 @@ namespace Org.BouncyCastle.Cms
string cekWrapAlgorithm)
{
if (!senderPrivateKey.IsPrivate)
- throw new ArgumentException("Expected private key", "senderPrivateKey");
+ throw new ArgumentException("Expected private key", nameof(senderPrivateKey));
if (senderPublicKey.IsPrivate)
- throw new ArgumentException("Expected public key", "senderPublicKey");
+ throw new ArgumentException("Expected public key", nameof(senderPublicKey));
/* TODO
* "a recipient X.509 version 3 certificate that contains a key usage extension MUST
* assert the keyAgreement bit."
*/
- KeyAgreeRecipientInfoGenerator karig = new KeyAgreeRecipientInfoGenerator();
- karig.KeyAgreementOID = new DerObjectIdentifier(agreementAlgorithm);
- karig.KeyEncryptionOID = new DerObjectIdentifier(cekWrapAlgorithm);
- karig.RecipientCerts = new List<X509Certificate>(recipientCerts);
- karig.SenderKeyPair = new AsymmetricCipherKeyPair(senderPublicKey, senderPrivateKey);
-
- recipientInfoGenerators.Add(karig);
+ recipientInfoGenerators.Add(new KeyAgreeRecipientInfoGenerator(recipientCerts)
+ {
+ KeyAgreementOid = new DerObjectIdentifier(agreementAlgorithm),
+ KeyEncryptionOid = new DerObjectIdentifier(cekWrapAlgorithm),
+ SenderKeyPair = new AsymmetricCipherKeyPair(senderPublicKey, senderPrivateKey),
+ });
}
+ public void AddKeyAgreementRecipient(
+ string agreementAlgorithm,
+ AsymmetricKeyParameter senderPrivateKey,
+ AsymmetricKeyParameter senderPublicKey,
+ byte[] recipientKeyID,
+ AsymmetricKeyParameter recipientPublicKey,
+ string cekWrapAlgorithm)
+ {
+ if (!senderPrivateKey.IsPrivate)
+ throw new ArgumentException("Expected private key", nameof(senderPrivateKey));
+ if (senderPublicKey.IsPrivate)
+ throw new ArgumentException("Expected public key", nameof(senderPublicKey));
+ if (recipientPublicKey.IsPrivate)
+ throw new ArgumentException("Expected public key", nameof(recipientPublicKey));
+
+ recipientInfoGenerators.Add(new KeyAgreeRecipientInfoGenerator(recipientKeyID, recipientPublicKey)
+ {
+ KeyAgreementOid = new DerObjectIdentifier(agreementAlgorithm),
+ KeyEncryptionOid = new DerObjectIdentifier(cekWrapAlgorithm),
+ SenderKeyPair = new AsymmetricCipherKeyPair(senderPublicKey, senderPrivateKey),
+ });
+ }
+
/// <summary>
/// Add a generator to produce the recipient info required.
/// </summary>
diff --git a/crypto/src/cms/KeyAgreeRecipientInfoGenerator.cs b/crypto/src/cms/KeyAgreeRecipientInfoGenerator.cs
index f74365571..8feb25b43 100644
--- a/crypto/src/cms/KeyAgreeRecipientInfoGenerator.cs
+++ b/crypto/src/cms/KeyAgreeRecipientInfoGenerator.cs
@@ -1,4 +1,3 @@
-using System;
using System.Collections.Generic;
using System.IO;
@@ -15,46 +14,54 @@ using Org.BouncyCastle.X509;
namespace Org.BouncyCastle.Cms
{
- internal class KeyAgreeRecipientInfoGenerator : RecipientInfoGenerator
+ internal class KeyAgreeRecipientInfoGenerator
+ : RecipientInfoGenerator
{
private static readonly CmsEnvelopedHelper Helper = CmsEnvelopedHelper.Instance;
- private DerObjectIdentifier keyAgreementOID;
- private DerObjectIdentifier keyEncryptionOID;
- private IList<X509Certificate> recipientCerts;
- private AsymmetricCipherKeyPair senderKeyPair;
+ private readonly List<KeyAgreeRecipientIdentifier> m_recipientIDs = new List<KeyAgreeRecipientIdentifier>();
+ private readonly List<AsymmetricKeyParameter> m_recipientKeys = new List<AsymmetricKeyParameter>();
- internal KeyAgreeRecipientInfoGenerator()
- {
- }
+ private DerObjectIdentifier m_keyAgreementOid;
+ private DerObjectIdentifier m_keyEncryptionOid;
+ private AsymmetricCipherKeyPair m_senderKeyPair;
- internal DerObjectIdentifier KeyAgreementOID
+ internal KeyAgreeRecipientInfoGenerator(IEnumerable<X509Certificate> recipientCerts)
{
- set { this.keyAgreementOID = value; }
- }
-
- internal DerObjectIdentifier KeyEncryptionOID
+ foreach (var 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);
+ }
+
+ internal DerObjectIdentifier KeyAgreementOid
{
- set { this.keyEncryptionOID = value; }
+ set { m_keyAgreementOid = value; }
}
- internal IEnumerable<X509Certificate> RecipientCerts
+ internal DerObjectIdentifier KeyEncryptionOid
{
- set { this.recipientCerts = new List<X509Certificate>(value); }
+ set { m_keyEncryptionOid = value; }
}
internal AsymmetricCipherKeyPair SenderKeyPair
{
- set { this.senderKeyPair = value; }
+ set { m_senderKeyPair = value; }
}
public RecipientInfo Generate(KeyParameter contentEncryptionKey, SecureRandom random)
{
byte[] keyBytes = contentEncryptionKey.GetKey();
- AsymmetricKeyParameter senderPublicKey = senderKeyPair.Public;
- ICipherParameters senderPrivateParams = senderKeyPair.Private;
-
+ AsymmetricKeyParameter senderPublicKey = m_senderKeyPair.Public;
+ ICipherParameters senderPrivateParams = m_senderKeyPair.Private;
OriginatorIdentifierOrKey originator;
try
@@ -67,14 +74,13 @@ namespace Org.BouncyCastle.Cms
throw new InvalidKeyException("cannot extract originator public key: " + e);
}
-
Asn1OctetString ukm = null;
- if (keyAgreementOID.Id.Equals(CmsEnvelopedGenerator.ECMqvSha1Kdf))
+ if (m_keyAgreementOid.Id.Equals(CmsEnvelopedGenerator.ECMqvSha1Kdf))
{
try
{
IAsymmetricCipherKeyPairGenerator ephemKPG =
- GeneratorUtilities.GetKeyPairGenerator(keyAgreementOID);
+ GeneratorUtilities.GetKeyPairGenerator(m_keyAgreementOid);
ephemKPG.Init(
((ECPublicKeyParameters)senderPublicKey).CreateKeyGenerationParameters(random));
@@ -99,22 +105,16 @@ namespace Org.BouncyCastle.Cms
}
}
-
- DerSequence paramSeq = new DerSequence(
- keyEncryptionOID,
- DerNull.Instance);
- AlgorithmIdentifier keyEncAlg = new AlgorithmIdentifier(keyAgreementOID, paramSeq);
-
+ DerSequence paramSeq = new DerSequence(m_keyEncryptionOid, DerNull.Instance);
+ AlgorithmIdentifier keyEncAlg = new AlgorithmIdentifier(m_keyAgreementOid, paramSeq);
Asn1EncodableVector recipientEncryptedKeys = new Asn1EncodableVector();
- foreach (X509Certificate recipientCert in recipientCerts)
+ for (int i = 0; i < m_recipientIDs.Count; ++i)
{
- // TODO Should there be a SubjectKeyIdentifier-based alternative?
- KeyAgreeRecipientIdentifier karid = new KeyAgreeRecipientIdentifier(
- CmsUtilities.GetIssuerAndSerialNumber(recipientCert));
+ var recipientID = m_recipientIDs[i];
+ ICipherParameters recipientPublicParams = m_recipientKeys[i];
- ICipherParameters recipientPublicParams = recipientCert.GetPublicKey();
- if (keyAgreementOID.Id.Equals(CmsEnvelopedGenerator.ECMqvSha1Kdf))
+ if (m_keyAgreementOid.Id.Equals(CmsEnvelopedGenerator.ECMqvSha1Kdf))
{
recipientPublicParams = new MqvPublicParameters(
(ECPublicKeyParameters)recipientPublicParams,
@@ -123,31 +123,30 @@ namespace Org.BouncyCastle.Cms
// Use key agreement to choose a wrap key for this recipient
IBasicAgreement keyAgreement = AgreementUtilities.GetBasicAgreementWithKdf(
- keyAgreementOID, keyEncryptionOID.Id);
+ m_keyAgreementOid, m_keyEncryptionOid.Id);
keyAgreement.Init(new ParametersWithRandom(senderPrivateParams, random));
BigInteger agreedValue = keyAgreement.CalculateAgreement(recipientPublicParams);
- int keyEncryptionKeySize = GeneratorUtilities.GetDefaultKeySize(keyEncryptionOID) / 8;
+ int keyEncryptionKeySize = GeneratorUtilities.GetDefaultKeySize(m_keyEncryptionOid) / 8;
byte[] keyEncryptionKeyBytes = X9IntegerConverter.IntegerToBytes(agreedValue, keyEncryptionKeySize);
KeyParameter keyEncryptionKey = ParameterUtilities.CreateKeyParameter(
- keyEncryptionOID, keyEncryptionKeyBytes);
+ m_keyEncryptionOid, keyEncryptionKeyBytes);
// Wrap the content encryption key with the agreement key
- IWrapper keyWrapper = WrapperUtilities.GetWrapper(keyEncryptionOID.Id);
+ IWrapper keyWrapper = WrapperUtilities.GetWrapper(m_keyEncryptionOid.Id);
keyWrapper.Init(true, new ParametersWithRandom(keyEncryptionKey, random));
byte[] encryptedKeyBytes = keyWrapper.Wrap(keyBytes, 0, keyBytes.Length);
Asn1OctetString encryptedKey = new DerOctetString(encryptedKeyBytes);
- recipientEncryptedKeys.Add(new RecipientEncryptedKey(karid, encryptedKey));
+ recipientEncryptedKeys.Add(new RecipientEncryptedKey(recipientID, encryptedKey));
}
return new RecipientInfo(new KeyAgreeRecipientInfo(originator, ukm, keyEncAlg,
new DerSequence(recipientEncryptedKeys)));
}
- private static OriginatorPublicKey CreateOriginatorPublicKey(
- AsymmetricKeyParameter publicKey)
+ private static OriginatorPublicKey CreateOriginatorPublicKey(AsymmetricKeyParameter publicKey)
{
SubjectPublicKeyInfo spki = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(publicKey);
return new OriginatorPublicKey(
|