142 lines
5.2 KiB
C#
142 lines
5.2 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.IO;
|
|
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.Utilities;
|
|
using Org.BouncyCastle.X509;
|
|
|
|
namespace Org.BouncyCastle.Cms;
|
|
|
|
internal class KeyAgreeRecipientInfoGenerator : RecipientInfoGenerator
|
|
{
|
|
private static readonly CmsEnvelopedHelper Helper = CmsEnvelopedHelper.Instance;
|
|
|
|
private DerObjectIdentifier keyAgreementOID;
|
|
|
|
private DerObjectIdentifier keyEncryptionOID;
|
|
|
|
private IList recipientCerts;
|
|
|
|
private AsymmetricCipherKeyPair senderKeyPair;
|
|
|
|
internal DerObjectIdentifier KeyAgreementOID
|
|
{
|
|
set
|
|
{
|
|
keyAgreementOID = value;
|
|
}
|
|
}
|
|
|
|
internal DerObjectIdentifier KeyEncryptionOID
|
|
{
|
|
set
|
|
{
|
|
keyEncryptionOID = value;
|
|
}
|
|
}
|
|
|
|
internal ICollection RecipientCerts
|
|
{
|
|
set
|
|
{
|
|
recipientCerts = Platform.CreateArrayList(value);
|
|
}
|
|
}
|
|
|
|
internal AsymmetricCipherKeyPair SenderKeyPair
|
|
{
|
|
set
|
|
{
|
|
senderKeyPair = value;
|
|
}
|
|
}
|
|
|
|
internal KeyAgreeRecipientInfoGenerator()
|
|
{
|
|
}
|
|
|
|
public RecipientInfo Generate(KeyParameter contentEncryptionKey, SecureRandom random)
|
|
{
|
|
byte[] key = contentEncryptionKey.GetKey();
|
|
AsymmetricKeyParameter asymmetricKeyParameter = senderKeyPair.Public;
|
|
ICipherParameters cipherParameters = senderKeyPair.Private;
|
|
OriginatorIdentifierOrKey originator;
|
|
try
|
|
{
|
|
originator = new OriginatorIdentifierOrKey(CreateOriginatorPublicKey(asymmetricKeyParameter));
|
|
}
|
|
catch (IOException ex)
|
|
{
|
|
throw new InvalidKeyException("cannot extract originator public key: " + ex);
|
|
}
|
|
Asn1OctetString ukm = null;
|
|
if (keyAgreementOID.Id.Equals(CmsEnvelopedGenerator.ECMqvSha1Kdf))
|
|
{
|
|
try
|
|
{
|
|
IAsymmetricCipherKeyPairGenerator keyPairGenerator = GeneratorUtilities.GetKeyPairGenerator(keyAgreementOID);
|
|
keyPairGenerator.Init(((ECPublicKeyParameters)asymmetricKeyParameter).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);
|
|
}
|
|
catch (SecurityUtilityException ex3)
|
|
{
|
|
throw new InvalidKeyException("cannot determine MQV ephemeral key pair parameters from public key: " + ex3);
|
|
}
|
|
}
|
|
DerSequence parameters = new DerSequence(keyEncryptionOID, DerNull.Instance);
|
|
AlgorithmIdentifier keyEncryptionAlgorithm = new AlgorithmIdentifier(keyAgreementOID, parameters);
|
|
Asn1EncodableVector asn1EncodableVector = new Asn1EncodableVector();
|
|
foreach (X509Certificate recipientCert in recipientCerts)
|
|
{
|
|
TbsCertificateStructure instance;
|
|
try
|
|
{
|
|
instance = TbsCertificateStructure.GetInstance(Asn1Object.FromByteArray(recipientCert.GetTbsCertificate()));
|
|
}
|
|
catch (Exception)
|
|
{
|
|
throw new ArgumentException("can't extract TBS structure from certificate");
|
|
}
|
|
IssuerAndSerialNumber issuerSerial = new IssuerAndSerialNumber(instance.Issuer, instance.SerialNumber.Value);
|
|
KeyAgreeRecipientIdentifier id = new KeyAgreeRecipientIdentifier(issuerSerial);
|
|
ICipherParameters cipherParameters2 = recipientCert.GetPublicKey();
|
|
if (keyAgreementOID.Id.Equals(CmsEnvelopedGenerator.ECMqvSha1Kdf))
|
|
{
|
|
cipherParameters2 = new MqvPublicParameters((ECPublicKeyParameters)cipherParameters2, (ECPublicKeyParameters)cipherParameters2);
|
|
}
|
|
IBasicAgreement basicAgreementWithKdf = AgreementUtilities.GetBasicAgreementWithKdf(keyAgreementOID, keyEncryptionOID.Id);
|
|
basicAgreementWithKdf.Init(new ParametersWithRandom(cipherParameters, random));
|
|
BigInteger s = basicAgreementWithKdf.CalculateAgreement(cipherParameters2);
|
|
int qLength = GeneratorUtilities.GetDefaultKeySize(keyEncryptionOID) / 8;
|
|
byte[] keyBytes = X9IntegerConverter.IntegerToBytes(s, qLength);
|
|
KeyParameter parameters2 = ParameterUtilities.CreateKeyParameter(keyEncryptionOID, keyBytes);
|
|
IWrapper wrapper = Helper.CreateWrapper(keyEncryptionOID.Id);
|
|
wrapper.Init(forWrapping: true, new ParametersWithRandom(parameters2, random));
|
|
byte[] str = wrapper.Wrap(key, 0, key.Length);
|
|
Asn1OctetString encryptedKey = new DerOctetString(str);
|
|
asn1EncodableVector.Add(new RecipientEncryptedKey(id, encryptedKey));
|
|
}
|
|
return new RecipientInfo(new KeyAgreeRecipientInfo(originator, ukm, keyEncryptionAlgorithm, new DerSequence(asn1EncodableVector)));
|
|
}
|
|
|
|
private static OriginatorPublicKey CreateOriginatorPublicKey(AsymmetricKeyParameter publicKey)
|
|
{
|
|
SubjectPublicKeyInfo subjectPublicKeyInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(publicKey);
|
|
return new OriginatorPublicKey(new AlgorithmIdentifier(subjectPublicKeyInfo.AlgorithmID.Algorithm, DerNull.Instance), subjectPublicKeyInfo.PublicKeyData.GetBytes());
|
|
}
|
|
}
|