You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
315 lines
8.8 KiB
315 lines
8.8 KiB
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR) |
|
#pragma warning disable |
|
using System; |
|
using System.Collections; |
|
using System.IO; |
|
|
|
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1; |
|
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Cms; |
|
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.X509; |
|
using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto; |
|
using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.IO; |
|
using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters; |
|
using BestHTTP.SecureProtocol.Org.BouncyCastle.Security; |
|
using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities; |
|
using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.IO; |
|
|
|
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Cms |
|
{ |
|
class CmsEnvelopedHelper |
|
{ |
|
internal static readonly CmsEnvelopedHelper Instance = new CmsEnvelopedHelper(); |
|
|
|
private static readonly IDictionary KeySizes = BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Platform.CreateHashtable(); |
|
private static readonly IDictionary BaseCipherNames = BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Platform.CreateHashtable(); |
|
|
|
static CmsEnvelopedHelper() |
|
{ |
|
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 (Asn1.Pkcs.PkcsObjectIdentifiers.RsaEncryption.Id.Equals(encryptionAlgOid)) |
|
{ |
|
return "RSA/ECB/PKCS1Padding"; |
|
} |
|
|
|
return encryptionAlgOid; |
|
} |
|
|
|
internal IBufferedCipher CreateAsymmetricCipher( |
|
string encryptionOid) |
|
{ |
|
string asymName = GetAsymmetricEncryptionAlgName(encryptionOid); |
|
if (!asymName.Equals(encryptionOid)) |
|
{ |
|
try |
|
{ |
|
return CipherUtilities.GetCipher(asymName); |
|
} |
|
catch (SecurityUtilityException) |
|
{ |
|
// Ignore |
|
} |
|
} |
|
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 alg = (string) BaseCipherNames[oid]; |
|
|
|
if (alg == null) |
|
throw new ArgumentException("no name for " + oid, "oid"); |
|
|
|
return alg + "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 infos = BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Platform.CreateArrayList(); |
|
for (int i = 0; i != recipientInfos.Count; i++) |
|
{ |
|
RecipientInfo info = RecipientInfo.GetInstance(recipientInfos[i]); |
|
|
|
ReadRecipientInfo(infos, info, secureReadable); |
|
} |
|
return new RecipientInformationStore(infos); |
|
} |
|
|
|
private static void ReadRecipientInfo( |
|
IList infos, RecipientInfo info, CmsSecureReadable secureReadable) |
|
{ |
|
Asn1Encodable recipInfo = info.Info; |
|
if (recipInfo is KeyTransRecipientInfo) |
|
{ |
|
infos.Add(new KeyTransRecipientInformation((KeyTransRecipientInfo)recipInfo, secureReadable)); |
|
} |
|
else if (recipInfo is KekRecipientInfo) |
|
{ |
|
infos.Add(new KekRecipientInformation((KekRecipientInfo)recipInfo, secureReadable)); |
|
} |
|
else if (recipInfo is KeyAgreeRecipientInfo) |
|
{ |
|
KeyAgreeRecipientInformation.ReadRecipientInfo(infos, (KeyAgreeRecipientInfo)recipInfo, secureReadable); |
|
} |
|
else if (recipInfo is PasswordRecipientInfo) |
|
{ |
|
infos.Add(new PasswordRecipientInformation((PasswordRecipientInfo)recipInfo, secureReadable)); |
|
} |
|
} |
|
|
|
internal class CmsAuthenticatedSecureReadable : CmsSecureReadable |
|
{ |
|
private AlgorithmIdentifier algorithm; |
|
private IMac mac; |
|
private CmsReadable readable; |
|
|
|
internal CmsAuthenticatedSecureReadable(AlgorithmIdentifier algorithm, CmsReadable readable) |
|
{ |
|
this.algorithm = algorithm; |
|
this.readable = readable; |
|
} |
|
|
|
public AlgorithmIdentifier Algorithm |
|
{ |
|
get { return this.algorithm; } |
|
} |
|
|
|
public object CryptoObject |
|
{ |
|
get { return this.mac; } |
|
} |
|
|
|
public CmsReadable GetReadable(KeyParameter sKey) |
|
{ |
|
string macAlg = this.algorithm.Algorithm.Id; |
|
// Asn1Object sParams = this.algorithm.Parameters.ToAsn1Object(); |
|
|
|
try |
|
{ |
|
this.mac = MacUtilities.GetMac(macAlg); |
|
|
|
// FIXME Support for MAC algorithm parameters similar to cipher parameters |
|
// ASN1Object sParams = (ASN1Object)macAlg.getParameters(); |
|
// |
|
// if (sParams != null && !(sParams instanceof ASN1Null)) |
|
// { |
|
// AlgorithmParameters params = CMSEnvelopedHelper.INSTANCE.createAlgorithmParameters(macAlg.getObjectId().getId(), provider); |
|
// |
|
// params.init(sParams.getEncoded(), "ASN.1"); |
|
// |
|
// mac.init(sKey, params.getParameterSpec(IvParameterSpec.class)); |
|
// } |
|
// else |
|
{ |
|
mac.Init(sKey); |
|
} |
|
|
|
// Asn1Object asn1Params = asn1Enc == null ? null : asn1Enc.ToAsn1Object(); |
|
// |
|
// ICipherParameters cipherParameters = sKey; |
|
// |
|
// if (asn1Params != null && !(asn1Params is Asn1Null)) |
|
// { |
|
// cipherParameters = ParameterUtilities.GetCipherParameters( |
|
// macAlg.Algorithm, cipherParameters, asn1Params); |
|
// } |
|
// else |
|
// { |
|
// string alg = macAlg.Algorithm.Id; |
|
// if (alg.Equals(CmsEnvelopedDataGenerator.DesEde3Cbc) |
|
// || alg.Equals(CmsEnvelopedDataGenerator.IdeaCbc) |
|
// || alg.Equals(CmsEnvelopedDataGenerator.Cast5Cbc)) |
|
// { |
|
// cipherParameters = new ParametersWithIV(cipherParameters, new byte[8]); |
|
// } |
|
// } |
|
// |
|
// mac.Init(cipherParameters); |
|
} |
|
catch (SecurityUtilityException e) |
|
{ |
|
throw new CmsException("couldn't create cipher.", e); |
|
} |
|
catch (InvalidKeyException e) |
|
{ |
|
throw new CmsException("key invalid in message.", e); |
|
} |
|
catch (IOException e) |
|
{ |
|
throw new CmsException("error decoding algorithm parameters.", e); |
|
} |
|
|
|
try |
|
{ |
|
return new CmsProcessableInputStream( |
|
new TeeInputStream( |
|
readable.GetInputStream(), |
|
new MacSink(this.mac))); |
|
} |
|
catch (IOException e) |
|
{ |
|
throw new CmsException("error reading content.", e); |
|
} |
|
} |
|
} |
|
|
|
internal class CmsEnvelopedSecureReadable : CmsSecureReadable |
|
{ |
|
private AlgorithmIdentifier algorithm; |
|
private IBufferedCipher cipher; |
|
private CmsReadable readable; |
|
|
|
internal CmsEnvelopedSecureReadable(AlgorithmIdentifier algorithm, CmsReadable readable) |
|
{ |
|
this.algorithm = algorithm; |
|
this.readable = readable; |
|
} |
|
|
|
public AlgorithmIdentifier Algorithm |
|
{ |
|
get { return this.algorithm; } |
|
} |
|
|
|
public object CryptoObject |
|
{ |
|
get { return this.cipher; } |
|
} |
|
|
|
public CmsReadable GetReadable(KeyParameter sKey) |
|
{ |
|
try |
|
{ |
|
this.cipher = CipherUtilities.GetCipher(this.algorithm.Algorithm); |
|
|
|
Asn1Encodable asn1Enc = this.algorithm.Parameters; |
|
Asn1Object asn1Params = asn1Enc == null ? null : asn1Enc.ToAsn1Object(); |
|
|
|
ICipherParameters cipherParameters = sKey; |
|
|
|
if (asn1Params != null && !(asn1Params is Asn1Null)) |
|
{ |
|
cipherParameters = ParameterUtilities.GetCipherParameters( |
|
this.algorithm.Algorithm, cipherParameters, asn1Params); |
|
} |
|
else |
|
{ |
|
string alg = this.algorithm.Algorithm.Id; |
|
if (alg.Equals(CmsEnvelopedDataGenerator.DesEde3Cbc) |
|
|| alg.Equals(CmsEnvelopedDataGenerator.IdeaCbc) |
|
|| alg.Equals(CmsEnvelopedDataGenerator.Cast5Cbc)) |
|
{ |
|
cipherParameters = new ParametersWithIV(cipherParameters, new byte[8]); |
|
} |
|
} |
|
|
|
cipher.Init(false, cipherParameters); |
|
} |
|
catch (SecurityUtilityException e) |
|
{ |
|
throw new CmsException("couldn't create cipher.", e); |
|
} |
|
catch (InvalidKeyException e) |
|
{ |
|
throw new CmsException("key invalid in message.", e); |
|
} |
|
catch (IOException e) |
|
{ |
|
throw new CmsException("error decoding algorithm parameters.", e); |
|
} |
|
|
|
try |
|
{ |
|
return new CmsProcessableInputStream( |
|
new CipherStream(readable.GetInputStream(), cipher, null)); |
|
} |
|
catch (IOException e) |
|
{ |
|
throw new CmsException("error reading content.", e); |
|
} |
|
} |
|
} |
|
} |
|
} |
|
#pragma warning restore |
|
#endif
|
|
|