243 lines
6.5 KiB
C#
243 lines
6.5 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.IO;
|
|
using Org.BouncyCastle.Asn1;
|
|
using Org.BouncyCastle.Asn1.Cms;
|
|
using Org.BouncyCastle.Asn1.Pkcs;
|
|
using Org.BouncyCastle.Asn1.X509;
|
|
using Org.BouncyCastle.Crypto;
|
|
using Org.BouncyCastle.Crypto.IO;
|
|
using Org.BouncyCastle.Crypto.Parameters;
|
|
using Org.BouncyCastle.Security;
|
|
using Org.BouncyCastle.Utilities;
|
|
using Org.BouncyCastle.Utilities.IO;
|
|
|
|
namespace Org.BouncyCastle.Cms;
|
|
|
|
internal class CmsEnvelopedHelper
|
|
{
|
|
internal class CmsAuthenticatedSecureReadable : CmsSecureReadable
|
|
{
|
|
private AlgorithmIdentifier algorithm;
|
|
|
|
private IMac mac;
|
|
|
|
private CmsReadable readable;
|
|
|
|
public AlgorithmIdentifier Algorithm => algorithm;
|
|
|
|
public object CryptoObject => mac;
|
|
|
|
internal CmsAuthenticatedSecureReadable(AlgorithmIdentifier algorithm, CmsReadable readable)
|
|
{
|
|
this.algorithm = algorithm;
|
|
this.readable = readable;
|
|
}
|
|
|
|
public CmsReadable GetReadable(KeyParameter sKey)
|
|
{
|
|
string id = algorithm.Algorithm.Id;
|
|
try
|
|
{
|
|
mac = MacUtilities.GetMac(id);
|
|
mac.Init(sKey);
|
|
}
|
|
catch (SecurityUtilityException e)
|
|
{
|
|
throw new CmsException("couldn't create cipher.", e);
|
|
}
|
|
catch (InvalidKeyException e2)
|
|
{
|
|
throw new CmsException("key invalid in message.", e2);
|
|
}
|
|
catch (IOException e3)
|
|
{
|
|
throw new CmsException("error decoding algorithm parameters.", e3);
|
|
}
|
|
try
|
|
{
|
|
return new CmsProcessableInputStream(new TeeInputStream(readable.GetInputStream(), new MacSink(mac)));
|
|
}
|
|
catch (IOException e4)
|
|
{
|
|
throw new CmsException("error reading content.", e4);
|
|
}
|
|
}
|
|
}
|
|
|
|
internal class CmsEnvelopedSecureReadable : CmsSecureReadable
|
|
{
|
|
private AlgorithmIdentifier algorithm;
|
|
|
|
private IBufferedCipher cipher;
|
|
|
|
private CmsReadable readable;
|
|
|
|
public AlgorithmIdentifier Algorithm => algorithm;
|
|
|
|
public object CryptoObject => cipher;
|
|
|
|
internal CmsEnvelopedSecureReadable(AlgorithmIdentifier algorithm, CmsReadable readable)
|
|
{
|
|
this.algorithm = algorithm;
|
|
this.readable = readable;
|
|
}
|
|
|
|
public CmsReadable GetReadable(KeyParameter sKey)
|
|
{
|
|
try
|
|
{
|
|
cipher = CipherUtilities.GetCipher(algorithm.Algorithm);
|
|
Asn1Object asn1Object = algorithm.Parameters?.ToAsn1Object();
|
|
ICipherParameters cipherParameters = sKey;
|
|
if (asn1Object != null && !(asn1Object is Asn1Null))
|
|
{
|
|
cipherParameters = ParameterUtilities.GetCipherParameters(algorithm.Algorithm, cipherParameters, asn1Object);
|
|
}
|
|
else
|
|
{
|
|
string id = algorithm.Algorithm.Id;
|
|
if (id.Equals(CmsEnvelopedGenerator.DesEde3Cbc) || id.Equals("1.3.6.1.4.1.188.7.1.1.2") || id.Equals("1.2.840.113533.7.66.10"))
|
|
{
|
|
cipherParameters = new ParametersWithIV(cipherParameters, new byte[8]);
|
|
}
|
|
}
|
|
cipher.Init(forEncryption: false, cipherParameters);
|
|
}
|
|
catch (SecurityUtilityException e)
|
|
{
|
|
throw new CmsException("couldn't create cipher.", e);
|
|
}
|
|
catch (InvalidKeyException e2)
|
|
{
|
|
throw new CmsException("key invalid in message.", e2);
|
|
}
|
|
catch (IOException e3)
|
|
{
|
|
throw new CmsException("error decoding algorithm parameters.", e3);
|
|
}
|
|
try
|
|
{
|
|
return new CmsProcessableInputStream(new CipherStream(readable.GetInputStream(), cipher, null));
|
|
}
|
|
catch (IOException e4)
|
|
{
|
|
throw new CmsException("error reading content.", e4);
|
|
}
|
|
}
|
|
}
|
|
|
|
internal static readonly CmsEnvelopedHelper Instance;
|
|
|
|
private static readonly IDictionary KeySizes;
|
|
|
|
private static readonly IDictionary BaseCipherNames;
|
|
|
|
static CmsEnvelopedHelper()
|
|
{
|
|
Instance = new CmsEnvelopedHelper();
|
|
KeySizes = Platform.CreateHashtable();
|
|
BaseCipherNames = Platform.CreateHashtable();
|
|
KeySizes.Add(CmsEnvelopedGenerator.DesEde3Cbc, 192);
|
|
KeySizes.Add(CmsEnvelopedGenerator.Aes128Cbc, 128);
|
|
KeySizes.Add(CmsEnvelopedGenerator.Aes192Cbc, 192);
|
|
KeySizes.Add(CmsEnvelopedGenerator.Aes256Cbc, 256);
|
|
BaseCipherNames.Add(CmsEnvelopedGenerator.DesEde3Cbc, "DESEDE");
|
|
BaseCipherNames.Add(CmsEnvelopedGenerator.Aes128Cbc, "AES");
|
|
BaseCipherNames.Add(CmsEnvelopedGenerator.Aes192Cbc, "AES");
|
|
BaseCipherNames.Add(CmsEnvelopedGenerator.Aes256Cbc, "AES");
|
|
}
|
|
|
|
private string GetAsymmetricEncryptionAlgName(string encryptionAlgOid)
|
|
{
|
|
if (PkcsObjectIdentifiers.RsaEncryption.Id.Equals(encryptionAlgOid))
|
|
{
|
|
return "RSA/ECB/PKCS1Padding";
|
|
}
|
|
return encryptionAlgOid;
|
|
}
|
|
|
|
internal IBufferedCipher CreateAsymmetricCipher(string encryptionOid)
|
|
{
|
|
string asymmetricEncryptionAlgName = GetAsymmetricEncryptionAlgName(encryptionOid);
|
|
if (!asymmetricEncryptionAlgName.Equals(encryptionOid))
|
|
{
|
|
try
|
|
{
|
|
return CipherUtilities.GetCipher(asymmetricEncryptionAlgName);
|
|
}
|
|
catch (SecurityUtilityException)
|
|
{
|
|
}
|
|
}
|
|
return CipherUtilities.GetCipher(encryptionOid);
|
|
}
|
|
|
|
internal IWrapper CreateWrapper(string encryptionOid)
|
|
{
|
|
try
|
|
{
|
|
return WrapperUtilities.GetWrapper(encryptionOid);
|
|
}
|
|
catch (SecurityUtilityException)
|
|
{
|
|
return WrapperUtilities.GetWrapper(GetAsymmetricEncryptionAlgName(encryptionOid));
|
|
}
|
|
}
|
|
|
|
internal string GetRfc3211WrapperName(string oid)
|
|
{
|
|
if (oid == null)
|
|
{
|
|
throw new ArgumentNullException("oid");
|
|
}
|
|
string text = (string)BaseCipherNames[oid];
|
|
if (text == null)
|
|
{
|
|
throw new ArgumentException("no name for " + oid, "oid");
|
|
}
|
|
return text + "RFC3211Wrap";
|
|
}
|
|
|
|
internal int GetKeySize(string oid)
|
|
{
|
|
if (!KeySizes.Contains(oid))
|
|
{
|
|
throw new ArgumentException("no keysize for " + oid, "oid");
|
|
}
|
|
return (int)KeySizes[oid];
|
|
}
|
|
|
|
internal static RecipientInformationStore BuildRecipientInformationStore(Asn1Set recipientInfos, CmsSecureReadable secureReadable)
|
|
{
|
|
IList list = Platform.CreateArrayList();
|
|
for (int i = 0; i != recipientInfos.Count; i++)
|
|
{
|
|
RecipientInfo instance = RecipientInfo.GetInstance(recipientInfos[i]);
|
|
ReadRecipientInfo(list, instance, secureReadable);
|
|
}
|
|
return new RecipientInformationStore(list);
|
|
}
|
|
|
|
private static void ReadRecipientInfo(IList infos, RecipientInfo info, CmsSecureReadable secureReadable)
|
|
{
|
|
Asn1Encodable info2 = info.Info;
|
|
if (info2 is KeyTransRecipientInfo)
|
|
{
|
|
infos.Add(new KeyTransRecipientInformation((KeyTransRecipientInfo)info2, secureReadable));
|
|
}
|
|
else if (info2 is KekRecipientInfo)
|
|
{
|
|
infos.Add(new KekRecipientInformation((KekRecipientInfo)info2, secureReadable));
|
|
}
|
|
else if (info2 is KeyAgreeRecipientInfo)
|
|
{
|
|
KeyAgreeRecipientInformation.ReadRecipientInfo(infos, (KeyAgreeRecipientInfo)info2, secureReadable);
|
|
}
|
|
else if (info2 is PasswordRecipientInfo)
|
|
{
|
|
infos.Add(new PasswordRecipientInformation((PasswordRecipientInfo)info2, secureReadable));
|
|
}
|
|
}
|
|
}
|