mirror of
https://gitee.com/jisol/jisol-game/
synced 2025-12-31 11:08:09 +00:00
提交Unity 联机Pro
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Cms
|
||||
{
|
||||
internal class BaseDigestCalculator
|
||||
: IDigestCalculator
|
||||
{
|
||||
private readonly byte[] digest;
|
||||
|
||||
internal BaseDigestCalculator(
|
||||
byte[] digest)
|
||||
{
|
||||
this.digest = digest;
|
||||
}
|
||||
|
||||
public byte[] GetDigest()
|
||||
{
|
||||
return Arrays.Clone(digest);
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 52a4d50de29f4804b93120269066e5c2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,34 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Cms
|
||||
{
|
||||
[Serializable]
|
||||
public class CmsAttributeTableGenerationException
|
||||
: CmsException
|
||||
{
|
||||
public CmsAttributeTableGenerationException()
|
||||
: base()
|
||||
{
|
||||
}
|
||||
|
||||
public CmsAttributeTableGenerationException(string message)
|
||||
: base(message)
|
||||
{
|
||||
}
|
||||
|
||||
public CmsAttributeTableGenerationException(string message, Exception innerException)
|
||||
: base(message, innerException)
|
||||
{
|
||||
}
|
||||
|
||||
protected CmsAttributeTableGenerationException(SerializationInfo info, StreamingContext context)
|
||||
: base(info, context)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 95031575dd3091648956fd5b88a549f3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,28 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System.Collections.Generic;
|
||||
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Cms;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Cms
|
||||
{
|
||||
/// <remarks>
|
||||
/// The 'Signature' parameter is only available when generating unsigned attributes.
|
||||
/// </remarks>
|
||||
public enum CmsAttributeTableParameter
|
||||
{
|
||||
// const string ContentType = "contentType";
|
||||
// const string Digest = "digest";
|
||||
// const string Signature = "encryptedDigest";
|
||||
// const string DigestAlgorithmIdentifier = "digestAlgID";
|
||||
|
||||
ContentType, Digest, Signature, DigestAlgorithmIdentifier
|
||||
}
|
||||
|
||||
public interface CmsAttributeTableGenerator
|
||||
{
|
||||
AttributeTable GetAttributes(IDictionary<CmsAttributeTableParameter, object> parameters);
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7d18c7fc2e70c2c4dbabd5bf8cadd733
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,115 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
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.Parameters;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Cms
|
||||
{
|
||||
/**
|
||||
* containing class for an CMS AuthEnveloped Data object
|
||||
*/
|
||||
internal class CmsAuthEnvelopedData
|
||||
{
|
||||
internal RecipientInformationStore recipientInfoStore;
|
||||
internal ContentInfo contentInfo;
|
||||
|
||||
private OriginatorInfo originator;
|
||||
private AlgorithmIdentifier authEncAlg;
|
||||
private Asn1Set authAttrs;
|
||||
private byte[] mac;
|
||||
private Asn1Set unauthAttrs;
|
||||
|
||||
public CmsAuthEnvelopedData(
|
||||
byte[] authEnvData)
|
||||
: this(CmsUtilities.ReadContentInfo(authEnvData))
|
||||
{
|
||||
}
|
||||
|
||||
public CmsAuthEnvelopedData(
|
||||
Stream authEnvData)
|
||||
: this(CmsUtilities.ReadContentInfo(authEnvData))
|
||||
{
|
||||
}
|
||||
|
||||
public CmsAuthEnvelopedData(
|
||||
ContentInfo contentInfo)
|
||||
{
|
||||
this.contentInfo = contentInfo;
|
||||
|
||||
AuthEnvelopedData authEnvData = AuthEnvelopedData.GetInstance(contentInfo.Content);
|
||||
|
||||
this.originator = authEnvData.OriginatorInfo;
|
||||
|
||||
//
|
||||
// read the recipients
|
||||
//
|
||||
Asn1Set recipientInfos = authEnvData.RecipientInfos;
|
||||
|
||||
//
|
||||
// read the auth-encrypted content info
|
||||
//
|
||||
EncryptedContentInfo authEncInfo = authEnvData.AuthEncryptedContentInfo;
|
||||
this.authEncAlg = authEncInfo.ContentEncryptionAlgorithm;
|
||||
CmsSecureReadable secureReadable = new AuthEnvelopedSecureReadable(this);
|
||||
|
||||
//
|
||||
// build the RecipientInformationStore
|
||||
//
|
||||
this.recipientInfoStore = CmsEnvelopedHelper.BuildRecipientInformationStore(
|
||||
recipientInfos, secureReadable);
|
||||
|
||||
// FIXME These need to be passed to the AEAD cipher as AAD (Additional Authenticated Data)
|
||||
this.authAttrs = authEnvData.AuthAttrs;
|
||||
this.mac = authEnvData.Mac.GetOctets();
|
||||
this.unauthAttrs = authEnvData.UnauthAttrs;
|
||||
}
|
||||
|
||||
private class AuthEnvelopedSecureReadable : CmsSecureReadable
|
||||
{
|
||||
private readonly CmsAuthEnvelopedData parent;
|
||||
|
||||
internal AuthEnvelopedSecureReadable(CmsAuthEnvelopedData parent)
|
||||
{
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
public AlgorithmIdentifier Algorithm
|
||||
{
|
||||
get { return parent.authEncAlg; }
|
||||
}
|
||||
|
||||
public object CryptoObject
|
||||
{
|
||||
get { return null; }
|
||||
}
|
||||
|
||||
public CmsReadable GetReadable(KeyParameter key)
|
||||
{
|
||||
// TODO Create AEAD cipher instance to decrypt and calculate tag ( MAC)
|
||||
throw new CmsException("AuthEnveloped data decryption not yet implemented");
|
||||
|
||||
// RFC 5084 ASN.1 Module
|
||||
// -- Parameters for AlgorithmIdentifier
|
||||
//
|
||||
// CCMParameters ::= SEQUENCE {
|
||||
// aes-nonce OCTET STRING (SIZE(7..13)),
|
||||
// aes-ICVlen AES-CCM-ICVlen DEFAULT 12 }
|
||||
//
|
||||
// AES-CCM-ICVlen ::= INTEGER (4 | 6 | 8 | 10 | 12 | 14 | 16)
|
||||
//
|
||||
// GCMParameters ::= SEQUENCE {
|
||||
// aes-nonce OCTET STRING, -- recommended size is 12 octets
|
||||
// aes-ICVlen AES-GCM-ICVlen DEFAULT 12 }
|
||||
//
|
||||
// AES-GCM-ICVlen ::= INTEGER (12 | 13 | 14 | 15 | 16)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7e3eb7a43c43e7c42aa4f8d9bd6ed4cd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,20 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Nist;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Cms
|
||||
{
|
||||
internal class CmsAuthEnvelopedGenerator
|
||||
{
|
||||
public static readonly string Aes128Ccm = NistObjectIdentifiers.IdAes128Ccm.Id;
|
||||
public static readonly string Aes192Ccm = NistObjectIdentifiers.IdAes192Ccm.Id;
|
||||
public static readonly string Aes256Ccm = NistObjectIdentifiers.IdAes256Ccm.Id;
|
||||
public static readonly string Aes128Gcm = NistObjectIdentifiers.IdAes128Gcm.Id;
|
||||
public static readonly string Aes192Gcm = NistObjectIdentifiers.IdAes192Gcm.Id;
|
||||
public static readonly string Aes256Gcm = NistObjectIdentifiers.IdAes256Gcm.Id;
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f95ee1f852b380e43ba55cdb0bad8129
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,140 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
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.Utilities;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Cms
|
||||
{
|
||||
/**
|
||||
* containing class for an CMS Authenticated Data object
|
||||
*/
|
||||
public class CmsAuthenticatedData
|
||||
{
|
||||
internal RecipientInformationStore recipientInfoStore;
|
||||
internal ContentInfo contentInfo;
|
||||
|
||||
private AlgorithmIdentifier macAlg;
|
||||
private Asn1Set authAttrs;
|
||||
private Asn1Set unauthAttrs;
|
||||
private byte[] mac;
|
||||
|
||||
public CmsAuthenticatedData(
|
||||
byte[] authData)
|
||||
: this(CmsUtilities.ReadContentInfo(authData))
|
||||
{
|
||||
}
|
||||
|
||||
public CmsAuthenticatedData(
|
||||
Stream authData)
|
||||
: this(CmsUtilities.ReadContentInfo(authData))
|
||||
{
|
||||
}
|
||||
|
||||
public CmsAuthenticatedData(
|
||||
ContentInfo contentInfo)
|
||||
{
|
||||
this.contentInfo = contentInfo;
|
||||
|
||||
AuthenticatedData authData = AuthenticatedData.GetInstance(contentInfo.Content);
|
||||
|
||||
//
|
||||
// read the recipients
|
||||
//
|
||||
Asn1Set recipientInfos = authData.RecipientInfos;
|
||||
|
||||
this.macAlg = authData.MacAlgorithm;
|
||||
|
||||
//
|
||||
// read the authenticated content info
|
||||
//
|
||||
ContentInfo encInfo = authData.EncapsulatedContentInfo;
|
||||
CmsReadable readable = new CmsProcessableByteArray(
|
||||
Asn1OctetString.GetInstance(encInfo.Content).GetOctets());
|
||||
CmsSecureReadable secureReadable = new CmsEnvelopedHelper.CmsAuthenticatedSecureReadable(
|
||||
this.macAlg, readable);
|
||||
|
||||
//
|
||||
// build the RecipientInformationStore
|
||||
//
|
||||
this.recipientInfoStore = CmsEnvelopedHelper.BuildRecipientInformationStore(
|
||||
recipientInfos, secureReadable);
|
||||
|
||||
this.authAttrs = authData.AuthAttrs;
|
||||
this.mac = authData.Mac.GetOctets();
|
||||
this.unauthAttrs = authData.UnauthAttrs;
|
||||
}
|
||||
|
||||
public byte[] GetMac()
|
||||
{
|
||||
return Arrays.Clone(mac);
|
||||
}
|
||||
|
||||
public AlgorithmIdentifier MacAlgorithmID
|
||||
{
|
||||
get { return macAlg; }
|
||||
}
|
||||
|
||||
/**
|
||||
* return the object identifier for the content MAC algorithm.
|
||||
*/
|
||||
public string MacAlgOid
|
||||
{
|
||||
get { return macAlg.Algorithm.Id; }
|
||||
}
|
||||
|
||||
/**
|
||||
* return a store of the intended recipients for this message
|
||||
*/
|
||||
public RecipientInformationStore GetRecipientInfos()
|
||||
{
|
||||
return recipientInfoStore;
|
||||
}
|
||||
|
||||
/**
|
||||
* return the ContentInfo
|
||||
*/
|
||||
public ContentInfo ContentInfo
|
||||
{
|
||||
get { return contentInfo; }
|
||||
}
|
||||
|
||||
/**
|
||||
* return a table of the digested attributes indexed by
|
||||
* the OID of the attribute.
|
||||
*/
|
||||
public Asn1.Cms.AttributeTable GetAuthAttrs()
|
||||
{
|
||||
if (authAttrs == null)
|
||||
return null;
|
||||
|
||||
return new Asn1.Cms.AttributeTable(authAttrs);
|
||||
}
|
||||
|
||||
/**
|
||||
* return a table of the undigested attributes indexed by
|
||||
* the OID of the attribute.
|
||||
*/
|
||||
public Asn1.Cms.AttributeTable GetUnauthAttrs()
|
||||
{
|
||||
if (unauthAttrs == null)
|
||||
return null;
|
||||
|
||||
return new Asn1.Cms.AttributeTable(unauthAttrs);
|
||||
}
|
||||
|
||||
/**
|
||||
* return the ASN.1 encoded representation of this object.
|
||||
*/
|
||||
public byte[] GetEncoded()
|
||||
{
|
||||
return contentInfo.GetEncoded();
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1e4e8925a09aa9741ad59f650cda261e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,150 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
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
|
||||
{
|
||||
/**
|
||||
* General class for generating a CMS authenticated-data message.
|
||||
*
|
||||
* A simple example of usage.
|
||||
*
|
||||
* <pre>
|
||||
* CMSAuthenticatedDataGenerator fact = new CMSAuthenticatedDataGenerator();
|
||||
*
|
||||
* fact.addKeyTransRecipient(cert);
|
||||
*
|
||||
* CMSAuthenticatedData data = fact.generate(content, algorithm, "BC");
|
||||
* </pre>
|
||||
*/
|
||||
public class CmsAuthenticatedDataGenerator
|
||||
: CmsAuthenticatedGenerator
|
||||
{
|
||||
public CmsAuthenticatedDataGenerator()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>Constructor allowing specific source of randomness</summary>
|
||||
/// <param name="random">Instance of <c>SecureRandom</c> to use.</param>
|
||||
public CmsAuthenticatedDataGenerator(SecureRandom random)
|
||||
: base(random)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* generate an enveloped object that contains an CMS Enveloped Data
|
||||
* object using the given provider and the passed in key generator.
|
||||
*/
|
||||
private CmsAuthenticatedData Generate(
|
||||
CmsProcessable content,
|
||||
string macOid,
|
||||
CipherKeyGenerator keyGen)
|
||||
{
|
||||
AlgorithmIdentifier macAlgId;
|
||||
KeyParameter encKey;
|
||||
Asn1OctetString encContent;
|
||||
Asn1OctetString macResult;
|
||||
|
||||
try
|
||||
{
|
||||
// FIXME Will this work for macs?
|
||||
byte[] encKeyBytes = keyGen.GenerateKey();
|
||||
encKey = ParameterUtilities.CreateKeyParameter(macOid, encKeyBytes);
|
||||
|
||||
Asn1Encodable asn1Params = GenerateAsn1Parameters(macOid, encKeyBytes);
|
||||
|
||||
macAlgId = GetAlgorithmIdentifier(macOid, encKey, asn1Params, out var cipherParameters);
|
||||
|
||||
IMac mac = MacUtilities.GetMac(macOid);
|
||||
// TODO Confirm no ParametersWithRandom needed
|
||||
// FIXME Only passing key at the moment
|
||||
// mac.Init(cipherParameters);
|
||||
mac.Init(encKey);
|
||||
|
||||
var bOut = new MemoryStream();
|
||||
using (var mOut = new TeeOutputStream(bOut, new MacSink(mac)))
|
||||
{
|
||||
content.Write(mOut);
|
||||
}
|
||||
|
||||
encContent = new BerOctetString(bOut.ToArray());
|
||||
|
||||
byte[] macOctets = MacUtilities.DoFinal(mac);
|
||||
macResult = new DerOctetString(macOctets);
|
||||
}
|
||||
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("exception decoding algorithm parameters.", e);
|
||||
}
|
||||
|
||||
var recipientInfos = new Asn1EncodableVector();
|
||||
|
||||
foreach (RecipientInfoGenerator rig in recipientInfoGenerators)
|
||||
{
|
||||
try
|
||||
{
|
||||
recipientInfos.Add(rig.Generate(encKey, m_random));
|
||||
}
|
||||
catch (InvalidKeyException e)
|
||||
{
|
||||
throw new CmsException("key inappropriate for algorithm.", e);
|
||||
}
|
||||
catch (GeneralSecurityException e)
|
||||
{
|
||||
throw new CmsException("error making encrypted content.", e);
|
||||
}
|
||||
}
|
||||
|
||||
var eci = new ContentInfo(CmsObjectIdentifiers.Data, encContent);
|
||||
|
||||
var contentInfo = new ContentInfo(
|
||||
CmsObjectIdentifiers.AuthenticatedData,
|
||||
new AuthenticatedData(null, new DerSet(recipientInfos), macAlgId, null, eci, null, macResult, null));
|
||||
|
||||
return new CmsAuthenticatedData(contentInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* generate an authenticated object that contains an CMS Authenticated Data object
|
||||
*/
|
||||
public CmsAuthenticatedData Generate(
|
||||
CmsProcessable content,
|
||||
string encryptionOid)
|
||||
{
|
||||
try
|
||||
{
|
||||
// FIXME Will this work for macs?
|
||||
CipherKeyGenerator keyGen = GeneratorUtilities.GetKeyGenerator(encryptionOid);
|
||||
|
||||
keyGen.Init(new KeyGenerationParameters(m_random, keyGen.DefaultStrength));
|
||||
|
||||
return Generate(content, encryptionOid, keyGen);
|
||||
}
|
||||
catch (SecurityUtilityException e)
|
||||
{
|
||||
throw new CmsException("can't find key generation algorithm.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5a8b41fa9a2f17b45ba2fd190514a66c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,217 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
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.Utilities;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Cms
|
||||
{
|
||||
/**
|
||||
* Parsing class for an CMS Authenticated Data object from an input stream.
|
||||
* <p>
|
||||
* Note: that because we are in a streaming mode only one recipient can be tried and it is important
|
||||
* that the methods on the parser are called in the appropriate order.
|
||||
* </p>
|
||||
* <p>
|
||||
* Example of use - assuming the first recipient matches the private key we have.
|
||||
* <pre>
|
||||
* CMSAuthenticatedDataParser ad = new CMSAuthenticatedDataParser(inputStream);
|
||||
*
|
||||
* RecipientInformationStore recipients = ad.getRecipientInfos();
|
||||
*
|
||||
* Collection c = recipients.getRecipients();
|
||||
* Iterator it = c.iterator();
|
||||
*
|
||||
* if (it.hasNext())
|
||||
* {
|
||||
* RecipientInformation recipient = (RecipientInformation)it.next();
|
||||
*
|
||||
* CMSTypedStream recData = recipient.getContentStream(privateKey, "BC");
|
||||
*
|
||||
* processDataStream(recData.getContentStream());
|
||||
*
|
||||
* if (!Arrays.equals(ad.getMac(), recipient.getMac())
|
||||
* {
|
||||
* System.err.println("Data corrupted!!!!");
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
* Note: this class does not introduce buffering - if you are processing large files you should create
|
||||
* the parser with:
|
||||
* <pre>
|
||||
* CMSAuthenticatedDataParser ep = new CMSAuthenticatedDataParser(new BufferedInputStream(inputStream, bufSize));
|
||||
* </pre>
|
||||
* where bufSize is a suitably large buffer size.
|
||||
* </p>
|
||||
*/
|
||||
public class CmsAuthenticatedDataParser
|
||||
: CmsContentInfoParser
|
||||
{
|
||||
internal RecipientInformationStore _recipientInfoStore;
|
||||
internal AuthenticatedDataParser authData;
|
||||
|
||||
private AlgorithmIdentifier macAlg;
|
||||
private byte[] mac;
|
||||
private Asn1.Cms.AttributeTable authAttrs;
|
||||
private Asn1.Cms.AttributeTable unauthAttrs;
|
||||
|
||||
private bool authAttrNotRead;
|
||||
private bool unauthAttrNotRead;
|
||||
|
||||
public CmsAuthenticatedDataParser(
|
||||
byte[] envelopedData)
|
||||
: this(new MemoryStream(envelopedData, false))
|
||||
{
|
||||
}
|
||||
|
||||
public CmsAuthenticatedDataParser(
|
||||
Stream envelopedData)
|
||||
: base(envelopedData)
|
||||
{
|
||||
this.authAttrNotRead = true;
|
||||
this.authData = new AuthenticatedDataParser(
|
||||
(Asn1SequenceParser)contentInfo.GetContent(Asn1Tags.Sequence));
|
||||
|
||||
// TODO Validate version?
|
||||
//DerInteger version = this.authData.getVersion();
|
||||
|
||||
//
|
||||
// read the recipients
|
||||
//
|
||||
Asn1Set recipientInfos = Asn1Set.GetInstance(authData.GetRecipientInfos().ToAsn1Object());
|
||||
|
||||
this.macAlg = authData.GetMacAlgorithm();
|
||||
|
||||
//
|
||||
// read the authenticated content info
|
||||
//
|
||||
ContentInfoParser data = authData.GetEnapsulatedContentInfo();
|
||||
CmsReadable readable = new CmsProcessableInputStream(
|
||||
((Asn1OctetStringParser)data.GetContent(Asn1Tags.OctetString)).GetOctetStream());
|
||||
CmsSecureReadable secureReadable = new CmsEnvelopedHelper.CmsAuthenticatedSecureReadable(
|
||||
this.macAlg, readable);
|
||||
|
||||
//
|
||||
// build the RecipientInformationStore
|
||||
//
|
||||
this._recipientInfoStore = CmsEnvelopedHelper.BuildRecipientInformationStore(
|
||||
recipientInfos, secureReadable);
|
||||
}
|
||||
|
||||
public AlgorithmIdentifier MacAlgorithmID
|
||||
{
|
||||
get { return macAlg; }
|
||||
}
|
||||
|
||||
/**
|
||||
* return the object identifier for the mac algorithm.
|
||||
*/
|
||||
public string MacAlgOid
|
||||
{
|
||||
get { return macAlg.Algorithm.Id; }
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* return the ASN.1 encoded encryption algorithm parameters, or null if
|
||||
* there aren't any.
|
||||
*/
|
||||
public Asn1Object MacAlgParams
|
||||
{
|
||||
get
|
||||
{
|
||||
Asn1Encodable ae = macAlg.Parameters;
|
||||
|
||||
return ae == null ? null : ae.ToAsn1Object();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* return a store of the intended recipients for this message
|
||||
*/
|
||||
public RecipientInformationStore GetRecipientInfos()
|
||||
{
|
||||
return _recipientInfoStore;
|
||||
}
|
||||
|
||||
public byte[] GetMac()
|
||||
{
|
||||
if (mac == null)
|
||||
{
|
||||
GetAuthAttrs();
|
||||
mac = authData.GetMac().GetOctets();
|
||||
}
|
||||
return Arrays.Clone(mac);
|
||||
}
|
||||
|
||||
/**
|
||||
* return a table of the unauthenticated attributes indexed by
|
||||
* the OID of the attribute.
|
||||
* @exception java.io.IOException
|
||||
*/
|
||||
public Asn1.Cms.AttributeTable GetAuthAttrs()
|
||||
{
|
||||
if (authAttrs == null && authAttrNotRead)
|
||||
{
|
||||
Asn1SetParser s = authData.GetAuthAttrs();
|
||||
|
||||
authAttrNotRead = false;
|
||||
|
||||
if (s != null)
|
||||
{
|
||||
Asn1EncodableVector v = new Asn1EncodableVector();
|
||||
|
||||
IAsn1Convertible o;
|
||||
while ((o = s.ReadObject()) != null)
|
||||
{
|
||||
Asn1SequenceParser seq = (Asn1SequenceParser)o;
|
||||
|
||||
v.Add(seq.ToAsn1Object());
|
||||
}
|
||||
|
||||
authAttrs = new Asn1.Cms.AttributeTable(new DerSet(v));
|
||||
}
|
||||
}
|
||||
|
||||
return authAttrs;
|
||||
}
|
||||
|
||||
/**
|
||||
* return a table of the unauthenticated attributes indexed by
|
||||
* the OID of the attribute.
|
||||
* @exception java.io.IOException
|
||||
*/
|
||||
public Asn1.Cms.AttributeTable GetUnauthAttrs()
|
||||
{
|
||||
if (unauthAttrs == null && unauthAttrNotRead)
|
||||
{
|
||||
Asn1SetParser s = authData.GetUnauthAttrs();
|
||||
|
||||
unauthAttrNotRead = false;
|
||||
|
||||
if (s != null)
|
||||
{
|
||||
Asn1EncodableVector v = new Asn1EncodableVector();
|
||||
|
||||
IAsn1Convertible o;
|
||||
while ((o = s.ReadObject()) != null)
|
||||
{
|
||||
Asn1SequenceParser seq = (Asn1SequenceParser)o;
|
||||
|
||||
v.Add(seq.ToAsn1Object());
|
||||
}
|
||||
|
||||
unauthAttrs = new Asn1.Cms.AttributeTable(new DerSet(v));
|
||||
}
|
||||
}
|
||||
|
||||
return unauthAttrs;
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 08feb4ccaf441894b9a5692041fb9168
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,278 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
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.Generators;
|
||||
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
|
||||
{
|
||||
/**
|
||||
* General class for generating a CMS authenticated-data message stream.
|
||||
* <p>
|
||||
* A simple example of usage.
|
||||
* <pre>
|
||||
* CMSAuthenticatedDataStreamGenerator edGen = new CMSAuthenticatedDataStreamGenerator();
|
||||
*
|
||||
* edGen.addKeyTransRecipient(cert);
|
||||
*
|
||||
* ByteArrayOutputStream bOut = new ByteArrayOutputStream();
|
||||
*
|
||||
* OutputStream out = edGen.open(
|
||||
* bOut, CMSAuthenticatedDataGenerator.AES128_CBC, "BC");*
|
||||
* out.write(data);
|
||||
*
|
||||
* out.close();
|
||||
* </pre>
|
||||
* </p>
|
||||
*/
|
||||
public class CmsAuthenticatedDataStreamGenerator
|
||||
: CmsAuthenticatedGenerator
|
||||
{
|
||||
// TODO Add support
|
||||
// private object _originatorInfo = null;
|
||||
// private object _unprotectedAttributes = null;
|
||||
private int _bufferSize;
|
||||
private bool _berEncodeRecipientSet;
|
||||
|
||||
public CmsAuthenticatedDataStreamGenerator()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>Constructor allowing specific source of randomness</summary>
|
||||
/// <param name="random">Instance of <c>SecureRandom</c> to use.</param>
|
||||
public CmsAuthenticatedDataStreamGenerator(SecureRandom random)
|
||||
: base(random)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the underlying string size for encapsulated data
|
||||
*
|
||||
* @param bufferSize length of octet strings to buffer the data.
|
||||
*/
|
||||
public void SetBufferSize(
|
||||
int bufferSize)
|
||||
{
|
||||
_bufferSize = bufferSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use a BER Set to store the recipient information
|
||||
*/
|
||||
public void SetBerEncodeRecipients(
|
||||
bool berEncodeRecipientSet)
|
||||
{
|
||||
_berEncodeRecipientSet = berEncodeRecipientSet;
|
||||
}
|
||||
|
||||
/**
|
||||
* generate an enveloped object that contains an CMS Enveloped Data
|
||||
* object using the given provider and the passed in key generator.
|
||||
* @throws java.io.IOException
|
||||
*/
|
||||
private Stream Open(
|
||||
Stream outStr,
|
||||
string macOid,
|
||||
CipherKeyGenerator keyGen)
|
||||
{
|
||||
// FIXME Will this work for macs?
|
||||
byte[] encKeyBytes = keyGen.GenerateKey();
|
||||
KeyParameter encKey = ParameterUtilities.CreateKeyParameter(macOid, encKeyBytes);
|
||||
|
||||
Asn1Encodable asn1Params = GenerateAsn1Parameters(macOid, encKeyBytes);
|
||||
|
||||
ICipherParameters cipherParameters;
|
||||
AlgorithmIdentifier macAlgId = GetAlgorithmIdentifier(
|
||||
macOid, encKey, asn1Params, out cipherParameters);
|
||||
|
||||
Asn1EncodableVector recipientInfos = new Asn1EncodableVector();
|
||||
|
||||
foreach (RecipientInfoGenerator rig in recipientInfoGenerators)
|
||||
{
|
||||
try
|
||||
{
|
||||
recipientInfos.Add(rig.Generate(encKey, m_random));
|
||||
}
|
||||
catch (InvalidKeyException e)
|
||||
{
|
||||
throw new CmsException("key inappropriate for algorithm.", e);
|
||||
}
|
||||
catch (GeneralSecurityException e)
|
||||
{
|
||||
throw new CmsException("error making encrypted content.", e);
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME Only passing key at the moment
|
||||
// return Open(outStr, macAlgId, cipherParameters, recipientInfos);
|
||||
return Open(outStr, macAlgId, encKey, recipientInfos);
|
||||
}
|
||||
|
||||
protected Stream Open(
|
||||
Stream outStr,
|
||||
AlgorithmIdentifier macAlgId,
|
||||
ICipherParameters cipherParameters,
|
||||
Asn1EncodableVector recipientInfos)
|
||||
{
|
||||
try
|
||||
{
|
||||
//
|
||||
// ContentInfo
|
||||
//
|
||||
BerSequenceGenerator cGen = new BerSequenceGenerator(outStr);
|
||||
|
||||
cGen.AddObject(CmsObjectIdentifiers.AuthenticatedData);
|
||||
|
||||
//
|
||||
// Authenticated Data
|
||||
//
|
||||
BerSequenceGenerator authGen = new BerSequenceGenerator(
|
||||
cGen.GetRawOutputStream(), 0, true);
|
||||
|
||||
authGen.AddObject(new DerInteger(AuthenticatedData.CalculateVersion(null)));
|
||||
|
||||
Stream authRaw = authGen.GetRawOutputStream();
|
||||
Asn1Generator recipGen = _berEncodeRecipientSet
|
||||
? (Asn1Generator) new BerSetGenerator(authRaw)
|
||||
: new DerSetGenerator(authRaw);
|
||||
|
||||
foreach (Asn1Encodable ae in recipientInfos)
|
||||
{
|
||||
recipGen.AddObject(ae);
|
||||
}
|
||||
|
||||
recipGen.Close();
|
||||
|
||||
authGen.AddObject(macAlgId);
|
||||
|
||||
BerSequenceGenerator eiGen = new BerSequenceGenerator(authRaw);
|
||||
eiGen.AddObject(CmsObjectIdentifiers.Data);
|
||||
|
||||
Stream octetOutputStream = CmsUtilities.CreateBerOctetOutputStream(
|
||||
eiGen.GetRawOutputStream(), 0, true, _bufferSize);
|
||||
|
||||
IMac mac = MacUtilities.GetMac(macAlgId.Algorithm);
|
||||
// TODO Confirm no ParametersWithRandom needed
|
||||
mac.Init(cipherParameters);
|
||||
Stream mOut = new TeeOutputStream(octetOutputStream, new MacSink(mac));
|
||||
|
||||
return new CmsAuthenticatedDataOutputStream(mOut, mac, cGen, authGen, eiGen);
|
||||
}
|
||||
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("exception decoding algorithm parameters.", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* generate an enveloped object that contains an CMS Enveloped Data object
|
||||
*/
|
||||
public Stream Open(
|
||||
Stream outStr,
|
||||
string encryptionOid)
|
||||
{
|
||||
CipherKeyGenerator keyGen = GeneratorUtilities.GetKeyGenerator(encryptionOid);
|
||||
|
||||
keyGen.Init(new KeyGenerationParameters(m_random, keyGen.DefaultStrength));
|
||||
|
||||
return Open(outStr, encryptionOid, keyGen);
|
||||
}
|
||||
|
||||
/**
|
||||
* generate an enveloped object that contains an CMS Enveloped Data object
|
||||
*/
|
||||
public Stream Open(
|
||||
Stream outStr,
|
||||
string encryptionOid,
|
||||
int keySize)
|
||||
{
|
||||
CipherKeyGenerator keyGen = GeneratorUtilities.GetKeyGenerator(encryptionOid);
|
||||
|
||||
keyGen.Init(new KeyGenerationParameters(m_random, keySize));
|
||||
|
||||
return Open(outStr, encryptionOid, keyGen);
|
||||
}
|
||||
|
||||
private class CmsAuthenticatedDataOutputStream
|
||||
: BaseOutputStream
|
||||
{
|
||||
private readonly Stream macStream;
|
||||
private readonly IMac mac;
|
||||
private readonly BerSequenceGenerator cGen;
|
||||
private readonly BerSequenceGenerator authGen;
|
||||
private readonly BerSequenceGenerator eiGen;
|
||||
|
||||
public CmsAuthenticatedDataOutputStream(
|
||||
Stream macStream,
|
||||
IMac mac,
|
||||
BerSequenceGenerator cGen,
|
||||
BerSequenceGenerator authGen,
|
||||
BerSequenceGenerator eiGen)
|
||||
{
|
||||
this.macStream = macStream;
|
||||
this.mac = mac;
|
||||
this.cGen = cGen;
|
||||
this.authGen = authGen;
|
||||
this.eiGen = eiGen;
|
||||
}
|
||||
|
||||
public override void Write(byte[] buffer, int offset, int count)
|
||||
{
|
||||
macStream.Write(buffer, offset, count);
|
||||
}
|
||||
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || _UNITY_2021_2_OR_NEWER_
|
||||
public override void Write(ReadOnlySpan<byte> buffer)
|
||||
{
|
||||
macStream.Write(buffer);
|
||||
}
|
||||
#endif
|
||||
|
||||
public override void WriteByte(byte value)
|
||||
{
|
||||
macStream.WriteByte(value);
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
macStream.Dispose();
|
||||
|
||||
// TODO Parent context(s) should really be be closed explicitly
|
||||
|
||||
eiGen.Close();
|
||||
|
||||
// [TODO] auth attributes go here
|
||||
byte[] macOctets = MacUtilities.DoFinal(mac);
|
||||
authGen.AddObject(new DerOctetString(macOctets));
|
||||
// [TODO] unauth attributes go here
|
||||
|
||||
authGen.Close();
|
||||
cGen.Close();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c74bee6672ed33d4484fbb4d444253e4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,32 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.X509;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Security;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Date;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.IO;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Cms
|
||||
{
|
||||
public class CmsAuthenticatedGenerator
|
||||
: CmsEnvelopedGenerator
|
||||
{
|
||||
public CmsAuthenticatedGenerator()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>Constructor allowing specific source of randomness</summary>
|
||||
/// <param name="random">Instance of <c>SecureRandom</c> to use.</param>
|
||||
public CmsAuthenticatedGenerator(SecureRandom random)
|
||||
: base(random)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 37764ed0474059d4cb0346705d807def
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,110 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System.IO;
|
||||
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Cms;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.IO.Compression;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Cms
|
||||
{
|
||||
/**
|
||||
* containing class for an CMS Compressed Data object
|
||||
*/
|
||||
public class CmsCompressedData
|
||||
{
|
||||
internal ContentInfo contentInfo;
|
||||
|
||||
public CmsCompressedData(
|
||||
byte[] compressedData)
|
||||
: this(CmsUtilities.ReadContentInfo(compressedData))
|
||||
{
|
||||
}
|
||||
|
||||
public CmsCompressedData(
|
||||
Stream compressedDataStream)
|
||||
: this(CmsUtilities.ReadContentInfo(compressedDataStream))
|
||||
{
|
||||
}
|
||||
|
||||
public CmsCompressedData(
|
||||
ContentInfo contentInfo)
|
||||
{
|
||||
this.contentInfo = contentInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the uncompressed content.
|
||||
*
|
||||
* @return the uncompressed content
|
||||
* @throws CmsException if there is an exception uncompressing the data.
|
||||
*/
|
||||
public byte[] GetContent()
|
||||
{
|
||||
CompressedData comData = CompressedData.GetInstance(contentInfo.Content);
|
||||
ContentInfo content = comData.EncapContentInfo;
|
||||
|
||||
Asn1OctetString bytes = (Asn1OctetString) content.Content;
|
||||
Stream zIn = ZLib.DecompressInput(bytes.GetOctetStream());
|
||||
|
||||
try
|
||||
{
|
||||
return CmsUtilities.StreamToByteArray(zIn);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new CmsException("exception reading compressed stream.", e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
zIn.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the uncompressed content, throwing an exception if the data size
|
||||
* is greater than the passed in limit. If the content is exceeded getCause()
|
||||
* on the CMSException will contain a StreamOverflowException
|
||||
*
|
||||
* @param limit maximum number of bytes to read
|
||||
* @return the content read
|
||||
* @throws CMSException if there is an exception uncompressing the data.
|
||||
*/
|
||||
public byte[] GetContent(int limit)
|
||||
{
|
||||
CompressedData comData = CompressedData.GetInstance(contentInfo.Content);
|
||||
ContentInfo content = comData.EncapContentInfo;
|
||||
|
||||
Asn1OctetString bytes = (Asn1OctetString)content.Content;
|
||||
Stream zIn = ZLib.DecompressInput(bytes.GetOctetStream());
|
||||
|
||||
try
|
||||
{
|
||||
return CmsUtilities.StreamToByteArray(zIn, limit);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new CmsException("exception reading compressed stream.", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* return the ContentInfo
|
||||
*/
|
||||
public ContentInfo ContentInfo
|
||||
{
|
||||
get { return contentInfo; }
|
||||
}
|
||||
|
||||
/**
|
||||
* return the ASN.1 encoded representation of this object.
|
||||
*/
|
||||
public byte[] GetEncoded()
|
||||
{
|
||||
return contentInfo.GetEncoded();
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4cbc55acb9953154086972e91a119005
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,71 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
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.Utilities;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Cms
|
||||
{
|
||||
/**
|
||||
* General class for generating a compressed CMS message.
|
||||
* <p>
|
||||
* A simple example of usage.</p>
|
||||
* <p>
|
||||
* <pre>
|
||||
* CMSCompressedDataGenerator fact = new CMSCompressedDataGenerator();
|
||||
* CMSCompressedData data = fact.Generate(content, algorithm);
|
||||
* </pre>
|
||||
* </p>
|
||||
*/
|
||||
public class CmsCompressedDataGenerator
|
||||
{
|
||||
public static readonly string ZLib = CmsObjectIdentifiers.ZlibCompress.Id;
|
||||
|
||||
public CmsCompressedDataGenerator()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate an object that contains an CMS Compressed Data
|
||||
*/
|
||||
public CmsCompressedData Generate(CmsProcessable content, string compressionOid)
|
||||
{
|
||||
if (ZLib != compressionOid)
|
||||
throw new ArgumentException("Unsupported compression algorithm: " + compressionOid,
|
||||
nameof(compressionOid));
|
||||
|
||||
AlgorithmIdentifier comAlgId;
|
||||
Asn1OctetString comOcts;
|
||||
|
||||
try
|
||||
{
|
||||
MemoryStream bOut = new MemoryStream();
|
||||
|
||||
using (var zOut = Utilities.IO.Compression.ZLib.CompressOutput(bOut, -1))
|
||||
{
|
||||
content.Write(zOut);
|
||||
}
|
||||
|
||||
comAlgId = new AlgorithmIdentifier(CmsObjectIdentifiers.ZlibCompress);
|
||||
comOcts = new BerOctetString(bOut.ToArray());
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new CmsException("exception encoding data.", e);
|
||||
}
|
||||
|
||||
ContentInfo comContent = new ContentInfo(CmsObjectIdentifiers.Data, comOcts);
|
||||
ContentInfo contentInfo = new ContentInfo(
|
||||
CmsObjectIdentifiers.CompressedData,
|
||||
new CompressedData(comAlgId, comContent));
|
||||
|
||||
return new CmsCompressedData(contentInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7769c99d12beb884b8c70fd13c920cbf
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,61 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Cms;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.IO.Compression;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Cms
|
||||
{
|
||||
/**
|
||||
* Class for reading a CMS Compressed Data stream.
|
||||
* <pre>
|
||||
* CMSCompressedDataParser cp = new CMSCompressedDataParser(inputStream);
|
||||
*
|
||||
* process(cp.GetContent().GetContentStream());
|
||||
* </pre>
|
||||
* Note: this class does not introduce buffering - if you are processing large files you should create
|
||||
* the parser with:
|
||||
* <pre>
|
||||
* CMSCompressedDataParser ep = new CMSCompressedDataParser(new BufferedInputStream(inputStream, bufSize));
|
||||
* </pre>
|
||||
* where bufSize is a suitably large buffer size.
|
||||
*/
|
||||
public class CmsCompressedDataParser
|
||||
: CmsContentInfoParser
|
||||
{
|
||||
public CmsCompressedDataParser(
|
||||
byte[] compressedData)
|
||||
: this(new MemoryStream(compressedData, false))
|
||||
{
|
||||
}
|
||||
|
||||
public CmsCompressedDataParser(
|
||||
Stream compressedData)
|
||||
: base(compressedData)
|
||||
{
|
||||
}
|
||||
|
||||
public CmsTypedStream GetContent()
|
||||
{
|
||||
try
|
||||
{
|
||||
CompressedDataParser comData = new CompressedDataParser((Asn1SequenceParser)this.contentInfo.GetContent(Asn1Tags.Sequence));
|
||||
ContentInfoParser content = comData.GetEncapContentInfo();
|
||||
|
||||
Asn1OctetStringParser bytes = (Asn1OctetStringParser)content.GetContent(Asn1Tags.OctetString);
|
||||
Stream zIn = ZLib.DecompressInput(bytes.GetOctetStream());
|
||||
|
||||
return new CmsTypedStream(content.ContentType.ToString(), zIn);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new CmsException("IOException reading compressed content.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 622eaf613f9bfed4bad33078ade6c789
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,154 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
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.IO;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.IO;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Cms
|
||||
{
|
||||
/**
|
||||
* General class for generating a compressed CMS message stream.
|
||||
* <p>
|
||||
* A simple example of usage.
|
||||
* </p>
|
||||
* <pre>
|
||||
* CMSCompressedDataStreamGenerator gen = new CMSCompressedDataStreamGenerator();
|
||||
*
|
||||
* Stream cOut = gen.Open(outputStream, CMSCompressedDataStreamGenerator.ZLIB);
|
||||
*
|
||||
* cOut.Write(data);
|
||||
*
|
||||
* cOut.Close();
|
||||
* </pre>
|
||||
*/
|
||||
public class CmsCompressedDataStreamGenerator
|
||||
{
|
||||
public static readonly string ZLib = CmsObjectIdentifiers.ZlibCompress.Id;
|
||||
|
||||
private int _bufferSize;
|
||||
|
||||
/**
|
||||
* base constructor
|
||||
*/
|
||||
public CmsCompressedDataStreamGenerator()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the underlying string size for encapsulated data
|
||||
*
|
||||
* @param bufferSize length of octet strings to buffer the data.
|
||||
*/
|
||||
public void SetBufferSize(int bufferSize)
|
||||
{
|
||||
_bufferSize = bufferSize;
|
||||
}
|
||||
|
||||
public Stream Open(Stream outStream)
|
||||
{
|
||||
return Open(outStream, CmsObjectIdentifiers.Data.Id, ZLib);
|
||||
}
|
||||
|
||||
public Stream Open(Stream outStream, string compressionOid)
|
||||
{
|
||||
return Open(outStream, CmsObjectIdentifiers.Data.Id, compressionOid);
|
||||
}
|
||||
|
||||
public Stream Open(Stream outStream, string contentOid, string compressionOid)
|
||||
{
|
||||
if (ZLib != compressionOid)
|
||||
throw new ArgumentException("Unsupported compression algorithm: " + compressionOid,
|
||||
nameof(compressionOid));
|
||||
|
||||
BerSequenceGenerator sGen = new BerSequenceGenerator(outStream);
|
||||
|
||||
sGen.AddObject(CmsObjectIdentifiers.CompressedData);
|
||||
|
||||
//
|
||||
// Compressed Data
|
||||
//
|
||||
BerSequenceGenerator cGen = new BerSequenceGenerator(
|
||||
sGen.GetRawOutputStream(), 0, true);
|
||||
|
||||
// CMSVersion
|
||||
cGen.AddObject(new DerInteger(0));
|
||||
|
||||
// CompressionAlgorithmIdentifier
|
||||
cGen.AddObject(new AlgorithmIdentifier(CmsObjectIdentifiers.ZlibCompress));
|
||||
|
||||
//
|
||||
// Encapsulated ContentInfo
|
||||
//
|
||||
BerSequenceGenerator eiGen = new BerSequenceGenerator(cGen.GetRawOutputStream());
|
||||
|
||||
eiGen.AddObject(new DerObjectIdentifier(contentOid));
|
||||
|
||||
Stream octetStream = CmsUtilities.CreateBerOctetOutputStream(
|
||||
eiGen.GetRawOutputStream(), 0, true, _bufferSize);
|
||||
|
||||
return new CmsCompressedOutputStream(
|
||||
Utilities.IO.Compression.ZLib.CompressOutput(octetStream, -1), sGen, cGen, eiGen);
|
||||
}
|
||||
|
||||
private class CmsCompressedOutputStream
|
||||
: BaseOutputStream
|
||||
{
|
||||
private Stream _out;
|
||||
private BerSequenceGenerator _sGen;
|
||||
private BerSequenceGenerator _cGen;
|
||||
private BerSequenceGenerator _eiGen;
|
||||
|
||||
internal CmsCompressedOutputStream(
|
||||
Stream outStream,
|
||||
BerSequenceGenerator sGen,
|
||||
BerSequenceGenerator cGen,
|
||||
BerSequenceGenerator eiGen)
|
||||
{
|
||||
_out = outStream;
|
||||
_sGen = sGen;
|
||||
_cGen = cGen;
|
||||
_eiGen = eiGen;
|
||||
}
|
||||
|
||||
public override void Write(byte[] buffer, int offset, int count)
|
||||
{
|
||||
_out.Write(buffer, offset, count);
|
||||
}
|
||||
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || _UNITY_2021_2_OR_NEWER_
|
||||
public override void Write(ReadOnlySpan<byte> buffer)
|
||||
{
|
||||
_out.Write(buffer);
|
||||
}
|
||||
#endif
|
||||
|
||||
public override void WriteByte(byte value)
|
||||
{
|
||||
_out.WriteByte(value);
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
_out.Dispose();
|
||||
|
||||
// TODO Parent context(s) should really be be closed explicitly
|
||||
|
||||
_eiGen.Close();
|
||||
_cGen.Close();
|
||||
_sGen.Close();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d91ec399f12b551429fc03e870166006
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,52 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Cms;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Cms
|
||||
{
|
||||
public class CmsContentInfoParser
|
||||
{
|
||||
protected ContentInfoParser contentInfo;
|
||||
protected Stream data;
|
||||
|
||||
protected CmsContentInfoParser(
|
||||
Stream data)
|
||||
{
|
||||
if (data == null)
|
||||
throw new ArgumentNullException("data");
|
||||
|
||||
this.data = data;
|
||||
|
||||
try
|
||||
{
|
||||
Asn1StreamParser inStream = new Asn1StreamParser(data);
|
||||
|
||||
this.contentInfo = new ContentInfoParser((Asn1SequenceParser)inStream.ReadObject());
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new CmsException("IOException reading content.", e);
|
||||
}
|
||||
catch (InvalidCastException e)
|
||||
{
|
||||
throw new CmsException("Unexpected object reading content.", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the underlying data stream.
|
||||
* @throws IOException if the close fails.
|
||||
*/
|
||||
public void Close()
|
||||
{
|
||||
data.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e4a4f23cbc361fd44aea8365372784a9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,116 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Cms;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.X509;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Cms
|
||||
{
|
||||
/**
|
||||
* containing class for an CMS Enveloped Data object
|
||||
*/
|
||||
public class CmsEnvelopedData
|
||||
{
|
||||
internal RecipientInformationStore recipientInfoStore;
|
||||
internal ContentInfo contentInfo;
|
||||
|
||||
private AlgorithmIdentifier encAlg;
|
||||
private Asn1Set unprotectedAttributes;
|
||||
|
||||
public CmsEnvelopedData(
|
||||
byte[] envelopedData)
|
||||
: this(CmsUtilities.ReadContentInfo(envelopedData))
|
||||
{
|
||||
}
|
||||
|
||||
public CmsEnvelopedData(
|
||||
Stream envelopedData)
|
||||
: this(CmsUtilities.ReadContentInfo(envelopedData))
|
||||
{
|
||||
}
|
||||
|
||||
public CmsEnvelopedData(
|
||||
ContentInfo contentInfo)
|
||||
{
|
||||
this.contentInfo = contentInfo;
|
||||
|
||||
EnvelopedData envData = EnvelopedData.GetInstance(contentInfo.Content);
|
||||
|
||||
//
|
||||
// read the recipients
|
||||
//
|
||||
Asn1Set recipientInfos = envData.RecipientInfos;
|
||||
|
||||
//
|
||||
// read the encrypted content info
|
||||
//
|
||||
EncryptedContentInfo encInfo = envData.EncryptedContentInfo;
|
||||
this.encAlg = encInfo.ContentEncryptionAlgorithm;
|
||||
CmsReadable readable = new CmsProcessableByteArray(encInfo.EncryptedContent.GetOctets());
|
||||
CmsSecureReadable secureReadable = new CmsEnvelopedHelper.CmsEnvelopedSecureReadable(
|
||||
this.encAlg, readable);
|
||||
|
||||
//
|
||||
// build the RecipientInformationStore
|
||||
//
|
||||
this.recipientInfoStore = CmsEnvelopedHelper.BuildRecipientInformationStore(
|
||||
recipientInfos, secureReadable);
|
||||
|
||||
this.unprotectedAttributes = envData.UnprotectedAttrs;
|
||||
}
|
||||
|
||||
public AlgorithmIdentifier EncryptionAlgorithmID
|
||||
{
|
||||
get { return encAlg; }
|
||||
}
|
||||
|
||||
/**
|
||||
* return the object identifier for the content encryption algorithm.
|
||||
*/
|
||||
public string EncryptionAlgOid
|
||||
{
|
||||
get { return encAlg.Algorithm.Id; }
|
||||
}
|
||||
|
||||
/**
|
||||
* return a store of the intended recipients for this message
|
||||
*/
|
||||
public RecipientInformationStore GetRecipientInfos()
|
||||
{
|
||||
return recipientInfoStore;
|
||||
}
|
||||
|
||||
/**
|
||||
* return the ContentInfo
|
||||
*/
|
||||
public ContentInfo ContentInfo
|
||||
{
|
||||
get { return contentInfo; }
|
||||
}
|
||||
|
||||
/**
|
||||
* return a table of the unprotected attributes indexed by
|
||||
* the OID of the attribute.
|
||||
*/
|
||||
public Asn1.Cms.AttributeTable GetUnprotectedAttributes()
|
||||
{
|
||||
if (unprotectedAttributes == null)
|
||||
return null;
|
||||
|
||||
return new Asn1.Cms.AttributeTable(unprotectedAttributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* return the ASN.1 encoded representation of this object.
|
||||
*/
|
||||
public byte[] GetEncoded()
|
||||
{
|
||||
return contentInfo.GetEncoded();
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8ea637f918b56de47aab71d1b268782a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,246 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System.Collections.Generic;
|
||||
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;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Cms
|
||||
{
|
||||
/// <remarks>
|
||||
/// General class for generating a CMS enveloped-data message.
|
||||
///
|
||||
/// A simple example of usage.
|
||||
///
|
||||
/// <pre>
|
||||
/// CmsEnvelopedDataGenerator fact = new CmsEnvelopedDataGenerator();
|
||||
///
|
||||
/// fact.AddKeyTransRecipient(cert);
|
||||
///
|
||||
/// CmsEnvelopedData data = fact.Generate(content, algorithm);
|
||||
/// </pre>
|
||||
/// </remarks>
|
||||
public class CmsEnvelopedDataGenerator
|
||||
: CmsEnvelopedGenerator
|
||||
{
|
||||
public CmsEnvelopedDataGenerator()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>Constructor allowing specific source of randomness</summary>
|
||||
/// <param name="random">Instance of <c>SecureRandom</c> to use.</param>
|
||||
public CmsEnvelopedDataGenerator(SecureRandom random)
|
||||
: base(random)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate an enveloped object that contains a CMS Enveloped Data
|
||||
/// object using the passed in key generator.
|
||||
/// </summary>
|
||||
private CmsEnvelopedData Generate(
|
||||
CmsProcessable content,
|
||||
string encryptionOid,
|
||||
CipherKeyGenerator keyGen)
|
||||
{
|
||||
AlgorithmIdentifier encAlgId = null;
|
||||
KeyParameter encKey;
|
||||
Asn1OctetString encContent;
|
||||
|
||||
try
|
||||
{
|
||||
byte[] encKeyBytes = keyGen.GenerateKey();
|
||||
encKey = ParameterUtilities.CreateKeyParameter(encryptionOid, encKeyBytes);
|
||||
|
||||
Asn1Encodable asn1Params = GenerateAsn1Parameters(encryptionOid, encKeyBytes);
|
||||
|
||||
ICipherParameters cipherParameters;
|
||||
encAlgId = GetAlgorithmIdentifier(
|
||||
encryptionOid, encKey, asn1Params, out cipherParameters);
|
||||
|
||||
IBufferedCipher cipher = CipherUtilities.GetCipher(encryptionOid);
|
||||
cipher.Init(true, new ParametersWithRandom(cipherParameters, m_random));
|
||||
|
||||
MemoryStream bOut = new MemoryStream();
|
||||
using (var cOut = new CipherStream(bOut, null, cipher))
|
||||
{
|
||||
content.Write(cOut);
|
||||
}
|
||||
|
||||
encContent = new BerOctetString(bOut.ToArray());
|
||||
}
|
||||
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("exception decoding algorithm parameters.", e);
|
||||
}
|
||||
|
||||
|
||||
Asn1EncodableVector recipientInfos = new Asn1EncodableVector();
|
||||
|
||||
foreach (RecipientInfoGenerator rig in recipientInfoGenerators)
|
||||
{
|
||||
try
|
||||
{
|
||||
recipientInfos.Add(rig.Generate(encKey, m_random));
|
||||
}
|
||||
catch (InvalidKeyException e)
|
||||
{
|
||||
throw new CmsException("key inappropriate for algorithm.", e);
|
||||
}
|
||||
catch (GeneralSecurityException e)
|
||||
{
|
||||
throw new CmsException("error making encrypted content.", e);
|
||||
}
|
||||
}
|
||||
|
||||
EncryptedContentInfo eci = new EncryptedContentInfo(
|
||||
CmsObjectIdentifiers.Data,
|
||||
encAlgId,
|
||||
encContent);
|
||||
|
||||
Asn1Set unprotectedAttrSet = null;
|
||||
if (unprotectedAttributeGenerator != null)
|
||||
{
|
||||
Asn1.Cms.AttributeTable attrTable = unprotectedAttributeGenerator.GetAttributes(
|
||||
new Dictionary<CmsAttributeTableParameter, object>());
|
||||
|
||||
unprotectedAttrSet = new BerSet(attrTable.ToAsn1EncodableVector());
|
||||
}
|
||||
|
||||
ContentInfo contentInfo = new ContentInfo(
|
||||
CmsObjectIdentifiers.EnvelopedData,
|
||||
new EnvelopedData(null, new DerSet(recipientInfos), eci, unprotectedAttrSet));
|
||||
|
||||
return new CmsEnvelopedData(contentInfo);
|
||||
}
|
||||
|
||||
/// <summary>Generate an enveloped object that contains an CMS Enveloped Data object.</summary>
|
||||
public CmsEnvelopedData Generate(
|
||||
CmsProcessable content,
|
||||
string encryptionOid)
|
||||
{
|
||||
try
|
||||
{
|
||||
CipherKeyGenerator keyGen = GeneratorUtilities.GetKeyGenerator(encryptionOid);
|
||||
|
||||
keyGen.Init(new KeyGenerationParameters(m_random, keyGen.DefaultStrength));
|
||||
|
||||
return Generate(content, encryptionOid, keyGen);
|
||||
}
|
||||
catch (SecurityUtilityException e)
|
||||
{
|
||||
throw new CmsException("can't find key generation algorithm.", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public CmsEnvelopedData Generate(CmsProcessable content, ICipherBuilderWithKey cipherBuilder)
|
||||
{
|
||||
//AlgorithmIdentifier encAlgId = null;
|
||||
KeyParameter encKey;
|
||||
Asn1OctetString encContent;
|
||||
|
||||
try
|
||||
{
|
||||
encKey = (KeyParameter) cipherBuilder.Key;
|
||||
|
||||
MemoryStream collector = new MemoryStream();
|
||||
var cipher = cipherBuilder.BuildCipher(collector);
|
||||
using (var bOut = cipher.Stream)
|
||||
{
|
||||
content.Write(bOut);
|
||||
}
|
||||
|
||||
encContent = new BerOctetString(collector.ToArray());
|
||||
}
|
||||
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("exception decoding algorithm parameters.", e);
|
||||
}
|
||||
|
||||
|
||||
Asn1EncodableVector recipientInfos = new Asn1EncodableVector();
|
||||
|
||||
foreach (RecipientInfoGenerator rig in recipientInfoGenerators)
|
||||
{
|
||||
try
|
||||
{
|
||||
recipientInfos.Add(rig.Generate(encKey, m_random));
|
||||
}
|
||||
catch (InvalidKeyException e)
|
||||
{
|
||||
throw new CmsException("key inappropriate for algorithm.", e);
|
||||
}
|
||||
catch (GeneralSecurityException e)
|
||||
{
|
||||
throw new CmsException("error making encrypted content.", e);
|
||||
}
|
||||
}
|
||||
|
||||
EncryptedContentInfo eci = new EncryptedContentInfo(
|
||||
CmsObjectIdentifiers.Data,
|
||||
(AlgorithmIdentifier) cipherBuilder.AlgorithmDetails,
|
||||
encContent);
|
||||
|
||||
Asn1Set unprotectedAttrSet = null;
|
||||
if (unprotectedAttributeGenerator != null)
|
||||
{
|
||||
Asn1.Cms.AttributeTable attrTable = unprotectedAttributeGenerator.GetAttributes(
|
||||
new Dictionary<CmsAttributeTableParameter, object>());
|
||||
|
||||
unprotectedAttrSet = new BerSet(attrTable.ToAsn1EncodableVector());
|
||||
}
|
||||
|
||||
ContentInfo contentInfo = new ContentInfo(
|
||||
CmsObjectIdentifiers.EnvelopedData,
|
||||
new EnvelopedData(null, new DerSet(recipientInfos), eci, unprotectedAttrSet));
|
||||
|
||||
return new CmsEnvelopedData(contentInfo);
|
||||
}
|
||||
|
||||
/// <summary>Generate an enveloped object that contains an CMS Enveloped Data object.</summary>
|
||||
public CmsEnvelopedData Generate(
|
||||
CmsProcessable content,
|
||||
string encryptionOid,
|
||||
int keySize)
|
||||
{
|
||||
try
|
||||
{
|
||||
CipherKeyGenerator keyGen = GeneratorUtilities.GetKeyGenerator(encryptionOid);
|
||||
|
||||
keyGen.Init(new KeyGenerationParameters(m_random, keySize));
|
||||
|
||||
return Generate(content, encryptionOid, keyGen);
|
||||
}
|
||||
catch (SecurityUtilityException e)
|
||||
{
|
||||
throw new CmsException("can't find key generation algorithm.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: aa4d4e34c5881f74ca33adf98582b07c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,163 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Cms;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.X509;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Cms
|
||||
{
|
||||
/**
|
||||
* Parsing class for an CMS Enveloped Data object from an input stream.
|
||||
* <p>
|
||||
* Note: that because we are in a streaming mode only one recipient can be tried and it is important
|
||||
* that the methods on the parser are called in the appropriate order.
|
||||
* </p>
|
||||
* <p>
|
||||
* Example of use - assuming the first recipient matches the private key we have.
|
||||
* <pre>
|
||||
* CmsEnvelopedDataParser ep = new CmsEnvelopedDataParser(inputStream);
|
||||
*
|
||||
* RecipientInformationStore recipients = ep.GetRecipientInfos();
|
||||
*
|
||||
* Collection c = recipients.getRecipients();
|
||||
* Iterator it = c.iterator();
|
||||
*
|
||||
* if (it.hasNext())
|
||||
* {
|
||||
* RecipientInformation recipient = (RecipientInformation)it.next();
|
||||
*
|
||||
* CMSTypedStream recData = recipient.getContentStream(privateKey);
|
||||
*
|
||||
* processDataStream(recData.getContentStream());
|
||||
* }
|
||||
* </pre>
|
||||
* Note: this class does not introduce buffering - if you are processing large files you should create
|
||||
* the parser with:
|
||||
* <pre>
|
||||
* CmsEnvelopedDataParser ep = new CmsEnvelopedDataParser(new BufferedInputStream(inputStream, bufSize));
|
||||
* </pre>
|
||||
* where bufSize is a suitably large buffer size.
|
||||
* </p>
|
||||
*/
|
||||
public class CmsEnvelopedDataParser
|
||||
: CmsContentInfoParser
|
||||
{
|
||||
internal RecipientInformationStore recipientInfoStore;
|
||||
internal EnvelopedDataParser envelopedData;
|
||||
|
||||
private AlgorithmIdentifier _encAlg;
|
||||
private Asn1.Cms.AttributeTable _unprotectedAttributes;
|
||||
private bool _attrNotRead;
|
||||
|
||||
public CmsEnvelopedDataParser(
|
||||
byte[] envelopedData)
|
||||
: this(new MemoryStream(envelopedData, false))
|
||||
{
|
||||
}
|
||||
|
||||
public CmsEnvelopedDataParser(
|
||||
Stream envelopedData)
|
||||
: base(envelopedData)
|
||||
{
|
||||
this._attrNotRead = true;
|
||||
this.envelopedData = new EnvelopedDataParser(
|
||||
(Asn1SequenceParser)this.contentInfo.GetContent(Asn1Tags.Sequence));
|
||||
|
||||
// TODO Validate version?
|
||||
//DerInteger version = this.envelopedData.Version;
|
||||
|
||||
//
|
||||
// read the recipients
|
||||
//
|
||||
Asn1Set recipientInfos = Asn1Set.GetInstance(this.envelopedData.GetRecipientInfos().ToAsn1Object());
|
||||
|
||||
//
|
||||
// read the encrypted content info
|
||||
//
|
||||
EncryptedContentInfoParser encInfo = this.envelopedData.GetEncryptedContentInfo();
|
||||
this._encAlg = encInfo.ContentEncryptionAlgorithm;
|
||||
CmsReadable readable = new CmsProcessableInputStream(
|
||||
((Asn1OctetStringParser)encInfo.GetEncryptedContent(Asn1Tags.OctetString)).GetOctetStream());
|
||||
CmsSecureReadable secureReadable = new CmsEnvelopedHelper.CmsEnvelopedSecureReadable(
|
||||
this._encAlg, readable);
|
||||
|
||||
//
|
||||
// build the RecipientInformationStore
|
||||
//
|
||||
this.recipientInfoStore = CmsEnvelopedHelper.BuildRecipientInformationStore(
|
||||
recipientInfos, secureReadable);
|
||||
}
|
||||
|
||||
public AlgorithmIdentifier EncryptionAlgorithmID
|
||||
{
|
||||
get { return _encAlg; }
|
||||
}
|
||||
|
||||
/**
|
||||
* return the object identifier for the content encryption algorithm.
|
||||
*/
|
||||
public string EncryptionAlgOid
|
||||
{
|
||||
get { return _encAlg.Algorithm.Id; }
|
||||
}
|
||||
|
||||
/**
|
||||
* return the ASN.1 encoded encryption algorithm parameters, or null if
|
||||
* there aren't any.
|
||||
*/
|
||||
public Asn1Object EncryptionAlgParams
|
||||
{
|
||||
get
|
||||
{
|
||||
Asn1Encodable ae = _encAlg.Parameters;
|
||||
|
||||
return ae == null ? null : ae.ToAsn1Object();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* return a store of the intended recipients for this message
|
||||
*/
|
||||
public RecipientInformationStore GetRecipientInfos()
|
||||
{
|
||||
return this.recipientInfoStore;
|
||||
}
|
||||
|
||||
/**
|
||||
* return a table of the unprotected attributes indexed by
|
||||
* the OID of the attribute.
|
||||
* @throws IOException
|
||||
*/
|
||||
public Asn1.Cms.AttributeTable GetUnprotectedAttributes()
|
||||
{
|
||||
if (_unprotectedAttributes == null && _attrNotRead)
|
||||
{
|
||||
Asn1SetParser asn1Set = this.envelopedData.GetUnprotectedAttrs();
|
||||
|
||||
_attrNotRead = false;
|
||||
|
||||
if (asn1Set != null)
|
||||
{
|
||||
Asn1EncodableVector v = new Asn1EncodableVector();
|
||||
IAsn1Convertible o;
|
||||
|
||||
while ((o = asn1Set.ReadObject()) != null)
|
||||
{
|
||||
Asn1SequenceParser seq = (Asn1SequenceParser)o;
|
||||
|
||||
v.Add(seq.ToAsn1Object());
|
||||
}
|
||||
|
||||
_unprotectedAttributes = new Asn1.Cms.AttributeTable(new DerSet(v));
|
||||
}
|
||||
}
|
||||
|
||||
return _unprotectedAttributes;
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2454ef1eaa70ad84aaf4aaba68576105
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,286 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
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
|
||||
{
|
||||
/**
|
||||
* General class for generating a CMS enveloped-data message stream.
|
||||
* <p>
|
||||
* A simple example of usage.
|
||||
* <pre>
|
||||
* CmsEnvelopedDataStreamGenerator edGen = new CmsEnvelopedDataStreamGenerator();
|
||||
*
|
||||
* edGen.AddKeyTransRecipient(cert);
|
||||
*
|
||||
* MemoryStream bOut = new MemoryStream();
|
||||
*
|
||||
* Stream out = edGen.Open(
|
||||
* bOut, CMSEnvelopedDataGenerator.AES128_CBC);*
|
||||
* out.Write(data);
|
||||
*
|
||||
* out.Close();
|
||||
* </pre>
|
||||
* </p>
|
||||
*/
|
||||
public class CmsEnvelopedDataStreamGenerator
|
||||
: CmsEnvelopedGenerator
|
||||
{
|
||||
private object _originatorInfo = null;
|
||||
private object _unprotectedAttributes = null;
|
||||
private int _bufferSize;
|
||||
private bool _berEncodeRecipientSet;
|
||||
|
||||
public CmsEnvelopedDataStreamGenerator()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>Constructor allowing specific source of randomness</summary>
|
||||
/// <param name="random">Instance of <c>SecureRandom</c> to use.</param>
|
||||
public CmsEnvelopedDataStreamGenerator(SecureRandom random)
|
||||
: base(random)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>Set the underlying string size for encapsulated data.</summary>
|
||||
/// <param name="bufferSize">Length of octet strings to buffer the data.</param>
|
||||
public void SetBufferSize(
|
||||
int bufferSize)
|
||||
{
|
||||
_bufferSize = bufferSize;
|
||||
}
|
||||
|
||||
/// <summary>Use a BER Set to store the recipient information.</summary>
|
||||
public void SetBerEncodeRecipients(
|
||||
bool berEncodeRecipientSet)
|
||||
{
|
||||
_berEncodeRecipientSet = berEncodeRecipientSet;
|
||||
}
|
||||
|
||||
private DerInteger Version
|
||||
{
|
||||
get
|
||||
{
|
||||
int version = (_originatorInfo != null || _unprotectedAttributes != null)
|
||||
? 2
|
||||
: 0;
|
||||
|
||||
return new DerInteger(version);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate an enveloped object that contains an CMS Enveloped Data
|
||||
/// object using the passed in key generator.
|
||||
/// </summary>
|
||||
private Stream Open(
|
||||
Stream outStream,
|
||||
string encryptionOid,
|
||||
CipherKeyGenerator keyGen)
|
||||
{
|
||||
byte[] encKeyBytes = keyGen.GenerateKey();
|
||||
KeyParameter encKey = ParameterUtilities.CreateKeyParameter(encryptionOid, encKeyBytes);
|
||||
|
||||
Asn1Encodable asn1Params = GenerateAsn1Parameters(encryptionOid, encKeyBytes);
|
||||
|
||||
ICipherParameters cipherParameters;
|
||||
AlgorithmIdentifier encAlgID = GetAlgorithmIdentifier(
|
||||
encryptionOid, encKey, asn1Params, out cipherParameters);
|
||||
|
||||
Asn1EncodableVector recipientInfos = new Asn1EncodableVector();
|
||||
|
||||
foreach (RecipientInfoGenerator rig in recipientInfoGenerators)
|
||||
{
|
||||
try
|
||||
{
|
||||
recipientInfos.Add(rig.Generate(encKey, m_random));
|
||||
}
|
||||
catch (InvalidKeyException e)
|
||||
{
|
||||
throw new CmsException("key inappropriate for algorithm.", e);
|
||||
}
|
||||
catch (GeneralSecurityException e)
|
||||
{
|
||||
throw new CmsException("error making encrypted content.", e);
|
||||
}
|
||||
}
|
||||
|
||||
return Open(outStream, encAlgID, cipherParameters, recipientInfos);
|
||||
}
|
||||
|
||||
private Stream Open(
|
||||
Stream outStream,
|
||||
AlgorithmIdentifier encAlgID,
|
||||
ICipherParameters cipherParameters,
|
||||
Asn1EncodableVector recipientInfos)
|
||||
{
|
||||
try
|
||||
{
|
||||
//
|
||||
// ContentInfo
|
||||
//
|
||||
BerSequenceGenerator cGen = new BerSequenceGenerator(outStream);
|
||||
|
||||
cGen.AddObject(CmsObjectIdentifiers.EnvelopedData);
|
||||
|
||||
//
|
||||
// Encrypted Data
|
||||
//
|
||||
BerSequenceGenerator envGen = new BerSequenceGenerator(
|
||||
cGen.GetRawOutputStream(), 0, true);
|
||||
|
||||
envGen.AddObject(this.Version);
|
||||
|
||||
Stream envRaw = envGen.GetRawOutputStream();
|
||||
Asn1Generator recipGen = _berEncodeRecipientSet
|
||||
? (Asn1Generator) new BerSetGenerator(envRaw)
|
||||
: new DerSetGenerator(envRaw);
|
||||
|
||||
foreach (Asn1Encodable ae in recipientInfos)
|
||||
{
|
||||
recipGen.AddObject(ae);
|
||||
}
|
||||
|
||||
recipGen.Close();
|
||||
|
||||
BerSequenceGenerator eiGen = new BerSequenceGenerator(envRaw);
|
||||
eiGen.AddObject(CmsObjectIdentifiers.Data);
|
||||
eiGen.AddObject(encAlgID);
|
||||
|
||||
Stream octetOutputStream = CmsUtilities.CreateBerOctetOutputStream(
|
||||
eiGen.GetRawOutputStream(), 0, false, _bufferSize);
|
||||
|
||||
IBufferedCipher cipher = CipherUtilities.GetCipher(encAlgID.Algorithm);
|
||||
cipher.Init(true, new ParametersWithRandom(cipherParameters, m_random));
|
||||
CipherStream cOut = new CipherStream(octetOutputStream, null, cipher);
|
||||
|
||||
return new CmsEnvelopedDataOutputStream(this, cOut, cGen, envGen, eiGen);
|
||||
}
|
||||
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("exception decoding algorithm parameters.", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* generate an enveloped object that contains an CMS Enveloped Data object
|
||||
* @throws IOException
|
||||
*/
|
||||
public Stream Open(
|
||||
Stream outStream,
|
||||
string encryptionOid)
|
||||
{
|
||||
CipherKeyGenerator keyGen = GeneratorUtilities.GetKeyGenerator(encryptionOid);
|
||||
|
||||
keyGen.Init(new KeyGenerationParameters(m_random, keyGen.DefaultStrength));
|
||||
|
||||
return Open(outStream, encryptionOid, keyGen);
|
||||
}
|
||||
|
||||
/**
|
||||
* generate an enveloped object that contains an CMS Enveloped Data object
|
||||
* @throws IOException
|
||||
*/
|
||||
public Stream Open(
|
||||
Stream outStream,
|
||||
string encryptionOid,
|
||||
int keySize)
|
||||
{
|
||||
CipherKeyGenerator keyGen = GeneratorUtilities.GetKeyGenerator(encryptionOid);
|
||||
|
||||
keyGen.Init(new KeyGenerationParameters(m_random, keySize));
|
||||
|
||||
return Open(outStream, encryptionOid, keyGen);
|
||||
}
|
||||
|
||||
private class CmsEnvelopedDataOutputStream
|
||||
: BaseOutputStream
|
||||
{
|
||||
private readonly CmsEnvelopedGenerator _outer;
|
||||
|
||||
private readonly CipherStream _out;
|
||||
private readonly BerSequenceGenerator _cGen;
|
||||
private readonly BerSequenceGenerator _envGen;
|
||||
private readonly BerSequenceGenerator _eiGen;
|
||||
|
||||
public CmsEnvelopedDataOutputStream(
|
||||
CmsEnvelopedGenerator outer,
|
||||
CipherStream outStream,
|
||||
BerSequenceGenerator cGen,
|
||||
BerSequenceGenerator envGen,
|
||||
BerSequenceGenerator eiGen)
|
||||
{
|
||||
_outer = outer;
|
||||
_out = outStream;
|
||||
_cGen = cGen;
|
||||
_envGen = envGen;
|
||||
_eiGen = eiGen;
|
||||
}
|
||||
|
||||
public override void Write(byte[] buffer, int offset, int count)
|
||||
{
|
||||
_out.Write(buffer, offset, count);
|
||||
}
|
||||
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || _UNITY_2021_2_OR_NEWER_
|
||||
public override void Write(ReadOnlySpan<byte> buffer)
|
||||
{
|
||||
_out.Write(buffer);
|
||||
}
|
||||
#endif
|
||||
|
||||
public override void WriteByte(byte value)
|
||||
{
|
||||
_out.WriteByte(value);
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
_out.Dispose();
|
||||
|
||||
// TODO Parent context(s) should really be closed explicitly
|
||||
|
||||
_eiGen.Close();
|
||||
|
||||
if (_outer.unprotectedAttributeGenerator != null)
|
||||
{
|
||||
Asn1.Cms.AttributeTable attrTable = _outer.unprotectedAttributeGenerator.GetAttributes(
|
||||
new Dictionary<CmsAttributeTableParameter, object>());
|
||||
|
||||
Asn1Set unprotectedAttrs = new BerSet(attrTable.ToAsn1EncodableVector());
|
||||
|
||||
_envGen.AddObject(new DerTaggedObject(false, 1, unprotectedAttrs));
|
||||
}
|
||||
|
||||
_envGen.Close();
|
||||
_cGen.Close();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 505dd39c923b320418fae1526255c484
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,343 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Cms;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Kisa;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Nist;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Ntt;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Pkcs;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.X509;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.X9;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Operators;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Security;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.X509;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Cms
|
||||
{
|
||||
/**
|
||||
* General class for generating a CMS enveloped-data message.
|
||||
*
|
||||
* A simple example of usage.
|
||||
*
|
||||
* <pre>
|
||||
* CMSEnvelopedDataGenerator fact = new CMSEnvelopedDataGenerator();
|
||||
*
|
||||
* fact.addKeyTransRecipient(cert);
|
||||
*
|
||||
* CMSEnvelopedData data = fact.generate(content, algorithm, "BC");
|
||||
* </pre>
|
||||
*/
|
||||
public abstract class CmsEnvelopedGenerator
|
||||
{
|
||||
// Note: These tables are complementary: If rc2Table[i]==j, then rc2Ekb[j]==i
|
||||
internal static readonly short[] rc2Table =
|
||||
{
|
||||
0xbd, 0x56, 0xea, 0xf2, 0xa2, 0xf1, 0xac, 0x2a, 0xb0, 0x93, 0xd1, 0x9c, 0x1b, 0x33, 0xfd, 0xd0,
|
||||
0x30, 0x04, 0xb6, 0xdc, 0x7d, 0xdf, 0x32, 0x4b, 0xf7, 0xcb, 0x45, 0x9b, 0x31, 0xbb, 0x21, 0x5a,
|
||||
0x41, 0x9f, 0xe1, 0xd9, 0x4a, 0x4d, 0x9e, 0xda, 0xa0, 0x68, 0x2c, 0xc3, 0x27, 0x5f, 0x80, 0x36,
|
||||
0x3e, 0xee, 0xfb, 0x95, 0x1a, 0xfe, 0xce, 0xa8, 0x34, 0xa9, 0x13, 0xf0, 0xa6, 0x3f, 0xd8, 0x0c,
|
||||
0x78, 0x24, 0xaf, 0x23, 0x52, 0xc1, 0x67, 0x17, 0xf5, 0x66, 0x90, 0xe7, 0xe8, 0x07, 0xb8, 0x60,
|
||||
0x48, 0xe6, 0x1e, 0x53, 0xf3, 0x92, 0xa4, 0x72, 0x8c, 0x08, 0x15, 0x6e, 0x86, 0x00, 0x84, 0xfa,
|
||||
0xf4, 0x7f, 0x8a, 0x42, 0x19, 0xf6, 0xdb, 0xcd, 0x14, 0x8d, 0x50, 0x12, 0xba, 0x3c, 0x06, 0x4e,
|
||||
0xec, 0xb3, 0x35, 0x11, 0xa1, 0x88, 0x8e, 0x2b, 0x94, 0x99, 0xb7, 0x71, 0x74, 0xd3, 0xe4, 0xbf,
|
||||
0x3a, 0xde, 0x96, 0x0e, 0xbc, 0x0a, 0xed, 0x77, 0xfc, 0x37, 0x6b, 0x03, 0x79, 0x89, 0x62, 0xc6,
|
||||
0xd7, 0xc0, 0xd2, 0x7c, 0x6a, 0x8b, 0x22, 0xa3, 0x5b, 0x05, 0x5d, 0x02, 0x75, 0xd5, 0x61, 0xe3,
|
||||
0x18, 0x8f, 0x55, 0x51, 0xad, 0x1f, 0x0b, 0x5e, 0x85, 0xe5, 0xc2, 0x57, 0x63, 0xca, 0x3d, 0x6c,
|
||||
0xb4, 0xc5, 0xcc, 0x70, 0xb2, 0x91, 0x59, 0x0d, 0x47, 0x20, 0xc8, 0x4f, 0x58, 0xe0, 0x01, 0xe2,
|
||||
0x16, 0x38, 0xc4, 0x6f, 0x3b, 0x0f, 0x65, 0x46, 0xbe, 0x7e, 0x2d, 0x7b, 0x82, 0xf9, 0x40, 0xb5,
|
||||
0x1d, 0x73, 0xf8, 0xeb, 0x26, 0xc7, 0x87, 0x97, 0x25, 0x54, 0xb1, 0x28, 0xaa, 0x98, 0x9d, 0xa5,
|
||||
0x64, 0x6d, 0x7a, 0xd4, 0x10, 0x81, 0x44, 0xef, 0x49, 0xd6, 0xae, 0x2e, 0xdd, 0x76, 0x5c, 0x2f,
|
||||
0xa7, 0x1c, 0xc9, 0x09, 0x69, 0x9a, 0x83, 0xcf, 0x29, 0x39, 0xb9, 0xe9, 0x4c, 0xff, 0x43, 0xab
|
||||
};
|
||||
|
||||
// internal static readonly short[] rc2Ekb =
|
||||
// {
|
||||
// 0x5d, 0xbe, 0x9b, 0x8b, 0x11, 0x99, 0x6e, 0x4d, 0x59, 0xf3, 0x85, 0xa6, 0x3f, 0xb7, 0x83, 0xc5,
|
||||
// 0xe4, 0x73, 0x6b, 0x3a, 0x68, 0x5a, 0xc0, 0x47, 0xa0, 0x64, 0x34, 0x0c, 0xf1, 0xd0, 0x52, 0xa5,
|
||||
// 0xb9, 0x1e, 0x96, 0x43, 0x41, 0xd8, 0xd4, 0x2c, 0xdb, 0xf8, 0x07, 0x77, 0x2a, 0xca, 0xeb, 0xef,
|
||||
// 0x10, 0x1c, 0x16, 0x0d, 0x38, 0x72, 0x2f, 0x89, 0xc1, 0xf9, 0x80, 0xc4, 0x6d, 0xae, 0x30, 0x3d,
|
||||
// 0xce, 0x20, 0x63, 0xfe, 0xe6, 0x1a, 0xc7, 0xb8, 0x50, 0xe8, 0x24, 0x17, 0xfc, 0x25, 0x6f, 0xbb,
|
||||
// 0x6a, 0xa3, 0x44, 0x53, 0xd9, 0xa2, 0x01, 0xab, 0xbc, 0xb6, 0x1f, 0x98, 0xee, 0x9a, 0xa7, 0x2d,
|
||||
// 0x4f, 0x9e, 0x8e, 0xac, 0xe0, 0xc6, 0x49, 0x46, 0x29, 0xf4, 0x94, 0x8a, 0xaf, 0xe1, 0x5b, 0xc3,
|
||||
// 0xb3, 0x7b, 0x57, 0xd1, 0x7c, 0x9c, 0xed, 0x87, 0x40, 0x8c, 0xe2, 0xcb, 0x93, 0x14, 0xc9, 0x61,
|
||||
// 0x2e, 0xe5, 0xcc, 0xf6, 0x5e, 0xa8, 0x5c, 0xd6, 0x75, 0x8d, 0x62, 0x95, 0x58, 0x69, 0x76, 0xa1,
|
||||
// 0x4a, 0xb5, 0x55, 0x09, 0x78, 0x33, 0x82, 0xd7, 0xdd, 0x79, 0xf5, 0x1b, 0x0b, 0xde, 0x26, 0x21,
|
||||
// 0x28, 0x74, 0x04, 0x97, 0x56, 0xdf, 0x3c, 0xf0, 0x37, 0x39, 0xdc, 0xff, 0x06, 0xa4, 0xea, 0x42,
|
||||
// 0x08, 0xda, 0xb4, 0x71, 0xb0, 0xcf, 0x12, 0x7a, 0x4e, 0xfa, 0x6c, 0x1d, 0x84, 0x00, 0xc8, 0x7f,
|
||||
// 0x91, 0x45, 0xaa, 0x2b, 0xc2, 0xb1, 0x8f, 0xd5, 0xba, 0xf2, 0xad, 0x19, 0xb2, 0x67, 0x36, 0xf7,
|
||||
// 0x0f, 0x0a, 0x92, 0x7d, 0xe3, 0x9d, 0xe9, 0x90, 0x3e, 0x23, 0x27, 0x66, 0x13, 0xec, 0x81, 0x15,
|
||||
// 0xbd, 0x22, 0xbf, 0x9f, 0x7e, 0xa9, 0x51, 0x4b, 0x4c, 0xfb, 0x02, 0xd3, 0x70, 0x86, 0x31, 0xe7,
|
||||
// 0x3b, 0x05, 0x03, 0x54, 0x60, 0x48, 0x65, 0x18, 0xd2, 0xcd, 0x5f, 0x32, 0x88, 0x0e, 0x35, 0xfd
|
||||
// };
|
||||
|
||||
|
||||
// TODO Create named constants for all of these
|
||||
public static readonly string DesEde3Cbc = PkcsObjectIdentifiers.DesEde3Cbc.Id;
|
||||
public static readonly string RC2Cbc = PkcsObjectIdentifiers.RC2Cbc.Id;
|
||||
public const string IdeaCbc = "1.3.6.1.4.1.188.7.1.1.2";
|
||||
public const string Cast5Cbc = "1.2.840.113533.7.66.10";
|
||||
public static readonly string Aes128Cbc = NistObjectIdentifiers.IdAes128Cbc.Id;
|
||||
public static readonly string Aes192Cbc = NistObjectIdentifiers.IdAes192Cbc.Id;
|
||||
public static readonly string Aes256Cbc = NistObjectIdentifiers.IdAes256Cbc.Id;
|
||||
public static readonly string Camellia128Cbc = NttObjectIdentifiers.IdCamellia128Cbc.Id;
|
||||
public static readonly string Camellia192Cbc = NttObjectIdentifiers.IdCamellia192Cbc.Id;
|
||||
public static readonly string Camellia256Cbc = NttObjectIdentifiers.IdCamellia256Cbc.Id;
|
||||
public static readonly string SeedCbc = KisaObjectIdentifiers.IdSeedCbc.Id;
|
||||
|
||||
public static readonly string DesEde3Wrap = PkcsObjectIdentifiers.IdAlgCms3DesWrap.Id;
|
||||
public static readonly string Aes128Wrap = NistObjectIdentifiers.IdAes128Wrap.Id;
|
||||
public static readonly string Aes192Wrap = NistObjectIdentifiers.IdAes192Wrap.Id;
|
||||
public static readonly string Aes256Wrap = NistObjectIdentifiers.IdAes256Wrap.Id;
|
||||
public static readonly string Camellia128Wrap = NttObjectIdentifiers.IdCamellia128Wrap.Id;
|
||||
public static readonly string Camellia192Wrap = NttObjectIdentifiers.IdCamellia192Wrap.Id;
|
||||
public static readonly string Camellia256Wrap = NttObjectIdentifiers.IdCamellia256Wrap.Id;
|
||||
public static readonly string SeedWrap = KisaObjectIdentifiers.IdNpkiAppCmsSeedWrap.Id;
|
||||
|
||||
public static readonly string ECDHSha1Kdf = X9ObjectIdentifiers.DHSinglePassStdDHSha1KdfScheme.Id;
|
||||
public static readonly string ECMqvSha1Kdf = X9ObjectIdentifiers.MqvSinglePassSha1KdfScheme.Id;
|
||||
|
||||
internal readonly IList<RecipientInfoGenerator> recipientInfoGenerators = new List<RecipientInfoGenerator>();
|
||||
internal readonly SecureRandom m_random;
|
||||
|
||||
internal CmsAttributeTableGenerator unprotectedAttributeGenerator = null;
|
||||
|
||||
protected CmsEnvelopedGenerator()
|
||||
: this(CryptoServicesRegistrar.GetSecureRandom())
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>Constructor allowing specific source of randomness</summary>
|
||||
/// <param name="random">Instance of <c>SecureRandom</c> to use.</param>
|
||||
protected CmsEnvelopedGenerator(SecureRandom random)
|
||||
{
|
||||
if (random == null)
|
||||
throw new ArgumentNullException(nameof(random));
|
||||
|
||||
m_random = random;
|
||||
}
|
||||
|
||||
public CmsAttributeTableGenerator UnprotectedAttributeGenerator
|
||||
{
|
||||
get { return this.unprotectedAttributeGenerator; }
|
||||
set { this.unprotectedAttributeGenerator = value; }
|
||||
}
|
||||
|
||||
/**
|
||||
* add a recipient.
|
||||
*
|
||||
* @param cert recipient's public key certificate
|
||||
* @exception ArgumentException if there is a problem with the certificate
|
||||
*/
|
||||
public void AddKeyTransRecipient(
|
||||
X509Certificate cert)
|
||||
{
|
||||
TbsCertificateStructure recipientTbsCert = CmsUtilities.GetTbsCertificateStructure(cert);
|
||||
SubjectPublicKeyInfo info = recipientTbsCert.SubjectPublicKeyInfo;
|
||||
this.AddRecipientInfoGenerator(new KeyTransRecipientInfoGenerator(cert, new Asn1KeyWrapper(info.AlgorithmID.Algorithm, info.AlgorithmID.Parameters, cert)));
|
||||
}
|
||||
|
||||
/**
|
||||
* add a recipient
|
||||
*
|
||||
* @param key the public key used by the recipient
|
||||
* @param subKeyId the identifier for the recipient's public key
|
||||
* @exception ArgumentException if there is a problem with the key
|
||||
*/
|
||||
public void AddKeyTransRecipient(
|
||||
AsymmetricKeyParameter pubKey,
|
||||
byte[] subKeyId)
|
||||
{
|
||||
SubjectPublicKeyInfo info = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(pubKey);
|
||||
this.AddRecipientInfoGenerator(new KeyTransRecipientInfoGenerator(subKeyId, new Asn1KeyWrapper(info.AlgorithmID.Algorithm, info.AlgorithmID.Parameters, pubKey)));
|
||||
}
|
||||
|
||||
/**
|
||||
* add a KEK recipient.
|
||||
* @param key the secret key to use for wrapping
|
||||
* @param keyIdentifier the byte string that identifies the key
|
||||
*/
|
||||
public void AddKekRecipient(
|
||||
string keyAlgorithm, // TODO Remove need for this parameter
|
||||
KeyParameter key,
|
||||
byte[] keyIdentifier)
|
||||
{
|
||||
AddKekRecipient(keyAlgorithm, key, new KekIdentifier(keyIdentifier, null, null));
|
||||
}
|
||||
|
||||
/**
|
||||
* add a KEK recipient.
|
||||
* @param key the secret key to use for wrapping
|
||||
* @param keyIdentifier the byte string that identifies the key
|
||||
*/
|
||||
public void AddKekRecipient(
|
||||
string keyAlgorithm, // TODO Remove need for this parameter
|
||||
KeyParameter key,
|
||||
KekIdentifier kekIdentifier)
|
||||
{
|
||||
KekRecipientInfoGenerator kekrig = new KekRecipientInfoGenerator();
|
||||
kekrig.KekIdentifier = kekIdentifier;
|
||||
kekrig.KeyEncryptionKeyOID = keyAlgorithm;
|
||||
kekrig.KeyEncryptionKey = key;
|
||||
|
||||
recipientInfoGenerators.Add(kekrig);
|
||||
}
|
||||
|
||||
public void AddPasswordRecipient(
|
||||
CmsPbeKey pbeKey,
|
||||
string kekAlgorithmOid)
|
||||
{
|
||||
Pbkdf2Params p = new Pbkdf2Params(pbeKey.Salt, pbeKey.IterationCount);
|
||||
|
||||
PasswordRecipientInfoGenerator prig = new PasswordRecipientInfoGenerator();
|
||||
prig.KeyDerivationAlgorithm = new AlgorithmIdentifier(PkcsObjectIdentifiers.IdPbkdf2, p);
|
||||
prig.KeyEncryptionKeyOID = kekAlgorithmOid;
|
||||
prig.KeyEncryptionKey = pbeKey.GetEncoded(kekAlgorithmOid);
|
||||
|
||||
recipientInfoGenerators.Add(prig);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a key agreement based recipient.
|
||||
*
|
||||
* @param agreementAlgorithm key agreement algorithm to use.
|
||||
* @param senderPrivateKey private key to initialise sender side of agreement with.
|
||||
* @param senderPublicKey sender public key to include with message.
|
||||
* @param recipientCert recipient's public key certificate.
|
||||
* @param cekWrapAlgorithm OID for key wrapping algorithm to use.
|
||||
* @exception SecurityUtilityException if the algorithm requested cannot be found
|
||||
* @exception InvalidKeyException if the keys are inappropriate for the algorithm specified
|
||||
*/
|
||||
public void AddKeyAgreementRecipient(
|
||||
string agreementAlgorithm,
|
||||
AsymmetricKeyParameter senderPrivateKey,
|
||||
AsymmetricKeyParameter senderPublicKey,
|
||||
X509Certificate recipientCert,
|
||||
string cekWrapAlgorithm)
|
||||
{
|
||||
var recipientCerts = new List<X509Certificate>(1);
|
||||
recipientCerts.Add(recipientCert);
|
||||
|
||||
AddKeyAgreementRecipients(agreementAlgorithm, senderPrivateKey, senderPublicKey,
|
||||
recipientCerts, cekWrapAlgorithm);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add multiple key agreement based recipients (sharing a single KeyAgreeRecipientInfo structure).
|
||||
*
|
||||
* @param agreementAlgorithm key agreement algorithm to use.
|
||||
* @param senderPrivateKey private key to initialise sender side of agreement with.
|
||||
* @param senderPublicKey sender public key to include with message.
|
||||
* @param recipientCerts recipients' public key certificates.
|
||||
* @param cekWrapAlgorithm OID for key wrapping algorithm to use.
|
||||
* @exception SecurityUtilityException if the algorithm requested cannot be found
|
||||
* @exception InvalidKeyException if the keys are inappropriate for the algorithm specified
|
||||
*/
|
||||
public void AddKeyAgreementRecipients(
|
||||
string agreementAlgorithm,
|
||||
AsymmetricKeyParameter senderPrivateKey,
|
||||
AsymmetricKeyParameter senderPublicKey,
|
||||
IEnumerable<X509Certificate> recipientCerts,
|
||||
string cekWrapAlgorithm)
|
||||
{
|
||||
if (!senderPrivateKey.IsPrivate)
|
||||
throw new ArgumentException("Expected private key", "senderPrivateKey");
|
||||
if (senderPublicKey.IsPrivate)
|
||||
throw new ArgumentException("Expected public key", "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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a generator to produce the recipient info required.
|
||||
/// </summary>
|
||||
/// <param name="recipientInfoGenerator">a generator of a recipient info object.</param>
|
||||
public void AddRecipientInfoGenerator(RecipientInfoGenerator recipientInfoGenerator)
|
||||
{
|
||||
recipientInfoGenerators.Add(recipientInfoGenerator);
|
||||
}
|
||||
|
||||
|
||||
protected internal virtual AlgorithmIdentifier GetAlgorithmIdentifier(
|
||||
string encryptionOid,
|
||||
KeyParameter encKey,
|
||||
Asn1Encodable asn1Params,
|
||||
out ICipherParameters cipherParameters)
|
||||
{
|
||||
Asn1Object asn1Object;
|
||||
if (asn1Params != null)
|
||||
{
|
||||
asn1Object = asn1Params.ToAsn1Object();
|
||||
cipherParameters = ParameterUtilities.GetCipherParameters(
|
||||
encryptionOid, encKey, asn1Object);
|
||||
}
|
||||
else
|
||||
{
|
||||
asn1Object = DerNull.Instance;
|
||||
cipherParameters = encKey;
|
||||
}
|
||||
|
||||
return new AlgorithmIdentifier(
|
||||
new DerObjectIdentifier(encryptionOid),
|
||||
asn1Object);
|
||||
}
|
||||
|
||||
protected internal virtual Asn1Encodable GenerateAsn1Parameters(
|
||||
string encryptionOid,
|
||||
byte[] encKeyBytes)
|
||||
{
|
||||
Asn1Encodable asn1Params = null;
|
||||
|
||||
try
|
||||
{
|
||||
if (encryptionOid.Equals(RC2Cbc))
|
||||
{
|
||||
byte[] iv = new byte[8];
|
||||
m_random.NextBytes(iv);
|
||||
|
||||
// TODO Is this detailed repeat of Java version really necessary?
|
||||
int effKeyBits = encKeyBytes.Length * 8;
|
||||
int parameterVersion;
|
||||
|
||||
if (effKeyBits < 256)
|
||||
{
|
||||
parameterVersion = rc2Table[effKeyBits];
|
||||
}
|
||||
else
|
||||
{
|
||||
parameterVersion = effKeyBits;
|
||||
}
|
||||
|
||||
asn1Params = new RC2CbcParameter(parameterVersion, iv);
|
||||
}
|
||||
else
|
||||
{
|
||||
asn1Params = ParameterUtilities.GenerateParameters(encryptionOid, m_random);
|
||||
}
|
||||
}
|
||||
catch (SecurityUtilityException)
|
||||
{
|
||||
// No problem... no parameters generated
|
||||
}
|
||||
|
||||
return asn1Params;
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7479720d2a2d32e4688e44695282bcbe
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,311 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
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.IO;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Cms
|
||||
{
|
||||
class CmsEnvelopedHelper
|
||||
{
|
||||
internal static readonly CmsEnvelopedHelper Instance = new CmsEnvelopedHelper();
|
||||
|
||||
private static readonly IDictionary<string, int> KeySizes = new Dictionary<string, int>();
|
||||
private static readonly IDictionary<string, string> BaseCipherNames = new Dictionary<string, string>();
|
||||
|
||||
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(nameof(oid));
|
||||
|
||||
if (!BaseCipherNames.TryGetValue(oid, out var alg))
|
||||
throw new ArgumentException("no name for " + oid, nameof(oid));
|
||||
|
||||
return alg + "RFC3211Wrap";
|
||||
}
|
||||
|
||||
internal int GetKeySize(string oid)
|
||||
{
|
||||
if (oid == null)
|
||||
throw new ArgumentNullException(nameof(oid));
|
||||
|
||||
if (!KeySizes.TryGetValue(oid, out var keySize))
|
||||
throw new ArgumentException("no keysize for " + oid, "oid");
|
||||
|
||||
return keySize;
|
||||
}
|
||||
|
||||
internal static RecipientInformationStore BuildRecipientInformationStore(
|
||||
Asn1Set recipientInfos, CmsSecureReadable secureReadable)
|
||||
{
|
||||
var infos = new List<RecipientInformation>();
|
||||
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<RecipientInformation> infos, RecipientInfo info,
|
||||
CmsSecureReadable secureReadable)
|
||||
{
|
||||
Asn1Encodable recipInfo = info.Info;
|
||||
if (recipInfo is KeyTransRecipientInfo keyTransRecipientInfo)
|
||||
{
|
||||
infos.Add(new KeyTransRecipientInformation(keyTransRecipientInfo, secureReadable));
|
||||
}
|
||||
else if (recipInfo is KekRecipientInfo kekRecipientInfo)
|
||||
{
|
||||
infos.Add(new KekRecipientInformation(kekRecipientInfo, secureReadable));
|
||||
}
|
||||
else if (recipInfo is KeyAgreeRecipientInfo keyAgreeRecipientInfo)
|
||||
{
|
||||
KeyAgreeRecipientInformation.ReadRecipientInfo(infos, keyAgreeRecipientInfo, secureReadable);
|
||||
}
|
||||
else if (recipInfo is PasswordRecipientInfo passwordRecipientInfo)
|
||||
{
|
||||
infos.Add(new PasswordRecipientInformation(passwordRecipientInfo, 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
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8aff90e61ecf2b749995884c8d10148a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,34 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Cms
|
||||
{
|
||||
[Serializable]
|
||||
public class CmsException
|
||||
: Exception
|
||||
{
|
||||
public CmsException()
|
||||
: base()
|
||||
{
|
||||
}
|
||||
|
||||
public CmsException(string message)
|
||||
: base(message)
|
||||
{
|
||||
}
|
||||
|
||||
public CmsException(string message, Exception innerException)
|
||||
: base(message, innerException)
|
||||
{
|
||||
}
|
||||
|
||||
protected CmsException(SerializationInfo info, StreamingContext context)
|
||||
: base(info, context)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4f90877e942bf2e4d98c1908021bf6d4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,84 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Pkcs;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.X509;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities;
|
||||
|
||||
//import javax.crypto.interfaces.PBEKey;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Cms
|
||||
{
|
||||
public abstract class CmsPbeKey
|
||||
// TODO Create an equivalent interface somewhere?
|
||||
// : PBEKey
|
||||
: ICipherParameters
|
||||
{
|
||||
internal readonly char[] password;
|
||||
internal readonly byte[] salt;
|
||||
internal readonly int iterationCount;
|
||||
|
||||
public CmsPbeKey(
|
||||
char[] password,
|
||||
byte[] salt,
|
||||
int iterationCount)
|
||||
{
|
||||
this.password = (char[])password.Clone();
|
||||
this.salt = Arrays.Clone(salt);
|
||||
this.iterationCount = iterationCount;
|
||||
}
|
||||
|
||||
public CmsPbeKey(
|
||||
char[] password,
|
||||
AlgorithmIdentifier keyDerivationAlgorithm)
|
||||
{
|
||||
if (!keyDerivationAlgorithm.Algorithm.Equals(PkcsObjectIdentifiers.IdPbkdf2))
|
||||
throw new ArgumentException("Unsupported key derivation algorithm: "
|
||||
+ keyDerivationAlgorithm.Algorithm);
|
||||
|
||||
Pbkdf2Params kdfParams = Pbkdf2Params.GetInstance(
|
||||
keyDerivationAlgorithm.Parameters.ToAsn1Object());
|
||||
|
||||
this.password = (char[])password.Clone();
|
||||
this.salt = kdfParams.GetSalt();
|
||||
this.iterationCount = kdfParams.IterationCount.IntValue;
|
||||
}
|
||||
|
||||
~CmsPbeKey()
|
||||
{
|
||||
Array.Clear(this.password, 0, this.password.Length);
|
||||
}
|
||||
|
||||
public byte[] Salt
|
||||
{
|
||||
get { return Arrays.Clone(salt); }
|
||||
}
|
||||
|
||||
public int IterationCount
|
||||
{
|
||||
get { return iterationCount; }
|
||||
}
|
||||
|
||||
public string Algorithm
|
||||
{
|
||||
get { return "PKCS5S2"; }
|
||||
}
|
||||
|
||||
public string Format
|
||||
{
|
||||
get { return "RAW"; }
|
||||
}
|
||||
|
||||
public byte[] GetEncoded()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
internal abstract KeyParameter GetEncoded(string algorithmOid);
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2d60637ca80b5e34f9547fc0de7e2600
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,20 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Cms
|
||||
{
|
||||
public interface CmsProcessable
|
||||
{
|
||||
/// <summary>
|
||||
/// Generic routine to copy out the data we want processed.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This routine may be called multiple times.
|
||||
/// </remarks>
|
||||
void Write(Stream outStream);
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dc71b700fdd90dd48a259bb7a12d52b8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,49 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Cms;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Cms
|
||||
{
|
||||
/**
|
||||
* a holding class for a byte array of data to be processed.
|
||||
*/
|
||||
public class CmsProcessableByteArray
|
||||
: CmsProcessable, CmsReadable
|
||||
{
|
||||
private readonly DerObjectIdentifier type;
|
||||
private readonly byte[] bytes;
|
||||
|
||||
public CmsProcessableByteArray(byte[] bytes)
|
||||
{
|
||||
type = CmsObjectIdentifiers.Data;
|
||||
this.bytes = bytes;
|
||||
}
|
||||
|
||||
public CmsProcessableByteArray(DerObjectIdentifier type, byte[] bytes)
|
||||
{
|
||||
this.bytes = bytes;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public DerObjectIdentifier Type
|
||||
{
|
||||
get { return type; }
|
||||
}
|
||||
|
||||
public virtual Stream GetInputStream()
|
||||
{
|
||||
return new MemoryStream(bytes, false);
|
||||
}
|
||||
|
||||
public virtual void Write(Stream zOut)
|
||||
{
|
||||
zOut.Write(bytes, 0, bytes.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d84ec454eb730c64480bf4b1467ebf9d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,47 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System.IO;
|
||||
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.IO;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Cms
|
||||
{
|
||||
/**
|
||||
* a holding class for a file of data to be processed.
|
||||
*/
|
||||
public class CmsProcessableFile
|
||||
: CmsProcessable, CmsReadable
|
||||
{
|
||||
private const int DefaultBufSize = 32 * 1024;
|
||||
|
||||
private readonly FileInfo _file;
|
||||
private readonly int _bufSize;
|
||||
|
||||
public CmsProcessableFile(FileInfo file)
|
||||
: this(file, DefaultBufSize)
|
||||
{
|
||||
}
|
||||
|
||||
public CmsProcessableFile(FileInfo file, int bufSize)
|
||||
{
|
||||
_file = file;
|
||||
_bufSize = bufSize;
|
||||
}
|
||||
|
||||
public virtual Stream GetInputStream()
|
||||
{
|
||||
return new FileStream(_file.FullName, FileMode.Open, FileAccess.Read, FileShare.Read, _bufSize);
|
||||
}
|
||||
|
||||
public virtual void Write(Stream zOut)
|
||||
{
|
||||
using (var inStr = _file.OpenRead())
|
||||
{
|
||||
Streams.PipeAll(inStr, zOut, _bufSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ee6794dc9ed9a21498c15a4d0ade7433
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,51 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.IO;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Cms
|
||||
{
|
||||
public class CmsProcessableInputStream
|
||||
: CmsProcessable, CmsReadable
|
||||
{
|
||||
private readonly Stream input;
|
||||
|
||||
private bool used = false;
|
||||
|
||||
public CmsProcessableInputStream(Stream input)
|
||||
{
|
||||
this.input = input;
|
||||
}
|
||||
|
||||
public virtual Stream GetInputStream()
|
||||
{
|
||||
CheckSingleUsage();
|
||||
|
||||
return input;
|
||||
}
|
||||
|
||||
public virtual void Write(Stream output)
|
||||
{
|
||||
CheckSingleUsage();
|
||||
|
||||
Streams.PipeAll(input, output);
|
||||
input.Dispose();
|
||||
}
|
||||
|
||||
protected virtual void CheckSingleUsage()
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
if (used)
|
||||
throw new InvalidOperationException("CmsProcessableInputStream can only be used once");
|
||||
|
||||
used = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: aa606174dc043f747972f4383debbfc4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,14 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Cms
|
||||
{
|
||||
public interface CmsReadable
|
||||
{
|
||||
Stream GetInputStream();
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0789b9aa682aeb342978fa21c8d81f43
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,18 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.X509;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Cms
|
||||
{
|
||||
internal interface CmsSecureReadable
|
||||
{
|
||||
AlgorithmIdentifier Algorithm { get; }
|
||||
object CryptoObject { get; }
|
||||
CmsReadable GetReadable(KeyParameter key);
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cacf6c4fdf0cc0a4e9a92dfebfbe7424
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,415 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Cms;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Collections;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.X509;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Cms
|
||||
{
|
||||
/**
|
||||
* general class for handling a pkcs7-signature message.
|
||||
*
|
||||
* A simple example of usage - note, in the example below the validity of
|
||||
* the certificate isn't verified, just the fact that one of the certs
|
||||
* matches the given signer...
|
||||
*
|
||||
* <pre>
|
||||
* IX509Store certs = s.GetCertificates();
|
||||
* SignerInformationStore signers = s.GetSignerInfos();
|
||||
*
|
||||
* foreach (SignerInformation signer in signers.GetSigners())
|
||||
* {
|
||||
* ArrayList certList = new ArrayList(certs.GetMatches(signer.SignerID));
|
||||
* X509Certificate cert = (X509Certificate) certList[0];
|
||||
*
|
||||
* if (signer.Verify(cert.GetPublicKey()))
|
||||
* {
|
||||
* verified++;
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
public class CmsSignedData
|
||||
{
|
||||
private static readonly CmsSignedHelper Helper = CmsSignedHelper.Instance;
|
||||
|
||||
private readonly CmsProcessable signedContent;
|
||||
private SignedData signedData;
|
||||
private ContentInfo contentInfo;
|
||||
private SignerInformationStore signerInfoStore;
|
||||
private IDictionary<string, byte[]> m_hashes;
|
||||
|
||||
private CmsSignedData(CmsSignedData c)
|
||||
{
|
||||
this.signedData = c.signedData;
|
||||
this.contentInfo = c.contentInfo;
|
||||
this.signedContent = c.signedContent;
|
||||
this.signerInfoStore = c.signerInfoStore;
|
||||
}
|
||||
|
||||
public CmsSignedData(byte[] sigBlock)
|
||||
: this(CmsUtilities.ReadContentInfo(new MemoryStream(sigBlock, false)))
|
||||
{
|
||||
}
|
||||
|
||||
public CmsSignedData(CmsProcessable signedContent, byte[] sigBlock)
|
||||
: this(signedContent, CmsUtilities.ReadContentInfo(new MemoryStream(sigBlock, false)))
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Content with detached signature, digests precomputed
|
||||
*
|
||||
* @param hashes a map of precomputed digests for content indexed by name of hash.
|
||||
* @param sigBlock the signature object.
|
||||
*/
|
||||
public CmsSignedData(IDictionary<string, byte[]> hashes, byte[] sigBlock)
|
||||
: this(hashes, CmsUtilities.ReadContentInfo(sigBlock))
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* base constructor - content with detached signature.
|
||||
*
|
||||
* @param signedContent the content that was signed.
|
||||
* @param sigData the signature object.
|
||||
*/
|
||||
public CmsSignedData(CmsProcessable signedContent, Stream sigData)
|
||||
: this(signedContent, CmsUtilities.ReadContentInfo(sigData))
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* base constructor - with encapsulated content
|
||||
*/
|
||||
public CmsSignedData(Stream sigData)
|
||||
: this(CmsUtilities.ReadContentInfo(sigData))
|
||||
{
|
||||
}
|
||||
|
||||
public CmsSignedData(CmsProcessable signedContent, ContentInfo sigData)
|
||||
{
|
||||
this.signedContent = signedContent;
|
||||
this.contentInfo = sigData;
|
||||
this.signedData = SignedData.GetInstance(contentInfo.Content);
|
||||
}
|
||||
|
||||
public CmsSignedData(IDictionary<string, byte[]> hashes, ContentInfo sigData)
|
||||
{
|
||||
this.m_hashes = hashes;
|
||||
this.contentInfo = sigData;
|
||||
this.signedData = SignedData.GetInstance(contentInfo.Content);
|
||||
}
|
||||
|
||||
public CmsSignedData(ContentInfo sigData)
|
||||
{
|
||||
this.contentInfo = sigData;
|
||||
this.signedData = SignedData.GetInstance(contentInfo.Content);
|
||||
|
||||
//
|
||||
// this can happen if the signed message is sent simply to send a
|
||||
// certificate chain.
|
||||
//
|
||||
if (signedData.EncapContentInfo.Content != null)
|
||||
{
|
||||
this.signedContent = new CmsProcessableByteArray(
|
||||
((Asn1OctetString)(signedData.EncapContentInfo.Content)).GetOctets());
|
||||
}
|
||||
// else
|
||||
// {
|
||||
// this.signedContent = null;
|
||||
// }
|
||||
}
|
||||
|
||||
/// <summary>Return the version number for this object.</summary>
|
||||
public int Version
|
||||
{
|
||||
get { return signedData.Version.IntValueExact; }
|
||||
}
|
||||
|
||||
/**
|
||||
* return the collection of signers that are associated with the
|
||||
* signatures for the message.
|
||||
*/
|
||||
public SignerInformationStore GetSignerInfos()
|
||||
{
|
||||
if (signerInfoStore == null)
|
||||
{
|
||||
var signerInfos = new List<SignerInformation>();
|
||||
Asn1Set s = signedData.SignerInfos;
|
||||
|
||||
foreach (object obj in s)
|
||||
{
|
||||
SignerInfo info = SignerInfo.GetInstance(obj);
|
||||
DerObjectIdentifier contentType = signedData.EncapContentInfo.ContentType;
|
||||
|
||||
if (m_hashes == null)
|
||||
{
|
||||
signerInfos.Add(new SignerInformation(info, contentType, signedContent, null));
|
||||
}
|
||||
else if (m_hashes.TryGetValue(info.DigestAlgorithm.Algorithm.Id, out var hash))
|
||||
{
|
||||
signerInfos.Add(new SignerInformation(info, contentType, null, new BaseDigestCalculator(hash)));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
signerInfoStore = new SignerInformationStore(signerInfos);
|
||||
}
|
||||
|
||||
return signerInfoStore;
|
||||
}
|
||||
|
||||
/**
|
||||
* return a X509Store containing the attribute certificates, if any, contained
|
||||
* in this message.
|
||||
*
|
||||
* @param type type of store to create
|
||||
* @return a store of attribute certificates
|
||||
* @exception NoSuchStoreException if the store type isn't available.
|
||||
* @exception CmsException if a general exception prevents creation of the X509Store
|
||||
*/
|
||||
public IStore<X509V2AttributeCertificate> GetAttributeCertificates()
|
||||
{
|
||||
return Helper.GetAttributeCertificates(signedData.Certificates);
|
||||
}
|
||||
|
||||
/**
|
||||
* return a X509Store containing the public key certificates, if any, contained in this message.
|
||||
*
|
||||
* @return a store of public key certificates
|
||||
* @exception NoSuchStoreException if the store type isn't available.
|
||||
* @exception CmsException if a general exception prevents creation of the X509Store
|
||||
*/
|
||||
public IStore<X509Certificate> GetCertificates()
|
||||
{
|
||||
return Helper.GetCertificates(signedData.Certificates);
|
||||
}
|
||||
|
||||
/**
|
||||
* return a X509Store containing CRLs, if any, contained in this message.
|
||||
*
|
||||
* @return a store of CRLs
|
||||
* @exception NoSuchStoreException if the store type isn't available.
|
||||
* @exception CmsException if a general exception prevents creation of the X509Store
|
||||
*/
|
||||
public IStore<X509Crl> GetCrls()
|
||||
{
|
||||
return Helper.GetCrls(signedData.CRLs);
|
||||
}
|
||||
|
||||
public IStore<Asn1Encodable> GetOtherRevInfos(DerObjectIdentifier otherRevInfoFormat)
|
||||
{
|
||||
return Helper.GetOtherRevInfos(signedData.CRLs, otherRevInfoFormat);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the <c>DerObjectIdentifier</c> associated with the encapsulated
|
||||
/// content info structure carried in the signed data.
|
||||
/// </summary>
|
||||
public DerObjectIdentifier SignedContentType
|
||||
{
|
||||
get { return signedData.EncapContentInfo.ContentType; }
|
||||
}
|
||||
|
||||
public CmsProcessable SignedContent
|
||||
{
|
||||
get { return signedContent; }
|
||||
}
|
||||
|
||||
/**
|
||||
* return the ContentInfo
|
||||
*/
|
||||
public ContentInfo ContentInfo
|
||||
{
|
||||
get { return contentInfo; }
|
||||
}
|
||||
|
||||
/**
|
||||
* return the ASN.1 encoded representation of this object.
|
||||
*/
|
||||
public byte[] GetEncoded()
|
||||
{
|
||||
return contentInfo.GetEncoded();
|
||||
}
|
||||
|
||||
/**
|
||||
* return the ASN.1 encoded representation of this object using the specified encoding.
|
||||
*
|
||||
* @param encoding the ASN.1 encoding format to use ("BER" or "DER").
|
||||
*/
|
||||
public byte[] GetEncoded(string encoding)
|
||||
{
|
||||
return contentInfo.GetEncoded(encoding);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the signerinformation store associated with this
|
||||
* CmsSignedData object with the new one passed in. You would
|
||||
* probably only want to do this if you wanted to change the unsigned
|
||||
* attributes associated with a signer, or perhaps delete one.
|
||||
*
|
||||
* @param signedData the signed data object to be used as a base.
|
||||
* @param signerInformationStore the new signer information store to use.
|
||||
* @return a new signed data object.
|
||||
*/
|
||||
public static CmsSignedData ReplaceSigners(
|
||||
CmsSignedData signedData,
|
||||
SignerInformationStore signerInformationStore)
|
||||
{
|
||||
//
|
||||
// copy
|
||||
//
|
||||
CmsSignedData cms = new CmsSignedData(signedData);
|
||||
|
||||
//
|
||||
// replace the store
|
||||
//
|
||||
cms.signerInfoStore = signerInformationStore;
|
||||
|
||||
//
|
||||
// replace the signers in the SignedData object
|
||||
//
|
||||
Asn1EncodableVector digestAlgs = new Asn1EncodableVector();
|
||||
Asn1EncodableVector vec = new Asn1EncodableVector();
|
||||
|
||||
foreach (SignerInformation signer in signerInformationStore.GetSigners())
|
||||
{
|
||||
digestAlgs.Add(Helper.FixAlgID(signer.DigestAlgorithmID));
|
||||
vec.Add(signer.ToSignerInfo());
|
||||
}
|
||||
|
||||
Asn1Set digests = new DerSet(digestAlgs);
|
||||
Asn1Set signers = new DerSet(vec);
|
||||
Asn1Sequence sD = (Asn1Sequence)signedData.signedData.ToAsn1Object();
|
||||
|
||||
//
|
||||
// signers are the last item in the sequence.
|
||||
//
|
||||
vec = new Asn1EncodableVector(
|
||||
sD[0], // version
|
||||
digests);
|
||||
|
||||
for (int i = 2; i != sD.Count - 1; i++)
|
||||
{
|
||||
vec.Add(sD[i]);
|
||||
}
|
||||
|
||||
vec.Add(signers);
|
||||
|
||||
cms.signedData = SignedData.GetInstance(new BerSequence(vec));
|
||||
|
||||
//
|
||||
// replace the contentInfo with the new one
|
||||
//
|
||||
cms.contentInfo = new ContentInfo(cms.contentInfo.ContentType, cms.signedData);
|
||||
|
||||
return cms;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the certificate and CRL information associated with this
|
||||
* CmsSignedData object with the new one passed in.
|
||||
*
|
||||
* @param signedData the signed data object to be used as a base.
|
||||
* @param x509Certs the new certificates to be used.
|
||||
* @param x509Crls the new CRLs to be used.
|
||||
* @return a new signed data object.
|
||||
* @exception CmsException if there is an error processing the stores
|
||||
*/
|
||||
public static CmsSignedData ReplaceCertificatesAndCrls(CmsSignedData signedData,
|
||||
IStore<X509Certificate> x509Certs, IStore<X509Crl> x509Crls)
|
||||
{
|
||||
return ReplaceCertificatesAndRevocations(signedData, x509Certs, x509Crls, null, null);
|
||||
}
|
||||
|
||||
public static CmsSignedData ReplaceCertificatesAndCrls(CmsSignedData signedData,
|
||||
IStore<X509Certificate> x509Certs, IStore<X509Crl> x509Crls,
|
||||
IStore<X509V2AttributeCertificate> x509AttrCerts)
|
||||
{
|
||||
return ReplaceCertificatesAndRevocations(signedData, x509Certs, x509Crls, x509AttrCerts, null);
|
||||
}
|
||||
|
||||
public static CmsSignedData ReplaceCertificatesAndRevocations(CmsSignedData signedData,
|
||||
IStore<X509Certificate> x509Certs, IStore<X509Crl> x509Crls,
|
||||
IStore<X509V2AttributeCertificate> x509AttrCerts, IStore<OtherRevocationInfoFormat> otherRevocationInfos)
|
||||
{
|
||||
//
|
||||
// copy
|
||||
//
|
||||
CmsSignedData cms = new CmsSignedData(signedData);
|
||||
|
||||
//
|
||||
// replace the certs and crls in the SignedData object
|
||||
//
|
||||
Asn1Set certSet = null;
|
||||
Asn1Set revocationSet = null;
|
||||
|
||||
if (x509Certs != null || x509AttrCerts != null)
|
||||
{
|
||||
var certificates = new List<Asn1Encodable>();
|
||||
if (x509Certs != null)
|
||||
{
|
||||
certificates.AddRange(CmsUtilities.GetCertificatesFromStore(x509Certs));
|
||||
}
|
||||
if (x509AttrCerts != null)
|
||||
{
|
||||
certificates.AddRange(CmsUtilities.GetAttributeCertificatesFromStore(x509AttrCerts));
|
||||
}
|
||||
|
||||
Asn1Set berSet = CmsUtilities.CreateBerSetFromList(certificates);
|
||||
if (berSet.Count > 0)
|
||||
{
|
||||
certSet = berSet;
|
||||
}
|
||||
}
|
||||
|
||||
if (x509Crls != null || otherRevocationInfos != null)
|
||||
{
|
||||
var revocations = new List<Asn1Encodable>();
|
||||
if (x509Crls != null)
|
||||
{
|
||||
revocations.AddRange(CmsUtilities.GetCrlsFromStore(x509Crls));
|
||||
}
|
||||
if (otherRevocationInfos != null)
|
||||
{
|
||||
revocations.AddRange(CmsUtilities.GetOtherRevocationInfosFromStore(otherRevocationInfos));
|
||||
}
|
||||
|
||||
Asn1Set berSet = CmsUtilities.CreateBerSetFromList(revocations);
|
||||
if (berSet.Count > 0)
|
||||
{
|
||||
revocationSet = berSet;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// replace the CMS structure.
|
||||
//
|
||||
SignedData old = signedData.signedData;
|
||||
cms.signedData = new SignedData(
|
||||
old.DigestAlgorithms,
|
||||
old.EncapContentInfo,
|
||||
certSet,
|
||||
revocationSet,
|
||||
old.SignerInfos);
|
||||
|
||||
//
|
||||
// replace the contentInfo with the new one
|
||||
//
|
||||
cms.contentInfo = new ContentInfo(cms.contentInfo.ContentType, cms.signedData);
|
||||
|
||||
return cms;
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c43e6a93201d37548a399de669fafeea
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,581 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
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.Security;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Security.Certificates;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.X509;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Operators;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Cms
|
||||
{
|
||||
/**
|
||||
* general class for generating a pkcs7-signature message.
|
||||
* <p>
|
||||
* A simple example of usage.
|
||||
*
|
||||
* <pre>
|
||||
* IX509Store certs...
|
||||
* IX509Store crls...
|
||||
* CmsSignedDataGenerator gen = new CmsSignedDataGenerator();
|
||||
*
|
||||
* gen.AddSigner(privKey, cert, CmsSignedGenerator.DigestSha1);
|
||||
* gen.AddCertificates(certs);
|
||||
* gen.AddCrls(crls);
|
||||
*
|
||||
* CmsSignedData data = gen.Generate(content);
|
||||
* </pre>
|
||||
* </p>
|
||||
*/
|
||||
public class CmsSignedDataGenerator
|
||||
: CmsSignedGenerator
|
||||
{
|
||||
private static readonly CmsSignedHelper Helper = CmsSignedHelper.Instance;
|
||||
|
||||
private readonly IList<SignerInf> signerInfs = new List<SignerInf>();
|
||||
|
||||
private class SignerInf
|
||||
{
|
||||
private readonly CmsSignedGenerator outer;
|
||||
|
||||
private readonly ISignatureFactory sigCalc;
|
||||
private readonly SignerIdentifier signerIdentifier;
|
||||
private readonly string digestOID;
|
||||
private readonly string encOID;
|
||||
private readonly CmsAttributeTableGenerator sAttr;
|
||||
private readonly CmsAttributeTableGenerator unsAttr;
|
||||
private readonly Asn1.Cms.AttributeTable baseSignedTable;
|
||||
|
||||
internal SignerInf(
|
||||
CmsSignedGenerator outer,
|
||||
AsymmetricKeyParameter key,
|
||||
SecureRandom random,
|
||||
SignerIdentifier signerIdentifier,
|
||||
string digestOID,
|
||||
string encOID,
|
||||
CmsAttributeTableGenerator sAttr,
|
||||
CmsAttributeTableGenerator unsAttr,
|
||||
Asn1.Cms.AttributeTable baseSignedTable)
|
||||
{
|
||||
string digestName = Helper.GetDigestAlgName(digestOID);
|
||||
|
||||
string signatureName = digestName + "with" + Helper.GetEncryptionAlgName(encOID);
|
||||
|
||||
this.outer = outer;
|
||||
this.sigCalc = new Asn1SignatureFactory(signatureName, key, random);
|
||||
this.signerIdentifier = signerIdentifier;
|
||||
this.digestOID = digestOID;
|
||||
this.encOID = encOID;
|
||||
this.sAttr = sAttr;
|
||||
this.unsAttr = unsAttr;
|
||||
this.baseSignedTable = baseSignedTable;
|
||||
}
|
||||
|
||||
internal SignerInf(
|
||||
CmsSignedGenerator outer,
|
||||
ISignatureFactory sigCalc,
|
||||
SignerIdentifier signerIdentifier,
|
||||
CmsAttributeTableGenerator sAttr,
|
||||
CmsAttributeTableGenerator unsAttr,
|
||||
Asn1.Cms.AttributeTable baseSignedTable)
|
||||
{
|
||||
this.outer = outer;
|
||||
this.sigCalc = sigCalc;
|
||||
this.signerIdentifier = signerIdentifier;
|
||||
this.digestOID = new DefaultDigestAlgorithmIdentifierFinder().Find(
|
||||
(AlgorithmIdentifier)sigCalc.AlgorithmDetails).Algorithm.Id;
|
||||
this.encOID = ((AlgorithmIdentifier)sigCalc.AlgorithmDetails).Algorithm.Id;
|
||||
this.sAttr = sAttr;
|
||||
this.unsAttr = unsAttr;
|
||||
this.baseSignedTable = baseSignedTable;
|
||||
}
|
||||
|
||||
internal AlgorithmIdentifier DigestAlgorithmID
|
||||
{
|
||||
get { return new AlgorithmIdentifier(new DerObjectIdentifier(digestOID), DerNull.Instance); }
|
||||
}
|
||||
|
||||
internal CmsAttributeTableGenerator SignedAttributes
|
||||
{
|
||||
get { return sAttr; }
|
||||
}
|
||||
|
||||
internal CmsAttributeTableGenerator UnsignedAttributes
|
||||
{
|
||||
get { return unsAttr; }
|
||||
}
|
||||
|
||||
internal SignerInfo ToSignerInfo(DerObjectIdentifier contentType, CmsProcessable content)
|
||||
{
|
||||
AlgorithmIdentifier digAlgId = DigestAlgorithmID;
|
||||
string digestName = Helper.GetDigestAlgName(digestOID);
|
||||
|
||||
string signatureName = digestName + "with" + Helper.GetEncryptionAlgName(encOID);
|
||||
|
||||
if (!outer.m_digests.TryGetValue(digestOID, out var hash))
|
||||
{
|
||||
IDigest dig = Helper.GetDigestInstance(digestName);
|
||||
if (content != null)
|
||||
{
|
||||
content.Write(new DigestSink(dig));
|
||||
}
|
||||
hash = DigestUtilities.DoFinal(dig);
|
||||
outer.m_digests.Add(digestOID, (byte[])hash.Clone());
|
||||
}
|
||||
|
||||
Asn1Set signedAttr = null;
|
||||
|
||||
IStreamCalculator<IBlockResult> calculator = sigCalc.CreateCalculator();
|
||||
using (Stream sigStr = calculator.Stream)
|
||||
{
|
||||
if (sAttr != null)
|
||||
{
|
||||
var parameters = outer.GetBaseParameters(contentType, digAlgId, hash);
|
||||
|
||||
//Asn1.Cms.AttributeTable signed = sAttr.GetAttributes(Collections.unmodifiableMap(parameters));
|
||||
Asn1.Cms.AttributeTable signed = sAttr.GetAttributes(parameters);
|
||||
|
||||
if (contentType == null) //counter signature
|
||||
{
|
||||
if (signed != null && signed[CmsAttributes.ContentType] != null)
|
||||
{
|
||||
signed = signed.Remove(CmsAttributes.ContentType);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO Validate proposed signed attributes
|
||||
|
||||
signedAttr = outer.GetAttributeSet(signed);
|
||||
|
||||
// sig must be composed from the DER encoding.
|
||||
signedAttr.EncodeTo(sigStr, Asn1Encodable.Der);
|
||||
}
|
||||
else if (content != null)
|
||||
{
|
||||
// TODO Use raw signature of the hash value instead
|
||||
content.Write(sigStr);
|
||||
}
|
||||
}
|
||||
|
||||
byte[] sigBytes = calculator.GetResult().Collect();
|
||||
|
||||
Asn1Set unsignedAttr = null;
|
||||
if (unsAttr != null)
|
||||
{
|
||||
var baseParameters = outer.GetBaseParameters(contentType, digAlgId, hash);
|
||||
baseParameters[CmsAttributeTableParameter.Signature] = sigBytes.Clone();
|
||||
|
||||
// Asn1.Cms.AttributeTable unsigned = unsAttr.GetAttributes(Collections.unmodifiableMap(baseParameters));
|
||||
Asn1.Cms.AttributeTable unsigned = unsAttr.GetAttributes(baseParameters);
|
||||
|
||||
// TODO Validate proposed unsigned attributes
|
||||
|
||||
unsignedAttr = outer.GetAttributeSet(unsigned);
|
||||
}
|
||||
|
||||
// TODO[RSAPSS] Need the ability to specify non-default parameters
|
||||
Asn1Encodable sigX509Parameters = SignerUtilities.GetDefaultX509Parameters(signatureName);
|
||||
AlgorithmIdentifier encAlgId = Helper.GetEncAlgorithmIdentifier(
|
||||
new DerObjectIdentifier(encOID), sigX509Parameters);
|
||||
|
||||
return new SignerInfo(signerIdentifier, digAlgId,
|
||||
signedAttr, encAlgId, new DerOctetString(sigBytes), unsignedAttr);
|
||||
}
|
||||
}
|
||||
|
||||
public CmsSignedDataGenerator()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>Constructor allowing specific source of randomness</summary>
|
||||
/// <param name="random">Instance of <c>SecureRandom</c> to use.</param>
|
||||
public CmsSignedDataGenerator(SecureRandom random)
|
||||
: base(random)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* add a signer - no attributes other than the default ones will be
|
||||
* provided here.
|
||||
*
|
||||
* @param key signing key to use
|
||||
* @param cert certificate containing corresponding public key
|
||||
* @param digestOID digest algorithm OID
|
||||
*/
|
||||
public void AddSigner(
|
||||
AsymmetricKeyParameter privateKey,
|
||||
X509Certificate cert,
|
||||
string digestOID)
|
||||
{
|
||||
AddSigner(privateKey, cert, Helper.GetEncOid(privateKey, digestOID), digestOID);
|
||||
}
|
||||
|
||||
/**
|
||||
* add a signer, specifying the digest encryption algorithm to use - no attributes other than the default ones will be
|
||||
* provided here.
|
||||
*
|
||||
* @param key signing key to use
|
||||
* @param cert certificate containing corresponding public key
|
||||
* @param encryptionOID digest encryption algorithm OID
|
||||
* @param digestOID digest algorithm OID
|
||||
*/
|
||||
public void AddSigner(
|
||||
AsymmetricKeyParameter privateKey,
|
||||
X509Certificate cert,
|
||||
string encryptionOID,
|
||||
string digestOID)
|
||||
{
|
||||
doAddSigner(privateKey, GetSignerIdentifier(cert), encryptionOID, digestOID,
|
||||
new DefaultSignedAttributeTableGenerator(), null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* add a signer - no attributes other than the default ones will be
|
||||
* provided here.
|
||||
*/
|
||||
public void AddSigner(
|
||||
AsymmetricKeyParameter privateKey,
|
||||
byte[] subjectKeyID,
|
||||
string digestOID)
|
||||
{
|
||||
AddSigner(privateKey, subjectKeyID, Helper.GetEncOid(privateKey, digestOID), digestOID);
|
||||
}
|
||||
|
||||
/**
|
||||
* add a signer, specifying the digest encryption algorithm to use - no attributes other than the default ones will be
|
||||
* provided here.
|
||||
*/
|
||||
public void AddSigner(
|
||||
AsymmetricKeyParameter privateKey,
|
||||
byte[] subjectKeyID,
|
||||
string encryptionOID,
|
||||
string digestOID)
|
||||
{
|
||||
doAddSigner(privateKey, GetSignerIdentifier(subjectKeyID), encryptionOID, digestOID,
|
||||
new DefaultSignedAttributeTableGenerator(), null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* add a signer with extra signed/unsigned attributes.
|
||||
*
|
||||
* @param key signing key to use
|
||||
* @param cert certificate containing corresponding public key
|
||||
* @param digestOID digest algorithm OID
|
||||
* @param signedAttr table of attributes to be included in signature
|
||||
* @param unsignedAttr table of attributes to be included as unsigned
|
||||
*/
|
||||
public void AddSigner(
|
||||
AsymmetricKeyParameter privateKey,
|
||||
X509Certificate cert,
|
||||
string digestOID,
|
||||
Asn1.Cms.AttributeTable signedAttr,
|
||||
Asn1.Cms.AttributeTable unsignedAttr)
|
||||
{
|
||||
AddSigner(privateKey, cert, Helper.GetEncOid(privateKey, digestOID), digestOID,
|
||||
signedAttr, unsignedAttr);
|
||||
}
|
||||
|
||||
/**
|
||||
* add a signer, specifying the digest encryption algorithm, with extra signed/unsigned attributes.
|
||||
*
|
||||
* @param key signing key to use
|
||||
* @param cert certificate containing corresponding public key
|
||||
* @param encryptionOID digest encryption algorithm OID
|
||||
* @param digestOID digest algorithm OID
|
||||
* @param signedAttr table of attributes to be included in signature
|
||||
* @param unsignedAttr table of attributes to be included as unsigned
|
||||
*/
|
||||
public void AddSigner(
|
||||
AsymmetricKeyParameter privateKey,
|
||||
X509Certificate cert,
|
||||
string encryptionOID,
|
||||
string digestOID,
|
||||
Asn1.Cms.AttributeTable signedAttr,
|
||||
Asn1.Cms.AttributeTable unsignedAttr)
|
||||
{
|
||||
doAddSigner(privateKey, GetSignerIdentifier(cert), encryptionOID, digestOID,
|
||||
new DefaultSignedAttributeTableGenerator(signedAttr),
|
||||
new SimpleAttributeTableGenerator(unsignedAttr),
|
||||
signedAttr);
|
||||
}
|
||||
|
||||
/**
|
||||
* add a signer with extra signed/unsigned attributes.
|
||||
*
|
||||
* @param key signing key to use
|
||||
* @param subjectKeyID subjectKeyID of corresponding public key
|
||||
* @param digestOID digest algorithm OID
|
||||
* @param signedAttr table of attributes to be included in signature
|
||||
* @param unsignedAttr table of attributes to be included as unsigned
|
||||
*/
|
||||
public void AddSigner(
|
||||
AsymmetricKeyParameter privateKey,
|
||||
byte[] subjectKeyID,
|
||||
string digestOID,
|
||||
Asn1.Cms.AttributeTable signedAttr,
|
||||
Asn1.Cms.AttributeTable unsignedAttr)
|
||||
{
|
||||
AddSigner(privateKey, subjectKeyID, Helper.GetEncOid(privateKey, digestOID), digestOID,
|
||||
signedAttr, unsignedAttr);
|
||||
}
|
||||
|
||||
/**
|
||||
* add a signer, specifying the digest encryption algorithm, with extra signed/unsigned attributes.
|
||||
*
|
||||
* @param key signing key to use
|
||||
* @param subjectKeyID subjectKeyID of corresponding public key
|
||||
* @param encryptionOID digest encryption algorithm OID
|
||||
* @param digestOID digest algorithm OID
|
||||
* @param signedAttr table of attributes to be included in signature
|
||||
* @param unsignedAttr table of attributes to be included as unsigned
|
||||
*/
|
||||
public void AddSigner(
|
||||
AsymmetricKeyParameter privateKey,
|
||||
byte[] subjectKeyID,
|
||||
string encryptionOID,
|
||||
string digestOID,
|
||||
Asn1.Cms.AttributeTable signedAttr,
|
||||
Asn1.Cms.AttributeTable unsignedAttr)
|
||||
{
|
||||
doAddSigner(privateKey, GetSignerIdentifier(subjectKeyID), encryptionOID, digestOID,
|
||||
new DefaultSignedAttributeTableGenerator(signedAttr),
|
||||
new SimpleAttributeTableGenerator(unsignedAttr),
|
||||
signedAttr);
|
||||
}
|
||||
|
||||
/**
|
||||
* add a signer with extra signed/unsigned attributes based on generators.
|
||||
*/
|
||||
public void AddSigner(
|
||||
AsymmetricKeyParameter privateKey,
|
||||
X509Certificate cert,
|
||||
string digestOID,
|
||||
CmsAttributeTableGenerator signedAttrGen,
|
||||
CmsAttributeTableGenerator unsignedAttrGen)
|
||||
{
|
||||
AddSigner(privateKey, cert, Helper.GetEncOid(privateKey, digestOID), digestOID,
|
||||
signedAttrGen, unsignedAttrGen);
|
||||
}
|
||||
|
||||
/**
|
||||
* add a signer, specifying the digest encryption algorithm, with extra signed/unsigned attributes based on generators.
|
||||
*/
|
||||
public void AddSigner(
|
||||
AsymmetricKeyParameter privateKey,
|
||||
X509Certificate cert,
|
||||
string encryptionOID,
|
||||
string digestOID,
|
||||
CmsAttributeTableGenerator signedAttrGen,
|
||||
CmsAttributeTableGenerator unsignedAttrGen)
|
||||
{
|
||||
doAddSigner(privateKey, GetSignerIdentifier(cert), encryptionOID, digestOID, signedAttrGen,
|
||||
unsignedAttrGen, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* add a signer with extra signed/unsigned attributes based on generators.
|
||||
*/
|
||||
public void AddSigner(
|
||||
AsymmetricKeyParameter privateKey,
|
||||
byte[] subjectKeyID,
|
||||
string digestOID,
|
||||
CmsAttributeTableGenerator signedAttrGen,
|
||||
CmsAttributeTableGenerator unsignedAttrGen)
|
||||
{
|
||||
AddSigner(privateKey, subjectKeyID, Helper.GetEncOid(privateKey, digestOID), digestOID,
|
||||
signedAttrGen, unsignedAttrGen);
|
||||
}
|
||||
|
||||
/**
|
||||
* add a signer, including digest encryption algorithm, with extra signed/unsigned attributes based on generators.
|
||||
*/
|
||||
public void AddSigner(
|
||||
AsymmetricKeyParameter privateKey,
|
||||
byte[] subjectKeyID,
|
||||
string encryptionOID,
|
||||
string digestOID,
|
||||
CmsAttributeTableGenerator signedAttrGen,
|
||||
CmsAttributeTableGenerator unsignedAttrGen)
|
||||
{
|
||||
doAddSigner(privateKey, GetSignerIdentifier(subjectKeyID), encryptionOID, digestOID,
|
||||
signedAttrGen, unsignedAttrGen, null);
|
||||
}
|
||||
|
||||
public void AddSignerInfoGenerator(SignerInfoGenerator signerInfoGenerator)
|
||||
{
|
||||
signerInfs.Add(new SignerInf(this, signerInfoGenerator.contentSigner, signerInfoGenerator.sigId,
|
||||
signerInfoGenerator.signedGen, signerInfoGenerator.unsignedGen, null));
|
||||
}
|
||||
|
||||
private void doAddSigner(
|
||||
AsymmetricKeyParameter privateKey,
|
||||
SignerIdentifier signerIdentifier,
|
||||
string encryptionOID,
|
||||
string digestOID,
|
||||
CmsAttributeTableGenerator signedAttrGen,
|
||||
CmsAttributeTableGenerator unsignedAttrGen,
|
||||
Asn1.Cms.AttributeTable baseSignedTable)
|
||||
{
|
||||
signerInfs.Add(new SignerInf(this, privateKey, m_random, signerIdentifier, digestOID, encryptionOID,
|
||||
signedAttrGen, unsignedAttrGen, baseSignedTable));
|
||||
}
|
||||
|
||||
/**
|
||||
* generate a signed object that for a CMS Signed Data object
|
||||
*/
|
||||
public CmsSignedData Generate(
|
||||
CmsProcessable content)
|
||||
{
|
||||
return Generate(content, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* generate a signed object that for a CMS Signed Data
|
||||
* object - if encapsulate is true a copy
|
||||
* of the message will be included in the signature. The content type
|
||||
* is set according to the OID represented by the string signedContentType.
|
||||
*/
|
||||
public CmsSignedData Generate(
|
||||
string signedContentType,
|
||||
// FIXME Avoid accessing more than once to support CmsProcessableInputStream
|
||||
CmsProcessable content,
|
||||
bool encapsulate)
|
||||
{
|
||||
Asn1EncodableVector digestAlgs = new Asn1EncodableVector();
|
||||
Asn1EncodableVector signerInfos = new Asn1EncodableVector();
|
||||
|
||||
m_digests.Clear(); // clear the current preserved digest state
|
||||
|
||||
//
|
||||
// add the precalculated SignerInfo objects.
|
||||
//
|
||||
foreach (SignerInformation signer in _signers)
|
||||
{
|
||||
digestAlgs.Add(Helper.FixAlgID(signer.DigestAlgorithmID));
|
||||
|
||||
// TODO Verify the content type and calculated digest match the precalculated SignerInfo
|
||||
signerInfos.Add(signer.ToSignerInfo());
|
||||
}
|
||||
|
||||
//
|
||||
// add the SignerInfo objects
|
||||
//
|
||||
bool isCounterSignature = (signedContentType == null);
|
||||
|
||||
DerObjectIdentifier contentTypeOid = isCounterSignature
|
||||
? null
|
||||
: new DerObjectIdentifier(signedContentType);
|
||||
|
||||
foreach (SignerInf signer in signerInfs)
|
||||
{
|
||||
try
|
||||
{
|
||||
digestAlgs.Add(signer.DigestAlgorithmID);
|
||||
signerInfos.Add(signer.ToSignerInfo(contentTypeOid, content));
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new CmsException("encoding error.", e);
|
||||
}
|
||||
catch (InvalidKeyException e)
|
||||
{
|
||||
throw new CmsException("key inappropriate for signature.", e);
|
||||
}
|
||||
catch (SignatureException e)
|
||||
{
|
||||
throw new CmsException("error creating signature.", e);
|
||||
}
|
||||
catch (CertificateEncodingException e)
|
||||
{
|
||||
throw new CmsException("error creating sid.", e);
|
||||
}
|
||||
}
|
||||
|
||||
Asn1Set certificates = null;
|
||||
|
||||
if (_certs.Count != 0)
|
||||
{
|
||||
certificates = UseDerForCerts
|
||||
? CmsUtilities.CreateDerSetFromList(_certs)
|
||||
: CmsUtilities.CreateBerSetFromList(_certs);
|
||||
}
|
||||
|
||||
Asn1Set certrevlist = null;
|
||||
|
||||
if (_crls.Count != 0)
|
||||
{
|
||||
certrevlist = UseDerForCrls
|
||||
? CmsUtilities.CreateDerSetFromList(_crls)
|
||||
: CmsUtilities.CreateBerSetFromList(_crls);
|
||||
}
|
||||
|
||||
Asn1OctetString octs = null;
|
||||
if (encapsulate)
|
||||
{
|
||||
MemoryStream bOut = new MemoryStream();
|
||||
if (content != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
content.Write(bOut);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new CmsException("encapsulation error.", e);
|
||||
}
|
||||
}
|
||||
octs = new BerOctetString(bOut.ToArray());
|
||||
}
|
||||
|
||||
ContentInfo encInfo = new ContentInfo(contentTypeOid, octs);
|
||||
|
||||
SignedData sd = new SignedData(
|
||||
new DerSet(digestAlgs),
|
||||
encInfo,
|
||||
certificates,
|
||||
certrevlist,
|
||||
new DerSet(signerInfos));
|
||||
|
||||
ContentInfo contentInfo = new ContentInfo(CmsObjectIdentifiers.SignedData, sd);
|
||||
|
||||
return new CmsSignedData(content, contentInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* generate a signed object that for a CMS Signed Data
|
||||
* object - if encapsulate is true a copy
|
||||
* of the message will be included in the signature with the
|
||||
* default content type "data".
|
||||
*/
|
||||
public CmsSignedData Generate(
|
||||
CmsProcessable content,
|
||||
bool encapsulate)
|
||||
{
|
||||
return this.Generate(Data, content, encapsulate);
|
||||
}
|
||||
|
||||
/**
|
||||
* generate a set of one or more SignerInformation objects representing counter signatures on
|
||||
* the passed in SignerInformation object.
|
||||
*
|
||||
* @param signer the signer to be countersigned
|
||||
* @param sigProvider the provider to be used for counter signing.
|
||||
* @return a store containing the signers.
|
||||
*/
|
||||
public SignerInformationStore GenerateCounterSigners(
|
||||
SignerInformation signer)
|
||||
{
|
||||
return this.Generate(null, new CmsProcessableByteArray(signer.GetSignature()), false).GetSignerInfos();
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 027a8f21814c46547a37d4ef8abcb9f2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,435 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
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.Security;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Collections;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.IO;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.X509;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Cms
|
||||
{
|
||||
/**
|
||||
* Parsing class for an CMS Signed Data object from an input stream.
|
||||
* <p>
|
||||
* Note: that because we are in a streaming mode only one signer can be tried and it is important
|
||||
* that the methods on the parser are called in the appropriate order.
|
||||
* </p>
|
||||
* <p>
|
||||
* A simple example of usage for an encapsulated signature.
|
||||
* </p>
|
||||
* <p>
|
||||
* Two notes: first, in the example below the validity of
|
||||
* the certificate isn't verified, just the fact that one of the certs
|
||||
* matches the given signer, and, second, because we are in a streaming
|
||||
* mode the order of the operations is important.
|
||||
* </p>
|
||||
* <pre>
|
||||
* CmsSignedDataParser sp = new CmsSignedDataParser(encapSigData);
|
||||
*
|
||||
* sp.GetSignedContent().Drain();
|
||||
*
|
||||
* IX509Store certs = sp.GetCertificates();
|
||||
* SignerInformationStore signers = sp.GetSignerInfos();
|
||||
*
|
||||
* foreach (SignerInformation signer in signers.GetSigners())
|
||||
* {
|
||||
* ArrayList certList = new ArrayList(certs.GetMatches(signer.SignerID));
|
||||
* X509Certificate cert = (X509Certificate) certList[0];
|
||||
*
|
||||
* Console.WriteLine("verify returns: " + signer.Verify(cert));
|
||||
* }
|
||||
* </pre>
|
||||
* Note also: this class does not introduce buffering - if you are processing large files you should create
|
||||
* the parser with:
|
||||
* <pre>
|
||||
* CmsSignedDataParser ep = new CmsSignedDataParser(new BufferedInputStream(encapSigData, bufSize));
|
||||
* </pre>
|
||||
* where bufSize is a suitably large buffer size.
|
||||
*/
|
||||
public class CmsSignedDataParser
|
||||
: CmsContentInfoParser
|
||||
{
|
||||
private static readonly CmsSignedHelper Helper = CmsSignedHelper.Instance;
|
||||
|
||||
private SignedDataParser _signedData;
|
||||
private DerObjectIdentifier _signedContentType;
|
||||
private CmsTypedStream _signedContent;
|
||||
private IDictionary<string, IDigest> m_digests;
|
||||
private HashSet<string> _digestOids;
|
||||
|
||||
private SignerInformationStore _signerInfoStore;
|
||||
private Asn1Set _certSet, _crlSet;
|
||||
private bool _isCertCrlParsed;
|
||||
|
||||
public CmsSignedDataParser(
|
||||
byte[] sigBlock)
|
||||
: this(new MemoryStream(sigBlock, false))
|
||||
{
|
||||
}
|
||||
|
||||
public CmsSignedDataParser(
|
||||
CmsTypedStream signedContent,
|
||||
byte[] sigBlock)
|
||||
: this(signedContent, new MemoryStream(sigBlock, false))
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* base constructor - with encapsulated content
|
||||
*/
|
||||
public CmsSignedDataParser(
|
||||
Stream sigData)
|
||||
: this(null, sigData)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* base constructor
|
||||
*
|
||||
* @param signedContent the content that was signed.
|
||||
* @param sigData the signature object.
|
||||
*/
|
||||
public CmsSignedDataParser(
|
||||
CmsTypedStream signedContent,
|
||||
Stream sigData)
|
||||
: base(sigData)
|
||||
{
|
||||
try
|
||||
{
|
||||
this._signedContent = signedContent;
|
||||
this._signedData = SignedDataParser.GetInstance(this.contentInfo.GetContent(Asn1Tags.Sequence));
|
||||
this.m_digests = new Dictionary<string, IDigest>(StringComparer.OrdinalIgnoreCase);
|
||||
this._digestOids = new HashSet<string>();
|
||||
|
||||
Asn1SetParser digAlgs = _signedData.GetDigestAlgorithms();
|
||||
IAsn1Convertible o;
|
||||
|
||||
while ((o = digAlgs.ReadObject()) != null)
|
||||
{
|
||||
AlgorithmIdentifier id = AlgorithmIdentifier.GetInstance(o.ToAsn1Object());
|
||||
|
||||
try
|
||||
{
|
||||
string digestOid = id.Algorithm.Id;
|
||||
string digestName = Helper.GetDigestAlgName(digestOid);
|
||||
|
||||
if (!this.m_digests.ContainsKey(digestName))
|
||||
{
|
||||
this.m_digests[digestName] = Helper.GetDigestInstance(digestName);
|
||||
this._digestOids.Add(digestOid);
|
||||
}
|
||||
}
|
||||
catch (SecurityUtilityException)
|
||||
{
|
||||
// TODO Should do something other than ignore it
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// If the message is simply a certificate chain message GetContent() may return null.
|
||||
//
|
||||
ContentInfoParser cont = _signedData.GetEncapContentInfo();
|
||||
Asn1OctetStringParser octs = (Asn1OctetStringParser)
|
||||
cont.GetContent(Asn1Tags.OctetString);
|
||||
|
||||
if (octs != null)
|
||||
{
|
||||
CmsTypedStream ctStr = new CmsTypedStream(
|
||||
cont.ContentType.Id, octs.GetOctetStream());
|
||||
|
||||
if (_signedContent == null)
|
||||
{
|
||||
this._signedContent = ctStr;
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// content passed in, need to read past empty encapsulated content info object if present
|
||||
//
|
||||
ctStr.Drain();
|
||||
}
|
||||
}
|
||||
|
||||
_signedContentType = _signedContent == null
|
||||
? cont.ContentType
|
||||
: new DerObjectIdentifier(_signedContent.ContentType);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new CmsException("io exception: " + e.Message, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the version number for the SignedData object
|
||||
*
|
||||
* @return the version number
|
||||
*/
|
||||
public int Version
|
||||
{
|
||||
get { return _signedData.Version.IntValueExact; }
|
||||
}
|
||||
|
||||
public ISet<string> DigestOids
|
||||
{
|
||||
get { return new HashSet<string>(_digestOids); }
|
||||
}
|
||||
|
||||
/**
|
||||
* return the collection of signers that are associated with the
|
||||
* signatures for the message.
|
||||
* @throws CmsException
|
||||
*/
|
||||
public SignerInformationStore GetSignerInfos()
|
||||
{
|
||||
if (_signerInfoStore == null)
|
||||
{
|
||||
PopulateCertCrlSets();
|
||||
|
||||
var signerInfos = new List<SignerInformation>();
|
||||
var hashes = new Dictionary<string, byte[]>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
foreach (var digest in m_digests)
|
||||
{
|
||||
hashes[digest.Key] = DigestUtilities.DoFinal(digest.Value);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Asn1SetParser s = _signedData.GetSignerInfos();
|
||||
IAsn1Convertible o;
|
||||
|
||||
while ((o = s.ReadObject()) != null)
|
||||
{
|
||||
SignerInfo info = SignerInfo.GetInstance(o.ToAsn1Object());
|
||||
string digestName = Helper.GetDigestAlgName(info.DigestAlgorithm.Algorithm.Id);
|
||||
|
||||
byte[] hash = hashes[digestName];
|
||||
|
||||
signerInfos.Add(new SignerInformation(info, _signedContentType, null, new BaseDigestCalculator(hash)));
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new CmsException("io exception: " + e.Message, e);
|
||||
}
|
||||
|
||||
_signerInfoStore = new SignerInformationStore(signerInfos);
|
||||
}
|
||||
|
||||
return _signerInfoStore;
|
||||
}
|
||||
|
||||
/**
|
||||
* return a X509Store containing the attribute certificates, if any, contained
|
||||
* in this message.
|
||||
*
|
||||
* @param type type of store to create
|
||||
* @return a store of attribute certificates
|
||||
* @exception org.bouncycastle.x509.NoSuchStoreException if the store type isn't available.
|
||||
* @exception CmsException if a general exception prevents creation of the X509Store
|
||||
*/
|
||||
public IStore<X509V2AttributeCertificate> GetAttributeCertificates()
|
||||
{
|
||||
PopulateCertCrlSets();
|
||||
|
||||
return Helper.GetAttributeCertificates(_certSet);
|
||||
}
|
||||
|
||||
/**
|
||||
* return a X509Store containing the public key certificates, if any, contained
|
||||
* in this message.
|
||||
*
|
||||
* @param type type of store to create
|
||||
* @return a store of public key certificates
|
||||
* @exception NoSuchStoreException if the store type isn't available.
|
||||
* @exception CmsException if a general exception prevents creation of the X509Store
|
||||
*/
|
||||
public IStore<X509Certificate> GetCertificates()
|
||||
{
|
||||
PopulateCertCrlSets();
|
||||
|
||||
return Helper.GetCertificates(_certSet);
|
||||
}
|
||||
|
||||
/**
|
||||
* return a X509Store containing CRLs, if any, contained
|
||||
* in this message.
|
||||
*
|
||||
* @param type type of store to create
|
||||
* @return a store of CRLs
|
||||
* @exception NoSuchStoreException if the store type isn't available.
|
||||
* @exception CmsException if a general exception prevents creation of the X509Store
|
||||
*/
|
||||
public IStore<X509Crl> GetCrls()
|
||||
{
|
||||
PopulateCertCrlSets();
|
||||
|
||||
return Helper.GetCrls(_crlSet);
|
||||
}
|
||||
|
||||
public IStore<Asn1Encodable> GetOtherRevInfos(DerObjectIdentifier otherRevInfoFormat)
|
||||
{
|
||||
PopulateCertCrlSets();
|
||||
|
||||
return Helper.GetOtherRevInfos(_crlSet, otherRevInfoFormat);
|
||||
}
|
||||
|
||||
private void PopulateCertCrlSets()
|
||||
{
|
||||
if (_isCertCrlParsed)
|
||||
return;
|
||||
|
||||
_isCertCrlParsed = true;
|
||||
|
||||
try
|
||||
{
|
||||
// care! Streaming - Must process the GetCertificates() result before calling GetCrls()
|
||||
_certSet = GetAsn1Set(_signedData.GetCertificates());
|
||||
_crlSet = GetAsn1Set(_signedData.GetCrls());
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new CmsException("problem parsing cert/crl sets", e);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the <c>DerObjectIdentifier</c> associated with the encapsulated
|
||||
/// content info structure carried in the signed data.
|
||||
/// </summary>
|
||||
public DerObjectIdentifier SignedContentType
|
||||
{
|
||||
get { return _signedContentType; }
|
||||
}
|
||||
|
||||
public CmsTypedStream GetSignedContent()
|
||||
{
|
||||
if (_signedContent == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
Stream digStream = _signedContent.ContentStream;
|
||||
|
||||
foreach (var digest in m_digests.Values)
|
||||
{
|
||||
digStream = new DigestStream(digStream, digest, null);
|
||||
}
|
||||
|
||||
return new CmsTypedStream(_signedContent.ContentType, digStream);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the signerinformation store associated with the passed
|
||||
* in message contained in the stream original with the new one passed in.
|
||||
* You would probably only want to do this if you wanted to change the unsigned
|
||||
* attributes associated with a signer, or perhaps delete one.
|
||||
* <p>
|
||||
* The output stream is returned unclosed.
|
||||
* </p>
|
||||
* @param original the signed data stream to be used as a base.
|
||||
* @param signerInformationStore the new signer information store to use.
|
||||
* @param out the stream to Write the new signed data object to.
|
||||
* @return out.
|
||||
*/
|
||||
public static Stream ReplaceSigners(
|
||||
Stream original,
|
||||
SignerInformationStore signerInformationStore,
|
||||
Stream outStr)
|
||||
{
|
||||
// NB: SecureRandom would be ignored since using existing signatures only
|
||||
CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator();
|
||||
CmsSignedDataParser parser = new CmsSignedDataParser(original);
|
||||
|
||||
// gen.AddDigests(parser.DigestOids);
|
||||
gen.AddSigners(signerInformationStore);
|
||||
|
||||
CmsTypedStream signedContent = parser.GetSignedContent();
|
||||
bool encapsulate = (signedContent != null);
|
||||
Stream contentOut = gen.Open(outStr, parser.SignedContentType.Id, encapsulate);
|
||||
if (encapsulate)
|
||||
{
|
||||
Streams.PipeAll(signedContent.ContentStream, contentOut);
|
||||
}
|
||||
|
||||
gen.AddAttributeCertificates(parser.GetAttributeCertificates());
|
||||
gen.AddCertificates(parser.GetCertificates());
|
||||
gen.AddCrls(parser.GetCrls());
|
||||
|
||||
// gen.AddSigners(parser.GetSignerInfos());
|
||||
|
||||
contentOut.Dispose();
|
||||
|
||||
return outStr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the certificate and CRL information associated with this
|
||||
* CMSSignedData object with the new one passed in.
|
||||
* <p>
|
||||
* The output stream is returned unclosed.
|
||||
* </p>
|
||||
* @param original the signed data stream to be used as a base.
|
||||
* @param certsAndCrls the new certificates and CRLs to be used.
|
||||
* @param out the stream to Write the new signed data object to.
|
||||
* @return out.
|
||||
* @exception CmsException if there is an error processing the CertStore
|
||||
*/
|
||||
public static Stream ReplaceCertificatesAndCrls(Stream original, IStore<X509Certificate> x509Certs,
|
||||
IStore<X509Crl> x509Crls, IStore<X509V2AttributeCertificate> x509AttrCerts, Stream outStr)
|
||||
{
|
||||
// NB: SecureRandom would be ignored since using existing signatures only
|
||||
CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator();
|
||||
CmsSignedDataParser parser = new CmsSignedDataParser(original);
|
||||
|
||||
gen.AddDigests(parser.DigestOids);
|
||||
|
||||
CmsTypedStream signedContent = parser.GetSignedContent();
|
||||
bool encapsulate = (signedContent != null);
|
||||
Stream contentOut = gen.Open(outStr, parser.SignedContentType.Id, encapsulate);
|
||||
if (encapsulate)
|
||||
{
|
||||
Streams.PipeAll(signedContent.ContentStream, contentOut);
|
||||
}
|
||||
|
||||
if (x509AttrCerts != null)
|
||||
{
|
||||
gen.AddAttributeCertificates(x509AttrCerts);
|
||||
}
|
||||
if (x509Certs != null)
|
||||
{
|
||||
gen.AddCertificates(x509Certs);
|
||||
}
|
||||
if (x509Crls != null)
|
||||
{
|
||||
gen.AddCrls(x509Crls);
|
||||
}
|
||||
|
||||
gen.AddSigners(parser.GetSignerInfos());
|
||||
|
||||
contentOut.Dispose();
|
||||
|
||||
return outStr;
|
||||
}
|
||||
|
||||
private static Asn1Set GetAsn1Set(
|
||||
Asn1SetParser asn1SetParser)
|
||||
{
|
||||
return asn1SetParser == null
|
||||
? null
|
||||
: Asn1Set.GetInstance(asn1SetParser.ToAsn1Object());
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0ccc5588045627642964cdaa1b1fddcf
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,913 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
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;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.X509;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Cms
|
||||
{
|
||||
/**
|
||||
* General class for generating a pkcs7-signature message stream.
|
||||
* <p>
|
||||
* A simple example of usage.
|
||||
* </p>
|
||||
* <pre>
|
||||
* IX509Store certs...
|
||||
* CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator();
|
||||
*
|
||||
* gen.AddSigner(privateKey, cert, CmsSignedDataStreamGenerator.DIGEST_SHA1);
|
||||
*
|
||||
* gen.AddCertificates(certs);
|
||||
*
|
||||
* Stream sigOut = gen.Open(bOut);
|
||||
*
|
||||
* sigOut.Write(Encoding.UTF8.GetBytes("Hello World!"));
|
||||
*
|
||||
* sigOut.Close();
|
||||
* </pre>
|
||||
*/
|
||||
public class CmsSignedDataStreamGenerator
|
||||
: CmsSignedGenerator
|
||||
{
|
||||
private static readonly CmsSignedHelper Helper = CmsSignedHelper.Instance;
|
||||
|
||||
private readonly IList<DigestAndSignerInfoGeneratorHolder> _signerInfs =
|
||||
new List<DigestAndSignerInfoGeneratorHolder>();
|
||||
private readonly HashSet<string> _messageDigestOids = new HashSet<string>();
|
||||
private readonly IDictionary<string, IDigest> m_messageDigests =
|
||||
new Dictionary<string, IDigest>(StringComparer.OrdinalIgnoreCase);
|
||||
private readonly IDictionary<string, byte[]> m_messageHashes =
|
||||
new Dictionary<string, byte[]>(StringComparer.OrdinalIgnoreCase);
|
||||
private bool _messageDigestsLocked;
|
||||
private int _bufferSize;
|
||||
|
||||
private class DigestAndSignerInfoGeneratorHolder
|
||||
{
|
||||
internal readonly ISignerInfoGenerator signerInf;
|
||||
internal readonly string digestOID;
|
||||
|
||||
internal DigestAndSignerInfoGeneratorHolder(ISignerInfoGenerator signerInf, string digestOID)
|
||||
{
|
||||
this.signerInf = signerInf;
|
||||
this.digestOID = digestOID;
|
||||
}
|
||||
|
||||
internal AlgorithmIdentifier DigestAlgorithm
|
||||
{
|
||||
get { return new AlgorithmIdentifier(new DerObjectIdentifier(this.digestOID), DerNull.Instance); }
|
||||
}
|
||||
}
|
||||
|
||||
private class SignerInfoGeneratorImpl : ISignerInfoGenerator
|
||||
{
|
||||
private readonly CmsSignedDataStreamGenerator outer;
|
||||
|
||||
private readonly SignerIdentifier _signerIdentifier;
|
||||
private readonly string _digestOID;
|
||||
private readonly string _encOID;
|
||||
private readonly CmsAttributeTableGenerator _sAttr;
|
||||
private readonly CmsAttributeTableGenerator _unsAttr;
|
||||
private readonly string _encName;
|
||||
private readonly ISigner _sig;
|
||||
|
||||
internal SignerInfoGeneratorImpl(
|
||||
CmsSignedDataStreamGenerator outer,
|
||||
AsymmetricKeyParameter key,
|
||||
SignerIdentifier signerIdentifier,
|
||||
string digestOID,
|
||||
string encOID,
|
||||
CmsAttributeTableGenerator sAttr,
|
||||
CmsAttributeTableGenerator unsAttr)
|
||||
{
|
||||
this.outer = outer;
|
||||
|
||||
_signerIdentifier = signerIdentifier;
|
||||
_digestOID = digestOID;
|
||||
_encOID = encOID;
|
||||
_sAttr = sAttr;
|
||||
_unsAttr = unsAttr;
|
||||
_encName = Helper.GetEncryptionAlgName(_encOID);
|
||||
|
||||
string digestName = Helper.GetDigestAlgName(_digestOID);
|
||||
string signatureName = digestName + "with" + _encName;
|
||||
|
||||
if (_sAttr != null)
|
||||
{
|
||||
_sig = Helper.GetSignatureInstance(signatureName);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Note: Need to use raw signatures here since we have already calculated the digest
|
||||
if (_encName.Equals("RSA"))
|
||||
{
|
||||
_sig = Helper.GetSignatureInstance("RSA");
|
||||
}
|
||||
else if (_encName.Equals("DSA"))
|
||||
{
|
||||
_sig = Helper.GetSignatureInstance("NONEwithDSA");
|
||||
}
|
||||
// TODO Add support for raw PSS
|
||||
// else if (_encName.equals("RSAandMGF1"))
|
||||
// {
|
||||
// _sig = CMSSignedHelper.INSTANCE.getSignatureInstance("NONEWITHRSAPSS", _sigProvider);
|
||||
// try
|
||||
// {
|
||||
// // Init the params this way to avoid having a 'raw' version of each PSS algorithm
|
||||
// Signature sig2 = CMSSignedHelper.INSTANCE.getSignatureInstance(signatureName, _sigProvider);
|
||||
// PSSParameterSpec spec = (PSSParameterSpec)sig2.getParameters().getParameterSpec(PSSParameterSpec.class);
|
||||
// _sig.setParameter(spec);
|
||||
// }
|
||||
// catch (Exception e)
|
||||
// {
|
||||
// throw new SignatureException("algorithm: " + _encName + " could not be configured.");
|
||||
// }
|
||||
// }
|
||||
else
|
||||
{
|
||||
throw new SignatureException("algorithm: " + _encName + " not supported in base signatures.");
|
||||
}
|
||||
}
|
||||
|
||||
_sig.Init(true, new ParametersWithRandom(key, outer.m_random));
|
||||
}
|
||||
|
||||
public SignerInfo Generate(DerObjectIdentifier contentType, AlgorithmIdentifier digestAlgorithm,
|
||||
byte[] calculatedDigest)
|
||||
{
|
||||
try
|
||||
{
|
||||
string digestName = Helper.GetDigestAlgName(_digestOID);
|
||||
string signatureName = digestName + "with" + _encName;
|
||||
|
||||
// AlgorithmIdentifier digAlgId = DigestAlgorithmID;
|
||||
//
|
||||
// byte[] hash = (byte[])outer._messageHashes[Helper.GetDigestAlgName(this._digestOID)];
|
||||
// outer._digests[_digestOID] = hash.Clone();
|
||||
|
||||
byte[] bytesToSign = calculatedDigest;
|
||||
|
||||
/* RFC 3852 5.4
|
||||
* The result of the message digest calculation process depends on
|
||||
* whether the signedAttrs field is present. When the field is absent,
|
||||
* the result is just the message digest of the content as described
|
||||
*
|
||||
* above. When the field is present, however, the result is the message
|
||||
* digest of the complete DER encoding of the SignedAttrs value
|
||||
* contained in the signedAttrs field.
|
||||
*/
|
||||
Asn1Set signedAttr = null;
|
||||
if (_sAttr != null)
|
||||
{
|
||||
var parameters = outer.GetBaseParameters(contentType, digestAlgorithm, calculatedDigest);
|
||||
|
||||
// Asn1.Cms.AttributeTable signed = _sAttr.GetAttributes(Collections.unmodifiableMap(parameters));
|
||||
Asn1.Cms.AttributeTable signed = _sAttr.GetAttributes(parameters);
|
||||
|
||||
if (contentType == null) //counter signature
|
||||
{
|
||||
if (signed != null && signed[CmsAttributes.ContentType] != null)
|
||||
{
|
||||
signed = signed.Remove(CmsAttributes.ContentType);
|
||||
}
|
||||
}
|
||||
|
||||
signedAttr = outer.GetAttributeSet(signed);
|
||||
|
||||
// sig must be composed from the DER encoding.
|
||||
bytesToSign = signedAttr.GetEncoded(Asn1Encodable.Der);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Note: Need to use raw signatures here since we have already calculated the digest
|
||||
if (_encName.Equals("RSA"))
|
||||
{
|
||||
DigestInfo dInfo = new DigestInfo(digestAlgorithm, calculatedDigest);
|
||||
bytesToSign = dInfo.GetEncoded(Asn1Encodable.Der);
|
||||
}
|
||||
}
|
||||
|
||||
_sig.BlockUpdate(bytesToSign, 0, bytesToSign.Length);
|
||||
byte[] sigBytes = _sig.GenerateSignature();
|
||||
|
||||
Asn1Set unsignedAttr = null;
|
||||
if (_unsAttr != null)
|
||||
{
|
||||
var parameters = outer.GetBaseParameters(contentType, digestAlgorithm, calculatedDigest);
|
||||
parameters[CmsAttributeTableParameter.Signature] = sigBytes.Clone();
|
||||
|
||||
// Asn1.Cms.AttributeTable unsigned = _unsAttr.getAttributes(Collections.unmodifiableMap(parameters));
|
||||
Asn1.Cms.AttributeTable unsigned = _unsAttr.GetAttributes(parameters);
|
||||
|
||||
unsignedAttr = outer.GetAttributeSet(unsigned);
|
||||
}
|
||||
|
||||
// TODO[RSAPSS] Need the ability to specify non-default parameters
|
||||
Asn1Encodable sigX509Parameters = SignerUtilities.GetDefaultX509Parameters(signatureName);
|
||||
AlgorithmIdentifier digestEncryptionAlgorithm = Helper.GetEncAlgorithmIdentifier(
|
||||
new DerObjectIdentifier(_encOID), sigX509Parameters);
|
||||
|
||||
return new SignerInfo(_signerIdentifier, digestAlgorithm,
|
||||
signedAttr, digestEncryptionAlgorithm, new DerOctetString(sigBytes), unsignedAttr);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new CmsStreamException("encoding error.", e);
|
||||
}
|
||||
catch (SignatureException e)
|
||||
{
|
||||
throw new CmsStreamException("error creating signature.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public CmsSignedDataStreamGenerator()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>Constructor allowing specific source of randomness</summary>
|
||||
/// <param name="random">Instance of <c>SecureRandom</c> to use.</param>
|
||||
public CmsSignedDataStreamGenerator(SecureRandom random)
|
||||
: base(random)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the underlying string size for encapsulated data
|
||||
*
|
||||
* @param bufferSize length of octet strings to buffer the data.
|
||||
*/
|
||||
public void SetBufferSize(int bufferSize)
|
||||
{
|
||||
_bufferSize = bufferSize;
|
||||
}
|
||||
|
||||
public void AddDigests(params string[] digestOids)
|
||||
{
|
||||
foreach (string digestOid in digestOids)
|
||||
{
|
||||
ConfigureDigest(digestOid);
|
||||
}
|
||||
}
|
||||
|
||||
public void AddDigests(IEnumerable<string> digestOids)
|
||||
{
|
||||
foreach (string digestOid in digestOids)
|
||||
{
|
||||
ConfigureDigest(digestOid);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* add a signer - no attributes other than the default ones will be
|
||||
* provided here.
|
||||
* @throws NoSuchAlgorithmException
|
||||
* @throws InvalidKeyException
|
||||
*/
|
||||
public void AddSigner(
|
||||
AsymmetricKeyParameter privateKey,
|
||||
X509Certificate cert,
|
||||
string digestOid)
|
||||
{
|
||||
AddSigner(privateKey, cert, digestOid,
|
||||
new DefaultSignedAttributeTableGenerator(), null);
|
||||
}
|
||||
|
||||
/**
|
||||
* add a signer, specifying the digest encryption algorithm - no attributes other than the default ones will be
|
||||
* provided here.
|
||||
* @throws NoSuchProviderException
|
||||
* @throws NoSuchAlgorithmException
|
||||
* @throws InvalidKeyException
|
||||
*/
|
||||
public void AddSigner(
|
||||
AsymmetricKeyParameter privateKey,
|
||||
X509Certificate cert,
|
||||
string encryptionOid,
|
||||
string digestOid)
|
||||
{
|
||||
AddSigner(privateKey, cert, encryptionOid, digestOid,
|
||||
new DefaultSignedAttributeTableGenerator(),
|
||||
(CmsAttributeTableGenerator)null);
|
||||
}
|
||||
|
||||
/**
|
||||
* add a signer with extra signed/unsigned attributes.
|
||||
* @throws NoSuchAlgorithmException
|
||||
* @throws InvalidKeyException
|
||||
*/
|
||||
public void AddSigner(
|
||||
AsymmetricKeyParameter privateKey,
|
||||
X509Certificate cert,
|
||||
string digestOid,
|
||||
Asn1.Cms.AttributeTable signedAttr,
|
||||
Asn1.Cms.AttributeTable unsignedAttr)
|
||||
{
|
||||
AddSigner(privateKey, cert, digestOid,
|
||||
new DefaultSignedAttributeTableGenerator(signedAttr),
|
||||
new SimpleAttributeTableGenerator(unsignedAttr));
|
||||
}
|
||||
|
||||
/**
|
||||
* add a signer with extra signed/unsigned attributes - specifying digest
|
||||
* encryption algorithm.
|
||||
* @throws NoSuchProviderException
|
||||
* @throws NoSuchAlgorithmException
|
||||
* @throws InvalidKeyException
|
||||
*/
|
||||
public void AddSigner(
|
||||
AsymmetricKeyParameter privateKey,
|
||||
X509Certificate cert,
|
||||
string encryptionOid,
|
||||
string digestOid,
|
||||
Asn1.Cms.AttributeTable signedAttr,
|
||||
Asn1.Cms.AttributeTable unsignedAttr)
|
||||
{
|
||||
AddSigner(privateKey, cert, encryptionOid, digestOid,
|
||||
new DefaultSignedAttributeTableGenerator(signedAttr),
|
||||
new SimpleAttributeTableGenerator(unsignedAttr));
|
||||
}
|
||||
|
||||
public void AddSigner(
|
||||
AsymmetricKeyParameter privateKey,
|
||||
X509Certificate cert,
|
||||
string digestOid,
|
||||
CmsAttributeTableGenerator signedAttrGenerator,
|
||||
CmsAttributeTableGenerator unsignedAttrGenerator)
|
||||
{
|
||||
AddSigner(privateKey, cert, Helper.GetEncOid(privateKey, digestOid), digestOid,
|
||||
signedAttrGenerator, unsignedAttrGenerator);
|
||||
}
|
||||
|
||||
public void AddSigner(
|
||||
AsymmetricKeyParameter privateKey,
|
||||
X509Certificate cert,
|
||||
string encryptionOid,
|
||||
string digestOid,
|
||||
CmsAttributeTableGenerator signedAttrGenerator,
|
||||
CmsAttributeTableGenerator unsignedAttrGenerator)
|
||||
{
|
||||
DoAddSigner(privateKey, GetSignerIdentifier(cert), encryptionOid, digestOid,
|
||||
signedAttrGenerator, unsignedAttrGenerator);
|
||||
}
|
||||
|
||||
/**
|
||||
* add a signer - no attributes other than the default ones will be
|
||||
* provided here.
|
||||
* @throws NoSuchAlgorithmException
|
||||
* @throws InvalidKeyException
|
||||
*/
|
||||
public void AddSigner(
|
||||
AsymmetricKeyParameter privateKey,
|
||||
byte[] subjectKeyID,
|
||||
string digestOid)
|
||||
{
|
||||
AddSigner(privateKey, subjectKeyID, digestOid, new DefaultSignedAttributeTableGenerator(),
|
||||
(CmsAttributeTableGenerator)null);
|
||||
}
|
||||
|
||||
/**
|
||||
* add a signer - no attributes other than the default ones will be
|
||||
* provided here.
|
||||
* @throws NoSuchProviderException
|
||||
* @throws NoSuchAlgorithmException
|
||||
* @throws InvalidKeyException
|
||||
*/
|
||||
public void AddSigner(
|
||||
AsymmetricKeyParameter privateKey,
|
||||
byte[] subjectKeyID,
|
||||
string encryptionOid,
|
||||
string digestOid)
|
||||
{
|
||||
AddSigner(privateKey, subjectKeyID, encryptionOid, digestOid,
|
||||
new DefaultSignedAttributeTableGenerator(),
|
||||
(CmsAttributeTableGenerator)null);
|
||||
}
|
||||
|
||||
/**
|
||||
* add a signer with extra signed/unsigned attributes.
|
||||
* @throws NoSuchAlgorithmException
|
||||
* @throws InvalidKeyException
|
||||
*/
|
||||
public void AddSigner(
|
||||
AsymmetricKeyParameter privateKey,
|
||||
byte[] subjectKeyID,
|
||||
string digestOid,
|
||||
Asn1.Cms.AttributeTable signedAttr,
|
||||
Asn1.Cms.AttributeTable unsignedAttr)
|
||||
{
|
||||
AddSigner(privateKey, subjectKeyID, digestOid,
|
||||
new DefaultSignedAttributeTableGenerator(signedAttr),
|
||||
new SimpleAttributeTableGenerator(unsignedAttr));
|
||||
}
|
||||
|
||||
public void AddSigner(
|
||||
AsymmetricKeyParameter privateKey,
|
||||
byte[] subjectKeyID,
|
||||
string digestOid,
|
||||
CmsAttributeTableGenerator signedAttrGenerator,
|
||||
CmsAttributeTableGenerator unsignedAttrGenerator)
|
||||
{
|
||||
AddSigner(privateKey, subjectKeyID, Helper.GetEncOid(privateKey, digestOid),
|
||||
digestOid, signedAttrGenerator, unsignedAttrGenerator);
|
||||
}
|
||||
|
||||
public void AddSigner(
|
||||
AsymmetricKeyParameter privateKey,
|
||||
byte[] subjectKeyID,
|
||||
string encryptionOid,
|
||||
string digestOid,
|
||||
CmsAttributeTableGenerator signedAttrGenerator,
|
||||
CmsAttributeTableGenerator unsignedAttrGenerator)
|
||||
{
|
||||
DoAddSigner(privateKey, GetSignerIdentifier(subjectKeyID), encryptionOid, digestOid,
|
||||
signedAttrGenerator, unsignedAttrGenerator);
|
||||
}
|
||||
|
||||
private void DoAddSigner(
|
||||
AsymmetricKeyParameter privateKey,
|
||||
SignerIdentifier signerIdentifier,
|
||||
string encryptionOid,
|
||||
string digestOid,
|
||||
CmsAttributeTableGenerator signedAttrGenerator,
|
||||
CmsAttributeTableGenerator unsignedAttrGenerator)
|
||||
{
|
||||
ConfigureDigest(digestOid);
|
||||
|
||||
SignerInfoGeneratorImpl signerInf = new SignerInfoGeneratorImpl(this, privateKey,
|
||||
signerIdentifier, digestOid, encryptionOid, signedAttrGenerator, unsignedAttrGenerator);
|
||||
|
||||
_signerInfs.Add(new DigestAndSignerInfoGeneratorHolder(signerInf, digestOid));
|
||||
}
|
||||
|
||||
internal override void AddSignerCallback(
|
||||
SignerInformation si)
|
||||
{
|
||||
// FIXME If there were parameters in si.DigestAlgorithmID.Parameters, they are lost
|
||||
// NB: Would need to call FixAlgID on the DigestAlgorithmID
|
||||
|
||||
// For precalculated signers, just need to register the algorithm, not configure a digest
|
||||
RegisterDigestOid(si.DigestAlgorithmID.Algorithm.Id);
|
||||
}
|
||||
|
||||
/**
|
||||
* generate a signed object that for a CMS Signed Data object
|
||||
*/
|
||||
public Stream Open(
|
||||
Stream outStream)
|
||||
{
|
||||
return Open(outStream, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* generate a signed object that for a CMS Signed Data
|
||||
* object - if encapsulate is true a copy
|
||||
* of the message will be included in the signature with the
|
||||
* default content type "data".
|
||||
*/
|
||||
public Stream Open(
|
||||
Stream outStream,
|
||||
bool encapsulate)
|
||||
{
|
||||
return Open(outStream, Data, encapsulate);
|
||||
}
|
||||
|
||||
/**
|
||||
* generate a signed object that for a CMS Signed Data
|
||||
* object using the given provider - if encapsulate is true a copy
|
||||
* of the message will be included in the signature with the
|
||||
* default content type "data". If dataOutputStream is non null the data
|
||||
* being signed will be written to the stream as it is processed.
|
||||
* @param out stream the CMS object is to be written to.
|
||||
* @param encapsulate true if data should be encapsulated.
|
||||
* @param dataOutputStream output stream to copy the data being signed to.
|
||||
*/
|
||||
public Stream Open(
|
||||
Stream outStream,
|
||||
bool encapsulate,
|
||||
Stream dataOutputStream)
|
||||
{
|
||||
return Open(outStream, Data, encapsulate, dataOutputStream);
|
||||
}
|
||||
|
||||
/**
|
||||
* generate a signed object that for a CMS Signed Data
|
||||
* object - if encapsulate is true a copy
|
||||
* of the message will be included in the signature. The content type
|
||||
* is set according to the OID represented by the string signedContentType.
|
||||
*/
|
||||
public Stream Open(
|
||||
Stream outStream,
|
||||
string signedContentType,
|
||||
bool encapsulate)
|
||||
{
|
||||
return Open(outStream, signedContentType, encapsulate, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* generate a signed object that for a CMS Signed Data
|
||||
* object using the given provider - if encapsulate is true a copy
|
||||
* of the message will be included in the signature. The content type
|
||||
* is set according to the OID represented by the string signedContentType.
|
||||
* @param out stream the CMS object is to be written to.
|
||||
* @param signedContentType OID for data to be signed.
|
||||
* @param encapsulate true if data should be encapsulated.
|
||||
* @param dataOutputStream output stream to copy the data being signed to.
|
||||
*/
|
||||
public Stream Open(
|
||||
Stream outStream,
|
||||
string signedContentType,
|
||||
bool encapsulate,
|
||||
Stream dataOutputStream)
|
||||
{
|
||||
if (outStream == null)
|
||||
throw new ArgumentNullException("outStream");
|
||||
if (!outStream.CanWrite)
|
||||
throw new ArgumentException("Expected writeable stream", "outStream");
|
||||
if (dataOutputStream != null && !dataOutputStream.CanWrite)
|
||||
throw new ArgumentException("Expected writeable stream", "dataOutputStream");
|
||||
|
||||
_messageDigestsLocked = true;
|
||||
|
||||
//
|
||||
// ContentInfo
|
||||
//
|
||||
BerSequenceGenerator sGen = new BerSequenceGenerator(outStream);
|
||||
|
||||
sGen.AddObject(CmsObjectIdentifiers.SignedData);
|
||||
|
||||
//
|
||||
// Signed Data
|
||||
//
|
||||
BerSequenceGenerator sigGen = new BerSequenceGenerator(
|
||||
sGen.GetRawOutputStream(), 0, true);
|
||||
|
||||
bool isCounterSignature = (signedContentType == null);
|
||||
|
||||
DerObjectIdentifier contentTypeOid = isCounterSignature
|
||||
? null
|
||||
: new DerObjectIdentifier(signedContentType);
|
||||
|
||||
sigGen.AddObject(CalculateVersion(contentTypeOid));
|
||||
|
||||
Asn1EncodableVector digestAlgs = new Asn1EncodableVector();
|
||||
|
||||
foreach (string digestOid in _messageDigestOids)
|
||||
{
|
||||
digestAlgs.Add(new AlgorithmIdentifier(new DerObjectIdentifier(digestOid), DerNull.Instance));
|
||||
}
|
||||
|
||||
new DerSet(digestAlgs).EncodeTo(sigGen.GetRawOutputStream());
|
||||
|
||||
BerSequenceGenerator eiGen = new BerSequenceGenerator(sigGen.GetRawOutputStream());
|
||||
eiGen.AddObject(contentTypeOid);
|
||||
|
||||
// If encapsulating, add the data as an octet string in the sequence
|
||||
Stream encapStream = encapsulate
|
||||
? CmsUtilities.CreateBerOctetOutputStream(eiGen.GetRawOutputStream(), 0, true, _bufferSize)
|
||||
: null;
|
||||
|
||||
// Also send the data to 'dataOutputStream' if necessary
|
||||
Stream teeStream = GetSafeTeeOutputStream(dataOutputStream, encapStream);
|
||||
|
||||
// Let all the digests see the data as it is written
|
||||
Stream digStream = AttachDigestsToOutputStream(m_messageDigests.Values, teeStream);
|
||||
|
||||
return new CmsSignedDataOutputStream(this, digStream, signedContentType, sGen, sigGen, eiGen);
|
||||
}
|
||||
|
||||
private void RegisterDigestOid(
|
||||
string digestOid)
|
||||
{
|
||||
if (_messageDigestsLocked)
|
||||
{
|
||||
if (!_messageDigestOids.Contains(digestOid))
|
||||
throw new InvalidOperationException("Cannot register new digest OIDs after the data stream is opened");
|
||||
}
|
||||
else
|
||||
{
|
||||
_messageDigestOids.Add(digestOid);
|
||||
}
|
||||
}
|
||||
|
||||
private void ConfigureDigest(string digestOid)
|
||||
{
|
||||
RegisterDigestOid(digestOid);
|
||||
|
||||
string digestName = Helper.GetDigestAlgName(digestOid);
|
||||
|
||||
if (!m_messageDigests.ContainsKey(digestName))
|
||||
{
|
||||
if (_messageDigestsLocked)
|
||||
throw new InvalidOperationException("Cannot configure new digests after the data stream is opened");
|
||||
|
||||
m_messageDigests[digestName] = Helper.GetDigestInstance(digestName);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO Make public?
|
||||
internal void Generate(
|
||||
Stream outStream,
|
||||
string eContentType,
|
||||
bool encapsulate,
|
||||
Stream dataOutputStream,
|
||||
CmsProcessable content)
|
||||
{
|
||||
using (var signedOut = Open(outStream, eContentType, encapsulate, dataOutputStream))
|
||||
{
|
||||
if (content != null)
|
||||
{
|
||||
content.Write(signedOut);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// RFC3852, section 5.1:
|
||||
// IF ((certificates is present) AND
|
||||
// (any certificates with a type of other are present)) OR
|
||||
// ((crls is present) AND
|
||||
// (any crls with a type of other are present))
|
||||
// THEN version MUST be 5
|
||||
// ELSE
|
||||
// IF (certificates is present) AND
|
||||
// (any version 2 attribute certificates are present)
|
||||
// THEN version MUST be 4
|
||||
// ELSE
|
||||
// IF ((certificates is present) AND
|
||||
// (any version 1 attribute certificates are present)) OR
|
||||
// (any SignerInfo structures are version 3) OR
|
||||
// (encapContentInfo eContentType is other than id-data)
|
||||
// THEN version MUST be 3
|
||||
// ELSE version MUST be 1
|
||||
//
|
||||
private DerInteger CalculateVersion(
|
||||
DerObjectIdentifier contentOid)
|
||||
{
|
||||
bool otherCert = false;
|
||||
bool otherCrl = false;
|
||||
bool attrCertV1Found = false;
|
||||
bool attrCertV2Found = false;
|
||||
|
||||
if (_certs != null)
|
||||
{
|
||||
foreach (object obj in _certs)
|
||||
{
|
||||
if (obj is Asn1TaggedObject tagged)
|
||||
{
|
||||
if (tagged.TagNo == 1)
|
||||
{
|
||||
attrCertV1Found = true;
|
||||
}
|
||||
else if (tagged.TagNo == 2)
|
||||
{
|
||||
attrCertV2Found = true;
|
||||
}
|
||||
else if (tagged.TagNo == 3)
|
||||
{
|
||||
otherCert = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (otherCert)
|
||||
{
|
||||
return new DerInteger(5);
|
||||
}
|
||||
|
||||
if (_crls != null)
|
||||
{
|
||||
foreach (object obj in _crls)
|
||||
{
|
||||
if (obj is Asn1TaggedObject)
|
||||
{
|
||||
otherCrl = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (otherCrl)
|
||||
{
|
||||
return new DerInteger(5);
|
||||
}
|
||||
|
||||
if (attrCertV2Found)
|
||||
{
|
||||
return new DerInteger(4);
|
||||
}
|
||||
|
||||
if (attrCertV1Found || !CmsObjectIdentifiers.Data.Equals(contentOid) || CheckForVersion3(_signers))
|
||||
{
|
||||
return new DerInteger(3);
|
||||
}
|
||||
|
||||
return new DerInteger(1);
|
||||
}
|
||||
|
||||
private bool CheckForVersion3(IList<SignerInformation> signerInfos)
|
||||
{
|
||||
foreach (SignerInformation si in signerInfos)
|
||||
{
|
||||
SignerInfo s = SignerInfo.GetInstance(si.ToSignerInfo());
|
||||
|
||||
if (s.Version.IntValueExact == 3)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static Stream AttachDigestsToOutputStream(IEnumerable<IDigest> digests, Stream s)
|
||||
{
|
||||
Stream result = s;
|
||||
foreach (IDigest digest in digests)
|
||||
{
|
||||
result = GetSafeTeeOutputStream(result, new DigestSink(digest));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static Stream GetSafeOutputStream(Stream s)
|
||||
{
|
||||
return s ?? Stream.Null;
|
||||
}
|
||||
|
||||
private static Stream GetSafeTeeOutputStream(Stream s1, Stream s2)
|
||||
{
|
||||
if (s1 == null)
|
||||
return GetSafeOutputStream(s2);
|
||||
if (s2 == null)
|
||||
return GetSafeOutputStream(s1);
|
||||
return new TeeOutputStream(s1, s2);
|
||||
}
|
||||
|
||||
private class CmsSignedDataOutputStream
|
||||
: BaseOutputStream
|
||||
{
|
||||
private readonly CmsSignedDataStreamGenerator outer;
|
||||
|
||||
private Stream _out;
|
||||
private DerObjectIdentifier _contentOID;
|
||||
private BerSequenceGenerator _sGen;
|
||||
private BerSequenceGenerator _sigGen;
|
||||
private BerSequenceGenerator _eiGen;
|
||||
|
||||
public CmsSignedDataOutputStream(
|
||||
CmsSignedDataStreamGenerator outer,
|
||||
Stream outStream,
|
||||
string contentOID,
|
||||
BerSequenceGenerator sGen,
|
||||
BerSequenceGenerator sigGen,
|
||||
BerSequenceGenerator eiGen)
|
||||
{
|
||||
this.outer = outer;
|
||||
|
||||
_out = outStream;
|
||||
_contentOID = new DerObjectIdentifier(contentOID);
|
||||
_sGen = sGen;
|
||||
_sigGen = sigGen;
|
||||
_eiGen = eiGen;
|
||||
}
|
||||
|
||||
public override void Write(byte[] buffer, int offset, int count)
|
||||
{
|
||||
_out.Write(buffer, offset, count);
|
||||
}
|
||||
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || _UNITY_2021_2_OR_NEWER_
|
||||
public override void Write(ReadOnlySpan<byte> buffer)
|
||||
{
|
||||
_out.Write(buffer);
|
||||
}
|
||||
#endif
|
||||
|
||||
public override void WriteByte(byte value)
|
||||
{
|
||||
_out.WriteByte(value);
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
DoClose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
private void DoClose()
|
||||
{
|
||||
_out.Dispose();
|
||||
|
||||
// TODO Parent context(s) should really be be closed explicitly
|
||||
|
||||
_eiGen.Close();
|
||||
|
||||
outer.m_digests.Clear(); // clear the current preserved digest state
|
||||
|
||||
if (outer._certs.Count > 0)
|
||||
{
|
||||
Asn1Set certs = outer.UseDerForCerts
|
||||
? CmsUtilities.CreateDerSetFromList(outer._certs)
|
||||
: CmsUtilities.CreateBerSetFromList(outer._certs);
|
||||
|
||||
WriteToGenerator(_sigGen, new BerTaggedObject(false, 0, certs));
|
||||
}
|
||||
|
||||
if (outer._crls.Count > 0)
|
||||
{
|
||||
Asn1Set crls = outer.UseDerForCrls
|
||||
? CmsUtilities.CreateDerSetFromList(outer._crls)
|
||||
: CmsUtilities.CreateBerSetFromList(outer._crls);
|
||||
|
||||
WriteToGenerator(_sigGen, new BerTaggedObject(false, 1, crls));
|
||||
}
|
||||
|
||||
//
|
||||
// Calculate the digest hashes
|
||||
//
|
||||
foreach (var de in outer.m_messageDigests)
|
||||
{
|
||||
outer.m_messageHashes.Add(de.Key, DigestUtilities.DoFinal(de.Value));
|
||||
}
|
||||
|
||||
// TODO If the digest OIDs for precalculated signers weren't mixed in with
|
||||
// the others, we could fill in outer._digests here, instead of SignerInfoGenerator.Generate
|
||||
|
||||
//
|
||||
// collect all the SignerInfo objects
|
||||
//
|
||||
Asn1EncodableVector signerInfos = new Asn1EncodableVector();
|
||||
|
||||
//
|
||||
// add the generated SignerInfo objects
|
||||
//
|
||||
{
|
||||
foreach (DigestAndSignerInfoGeneratorHolder holder in outer._signerInfs)
|
||||
{
|
||||
AlgorithmIdentifier digestAlgorithm = holder.DigestAlgorithm;
|
||||
|
||||
byte[] calculatedDigest = outer.m_messageHashes[
|
||||
Helper.GetDigestAlgName(holder.digestOID)];
|
||||
outer.m_digests[holder.digestOID] = (byte[])calculatedDigest.Clone();
|
||||
|
||||
signerInfos.Add(holder.signerInf.Generate(_contentOID, digestAlgorithm, calculatedDigest));
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// add the precalculated SignerInfo objects.
|
||||
//
|
||||
{
|
||||
foreach (SignerInformation signer in outer._signers)
|
||||
{
|
||||
// TODO Verify the content type and calculated digest match the precalculated SignerInfo
|
||||
// if (!signer.ContentType.Equals(_contentOID))
|
||||
// {
|
||||
// // TODO The precalculated content type did not match - error?
|
||||
// }
|
||||
//
|
||||
// byte[] calculatedDigest = (byte[])outer._digests[signer.DigestAlgOid];
|
||||
// if (calculatedDigest == null)
|
||||
// {
|
||||
// // TODO We can't confirm this digest because we didn't calculate it - error?
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// if (!Arrays.AreEqual(signer.GetContentDigest(), calculatedDigest))
|
||||
// {
|
||||
// // TODO The precalculated digest did not match - error?
|
||||
// }
|
||||
// }
|
||||
|
||||
signerInfos.Add(signer.ToSignerInfo());
|
||||
}
|
||||
}
|
||||
|
||||
WriteToGenerator(_sigGen, new DerSet(signerInfos));
|
||||
|
||||
_sigGen.Close();
|
||||
_sGen.Close();
|
||||
}
|
||||
|
||||
private static void WriteToGenerator(Asn1Generator ag, Asn1Encodable ae)
|
||||
{
|
||||
ae.EncodeTo(ag.GetRawOutputStream());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7609ff86af1d8cc4599341b4d5d36229
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,664 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.BC;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Bsi;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Cms;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.CryptoPro;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Eac;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.GM;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Nist;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Oiw;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Pkcs;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Rosstandart;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.TeleTrust;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.X509;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.X9;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Security;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Collections;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.X509;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Cms
|
||||
{
|
||||
public class DefaultSignatureAlgorithmIdentifierFinder
|
||||
{
|
||||
private static readonly IDictionary<string, DerObjectIdentifier> m_algorithms =
|
||||
new Dictionary<string, DerObjectIdentifier>(StringComparer.OrdinalIgnoreCase);
|
||||
private static readonly HashSet<DerObjectIdentifier> noParams = new HashSet<DerObjectIdentifier>();
|
||||
private static readonly IDictionary<string, Asn1Encodable> m_params =
|
||||
new Dictionary<string, Asn1Encodable>(StringComparer.OrdinalIgnoreCase);
|
||||
private static readonly HashSet<DerObjectIdentifier> pkcs15RsaEncryption = new HashSet<DerObjectIdentifier>();
|
||||
private static readonly IDictionary<DerObjectIdentifier, DerObjectIdentifier> m_digestOids =
|
||||
new Dictionary<DerObjectIdentifier, DerObjectIdentifier>();
|
||||
|
||||
//private static readonly DerObjectIdentifier ENCRYPTION_RSA = PkcsObjectIdentifiers.RsaEncryption;
|
||||
//private static readonly DerObjectIdentifier ENCRYPTION_DSA = X9ObjectIdentifiers.IdDsaWithSha1;
|
||||
//private static readonly DerObjectIdentifier ENCRYPTION_ECDSA = X9ObjectIdentifiers.ECDsaWithSha1;
|
||||
//private static readonly DerObjectIdentifier ENCRYPTION_RSA_PSS = PkcsObjectIdentifiers.IdRsassaPss;
|
||||
//private static readonly DerObjectIdentifier ENCRYPTION_GOST3410 = CryptoProObjectIdentifiers.GostR3410x94;
|
||||
//private static readonly DerObjectIdentifier ENCRYPTION_ECGOST3410 = CryptoProObjectIdentifiers.GostR3410x2001;
|
||||
//private static readonly DerObjectIdentifier ENCRYPTION_ECGOST3410_2012_256 = RosstandartObjectIdentifiers.id_tc26_gost_3410_12_256;
|
||||
//private static readonly DerObjectIdentifier ENCRYPTION_ECGOST3410_2012_512 = RosstandartObjectIdentifiers.id_tc26_gost_3410_12_512;
|
||||
|
||||
static DefaultSignatureAlgorithmIdentifierFinder()
|
||||
{
|
||||
m_algorithms["MD2WITHRSAENCRYPTION"] = PkcsObjectIdentifiers.MD2WithRsaEncryption;
|
||||
m_algorithms["MD2WITHRSA"] = PkcsObjectIdentifiers.MD2WithRsaEncryption;
|
||||
m_algorithms["MD5WITHRSAENCRYPTION"] = PkcsObjectIdentifiers.MD5WithRsaEncryption;
|
||||
m_algorithms["MD5WITHRSA"] = PkcsObjectIdentifiers.MD5WithRsaEncryption;
|
||||
m_algorithms["SHA1WITHRSAENCRYPTION"] = PkcsObjectIdentifiers.Sha1WithRsaEncryption;
|
||||
m_algorithms["SHA-1WITHRSAENCRYPTION"] = PkcsObjectIdentifiers.Sha1WithRsaEncryption;
|
||||
m_algorithms["SHA1WITHRSA"] = PkcsObjectIdentifiers.Sha1WithRsaEncryption;
|
||||
m_algorithms["SHA-1WITHRSA"] = PkcsObjectIdentifiers.Sha1WithRsaEncryption;
|
||||
m_algorithms["SHA224WITHRSAENCRYPTION"] = PkcsObjectIdentifiers.Sha224WithRsaEncryption;
|
||||
m_algorithms["SHA-224WITHRSAENCRYPTION"] = PkcsObjectIdentifiers.Sha224WithRsaEncryption;
|
||||
m_algorithms["SHA224WITHRSA"] = PkcsObjectIdentifiers.Sha224WithRsaEncryption;
|
||||
m_algorithms["SHA-224WITHRSA"] = PkcsObjectIdentifiers.Sha224WithRsaEncryption;
|
||||
m_algorithms["SHA256WITHRSAENCRYPTION"] = PkcsObjectIdentifiers.Sha256WithRsaEncryption;
|
||||
m_algorithms["SHA-256WITHRSAENCRYPTION"] = PkcsObjectIdentifiers.Sha256WithRsaEncryption;
|
||||
m_algorithms["SHA256WITHRSA"] = PkcsObjectIdentifiers.Sha256WithRsaEncryption;
|
||||
m_algorithms["SHA-256WITHRSA"] = PkcsObjectIdentifiers.Sha256WithRsaEncryption;
|
||||
m_algorithms["SHA384WITHRSAENCRYPTION"] = PkcsObjectIdentifiers.Sha384WithRsaEncryption;
|
||||
m_algorithms["SHA-384WITHRSAENCRYPTION"] = PkcsObjectIdentifiers.Sha384WithRsaEncryption;
|
||||
m_algorithms["SHA384WITHRSA"] = PkcsObjectIdentifiers.Sha384WithRsaEncryption;
|
||||
m_algorithms["SHA-384WITHRSA"] = PkcsObjectIdentifiers.Sha384WithRsaEncryption;
|
||||
m_algorithms["SHA512WITHRSAENCRYPTION"] = PkcsObjectIdentifiers.Sha512WithRsaEncryption;
|
||||
m_algorithms["SHA-512WITHRSAENCRYPTION"] = PkcsObjectIdentifiers.Sha512WithRsaEncryption;
|
||||
m_algorithms["SHA512WITHRSA"] = PkcsObjectIdentifiers.Sha512WithRsaEncryption;
|
||||
m_algorithms["SHA-512WITHRSA"] = PkcsObjectIdentifiers.Sha512WithRsaEncryption;
|
||||
m_algorithms["SHA512(224)WITHRSAENCRYPTION"] = PkcsObjectIdentifiers.Sha512_224WithRSAEncryption;
|
||||
m_algorithms["SHA-512(224)WITHRSAENCRYPTION"] = PkcsObjectIdentifiers.Sha512_224WithRSAEncryption;
|
||||
m_algorithms["SHA512(224)WITHRSA"] = PkcsObjectIdentifiers.Sha512_224WithRSAEncryption;
|
||||
m_algorithms["SHA-512(224)WITHRSA"] = PkcsObjectIdentifiers.Sha512_224WithRSAEncryption;
|
||||
m_algorithms["SHA512(256)WITHRSAENCRYPTION"] = PkcsObjectIdentifiers.Sha512_256WithRSAEncryption;
|
||||
m_algorithms["SHA-512(256)WITHRSAENCRYPTION"] = PkcsObjectIdentifiers.Sha512_256WithRSAEncryption;
|
||||
m_algorithms["SHA512(256)WITHRSA"] = PkcsObjectIdentifiers.Sha512_256WithRSAEncryption;
|
||||
m_algorithms["SHA-512(256)WITHRSA"] = PkcsObjectIdentifiers.Sha512_256WithRSAEncryption;
|
||||
m_algorithms["SHA1WITHRSAANDMGF1"] = PkcsObjectIdentifiers.IdRsassaPss;
|
||||
m_algorithms["SHA224WITHRSAANDMGF1"] = PkcsObjectIdentifiers.IdRsassaPss;
|
||||
m_algorithms["SHA256WITHRSAANDMGF1"] = PkcsObjectIdentifiers.IdRsassaPss;
|
||||
m_algorithms["SHA384WITHRSAANDMGF1"] = PkcsObjectIdentifiers.IdRsassaPss;
|
||||
m_algorithms["SHA512WITHRSAANDMGF1"] = PkcsObjectIdentifiers.IdRsassaPss;
|
||||
m_algorithms["SHA3-224WITHRSAANDMGF1"] = PkcsObjectIdentifiers.IdRsassaPss;
|
||||
m_algorithms["SHA3-256WITHRSAANDMGF1"] = PkcsObjectIdentifiers.IdRsassaPss;
|
||||
m_algorithms["SHA3-384WITHRSAANDMGF1"] = PkcsObjectIdentifiers.IdRsassaPss;
|
||||
m_algorithms["SHA3-512WITHRSAANDMGF1"] = PkcsObjectIdentifiers.IdRsassaPss;
|
||||
m_algorithms["RIPEMD160WITHRSAENCRYPTION"] = TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD160;
|
||||
m_algorithms["RIPEMD160WITHRSA"] = TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD160;
|
||||
m_algorithms["RIPEMD128WITHRSAENCRYPTION"] = TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD128;
|
||||
m_algorithms["RIPEMD128WITHRSA"] = TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD128;
|
||||
m_algorithms["RIPEMD256WITHRSAENCRYPTION"] = TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD256;
|
||||
m_algorithms["RIPEMD256WITHRSA"] = TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD256;
|
||||
m_algorithms["SHA1WITHDSA"] = X9ObjectIdentifiers.IdDsaWithSha1;
|
||||
m_algorithms["SHA-1WITHDSA"] = X9ObjectIdentifiers.IdDsaWithSha1;
|
||||
m_algorithms["DSAWITHSHA1"] = X9ObjectIdentifiers.IdDsaWithSha1;
|
||||
m_algorithms["SHA224WITHDSA"] = NistObjectIdentifiers.DsaWithSha224;
|
||||
m_algorithms["SHA256WITHDSA"] = NistObjectIdentifiers.DsaWithSha256;
|
||||
m_algorithms["SHA384WITHDSA"] = NistObjectIdentifiers.DsaWithSha384;
|
||||
m_algorithms["SHA512WITHDSA"] = NistObjectIdentifiers.DsaWithSha512;
|
||||
m_algorithms["SHA3-224WITHDSA"] = NistObjectIdentifiers.IdDsaWithSha3_224;
|
||||
m_algorithms["SHA3-256WITHDSA"] = NistObjectIdentifiers.IdDsaWithSha3_256;
|
||||
m_algorithms["SHA3-384WITHDSA"] = NistObjectIdentifiers.IdDsaWithSha3_384;
|
||||
m_algorithms["SHA3-512WITHDSA"] = NistObjectIdentifiers.IdDsaWithSha3_512;
|
||||
m_algorithms["SHA3-224WITHECDSA"] = NistObjectIdentifiers.IdEcdsaWithSha3_224;
|
||||
m_algorithms["SHA3-256WITHECDSA"] = NistObjectIdentifiers.IdEcdsaWithSha3_256;
|
||||
m_algorithms["SHA3-384WITHECDSA"] = NistObjectIdentifiers.IdEcdsaWithSha3_384;
|
||||
m_algorithms["SHA3-512WITHECDSA"] = NistObjectIdentifiers.IdEcdsaWithSha3_512;
|
||||
m_algorithms["SHA3-224WITHRSA"] = NistObjectIdentifiers.IdRsassaPkcs1V15WithSha3_224;
|
||||
m_algorithms["SHA3-256WITHRSA"] = NistObjectIdentifiers.IdRsassaPkcs1V15WithSha3_256;
|
||||
m_algorithms["SHA3-384WITHRSA"] = NistObjectIdentifiers.IdRsassaPkcs1V15WithSha3_384;
|
||||
m_algorithms["SHA3-512WITHRSA"] = NistObjectIdentifiers.IdRsassaPkcs1V15WithSha3_512;
|
||||
m_algorithms["SHA3-224WITHRSAENCRYPTION"] = NistObjectIdentifiers.IdRsassaPkcs1V15WithSha3_224;
|
||||
m_algorithms["SHA3-256WITHRSAENCRYPTION"] = NistObjectIdentifiers.IdRsassaPkcs1V15WithSha3_256;
|
||||
m_algorithms["SHA3-384WITHRSAENCRYPTION"] = NistObjectIdentifiers.IdRsassaPkcs1V15WithSha3_384;
|
||||
m_algorithms["SHA3-512WITHRSAENCRYPTION"] = NistObjectIdentifiers.IdRsassaPkcs1V15WithSha3_512;
|
||||
m_algorithms["SHA1WITHECDSA"] = X9ObjectIdentifiers.ECDsaWithSha1;
|
||||
m_algorithms["ECDSAWITHSHA1"] = X9ObjectIdentifiers.ECDsaWithSha1;
|
||||
m_algorithms["SHA224WITHECDSA"] = X9ObjectIdentifiers.ECDsaWithSha224;
|
||||
m_algorithms["SHA256WITHECDSA"] = X9ObjectIdentifiers.ECDsaWithSha256;
|
||||
m_algorithms["SHA384WITHECDSA"] = X9ObjectIdentifiers.ECDsaWithSha384;
|
||||
m_algorithms["SHA512WITHECDSA"] = X9ObjectIdentifiers.ECDsaWithSha512;
|
||||
|
||||
|
||||
m_algorithms["GOST3411WITHGOST3410"] = CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x94;
|
||||
m_algorithms["GOST3411WITHGOST3410-94"] = CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x94;
|
||||
m_algorithms["GOST3411WITHECGOST3410"] = CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x2001;
|
||||
m_algorithms["GOST3411WITHECGOST3410-2001"] = CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x2001;
|
||||
m_algorithms["GOST3411WITHGOST3410-2001"] = CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x2001;
|
||||
m_algorithms["GOST3411WITHECGOST3410-2012-256"] = RosstandartObjectIdentifiers.id_tc26_signwithdigest_gost_3410_12_256;
|
||||
m_algorithms["GOST3411WITHECGOST3410-2012-512"] = RosstandartObjectIdentifiers.id_tc26_signwithdigest_gost_3410_12_512;
|
||||
m_algorithms["GOST3411-2012-256WITHECGOST3410"] = RosstandartObjectIdentifiers.id_tc26_signwithdigest_gost_3410_12_256;
|
||||
m_algorithms["GOST3411-2012-256WITHECGOST3410-2012-256"] = RosstandartObjectIdentifiers.id_tc26_signwithdigest_gost_3410_12_256;
|
||||
m_algorithms["GOST3411-2012-512WITHECGOST3410"] = RosstandartObjectIdentifiers.id_tc26_signwithdigest_gost_3410_12_512;
|
||||
m_algorithms["GOST3411-2012-512WITHECGOST3410-2012-512"] = RosstandartObjectIdentifiers.id_tc26_signwithdigest_gost_3410_12_512;
|
||||
m_algorithms["SHA1WITHPLAIN-ECDSA"] = BsiObjectIdentifiers.ecdsa_plain_SHA1;
|
||||
m_algorithms["SHA224WITHPLAIN-ECDSA"] = BsiObjectIdentifiers.ecdsa_plain_SHA224;
|
||||
m_algorithms["SHA256WITHPLAIN-ECDSA"] = BsiObjectIdentifiers.ecdsa_plain_SHA256;
|
||||
m_algorithms["SHA384WITHPLAIN-ECDSA"] = BsiObjectIdentifiers.ecdsa_plain_SHA384;
|
||||
m_algorithms["SHA512WITHPLAIN-ECDSA"] = BsiObjectIdentifiers.ecdsa_plain_SHA512;
|
||||
m_algorithms["RIPEMD160WITHPLAIN-ECDSA"] = BsiObjectIdentifiers.ecdsa_plain_RIPEMD160;
|
||||
m_algorithms["SHA1WITHCVC-ECDSA"] = EacObjectIdentifiers.id_TA_ECDSA_SHA_1;
|
||||
m_algorithms["SHA224WITHCVC-ECDSA"] = EacObjectIdentifiers.id_TA_ECDSA_SHA_224;
|
||||
m_algorithms["SHA256WITHCVC-ECDSA"] = EacObjectIdentifiers.id_TA_ECDSA_SHA_256;
|
||||
m_algorithms["SHA384WITHCVC-ECDSA"] = EacObjectIdentifiers.id_TA_ECDSA_SHA_384;
|
||||
m_algorithms["SHA512WITHCVC-ECDSA"] = EacObjectIdentifiers.id_TA_ECDSA_SHA_512;
|
||||
m_algorithms["SHA3-512WITHSPHINCS256"] = BCObjectIdentifiers.sphincs256_with_SHA3_512;
|
||||
m_algorithms["SHA512WITHSPHINCS256"] = BCObjectIdentifiers.sphincs256_with_SHA512;
|
||||
|
||||
m_algorithms["SHA256WITHSM2"] = GMObjectIdentifiers.sm2sign_with_sha256;
|
||||
m_algorithms["SM3WITHSM2"] = GMObjectIdentifiers.sm2sign_with_sm3;
|
||||
|
||||
m_algorithms["SHA256WITHXMSS"] = BCObjectIdentifiers.xmss_with_SHA256;
|
||||
m_algorithms["SHA512WITHXMSS"] = BCObjectIdentifiers.xmss_with_SHA512;
|
||||
m_algorithms["SHAKE128WITHXMSS"] = BCObjectIdentifiers.xmss_with_SHAKE128;
|
||||
m_algorithms["SHAKE256WITHXMSS"] = BCObjectIdentifiers.xmss_with_SHAKE256;
|
||||
|
||||
m_algorithms["SHA256WITHXMSSMT"] = BCObjectIdentifiers.xmss_mt_with_SHA256;
|
||||
m_algorithms["SHA512WITHXMSSMT"] = BCObjectIdentifiers.xmss_mt_with_SHA512;
|
||||
m_algorithms["SHAKE128WITHXMSSMT"] = BCObjectIdentifiers.xmss_mt_with_SHAKE128;
|
||||
m_algorithms["SHAKE256WITHXMSSMT"] = BCObjectIdentifiers.xmss_mt_with_SHAKE256;
|
||||
|
||||
|
||||
//
|
||||
// According to RFC 3279, the ASN.1 encoding SHALL (id-dsa-with-sha1) or MUST (ecdsa-with-SHA*) omit the parameters field.
|
||||
// The parameters field SHALL be NULL for RSA based signature algorithms.
|
||||
//
|
||||
noParams.Add(X9ObjectIdentifiers.ECDsaWithSha1);
|
||||
noParams.Add(X9ObjectIdentifiers.ECDsaWithSha224);
|
||||
noParams.Add(X9ObjectIdentifiers.ECDsaWithSha256);
|
||||
noParams.Add(X9ObjectIdentifiers.ECDsaWithSha384);
|
||||
noParams.Add(X9ObjectIdentifiers.ECDsaWithSha512);
|
||||
noParams.Add(X9ObjectIdentifiers.IdDsaWithSha1);
|
||||
noParams.Add(NistObjectIdentifiers.DsaWithSha224);
|
||||
noParams.Add(NistObjectIdentifiers.DsaWithSha256);
|
||||
noParams.Add(NistObjectIdentifiers.DsaWithSha384);
|
||||
noParams.Add(NistObjectIdentifiers.DsaWithSha512);
|
||||
noParams.Add(NistObjectIdentifiers.IdDsaWithSha3_224);
|
||||
noParams.Add(NistObjectIdentifiers.IdDsaWithSha3_256);
|
||||
noParams.Add(NistObjectIdentifiers.IdDsaWithSha3_384);
|
||||
noParams.Add(NistObjectIdentifiers.IdDsaWithSha3_512);
|
||||
noParams.Add(NistObjectIdentifiers.IdEcdsaWithSha3_224);
|
||||
noParams.Add(NistObjectIdentifiers.IdEcdsaWithSha3_256);
|
||||
noParams.Add(NistObjectIdentifiers.IdEcdsaWithSha3_384);
|
||||
noParams.Add(NistObjectIdentifiers.IdEcdsaWithSha3_512);
|
||||
|
||||
|
||||
//
|
||||
// RFC 4491
|
||||
//
|
||||
noParams.Add(CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x94);
|
||||
noParams.Add(CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x2001);
|
||||
noParams.Add(RosstandartObjectIdentifiers.id_tc26_signwithdigest_gost_3410_12_256);
|
||||
noParams.Add(RosstandartObjectIdentifiers.id_tc26_signwithdigest_gost_3410_12_512);
|
||||
|
||||
//
|
||||
// SPHINCS-256
|
||||
//
|
||||
noParams.Add(BCObjectIdentifiers.sphincs256_with_SHA512);
|
||||
noParams.Add(BCObjectIdentifiers.sphincs256_with_SHA3_512);
|
||||
|
||||
//
|
||||
// XMSS
|
||||
//
|
||||
noParams.Add(BCObjectIdentifiers.xmss_with_SHA256);
|
||||
noParams.Add(BCObjectIdentifiers.xmss_with_SHA512);
|
||||
noParams.Add(BCObjectIdentifiers.xmss_with_SHAKE128);
|
||||
noParams.Add(BCObjectIdentifiers.xmss_with_SHAKE256);
|
||||
noParams.Add(BCObjectIdentifiers.xmss_mt_with_SHA256);
|
||||
noParams.Add(BCObjectIdentifiers.xmss_mt_with_SHA512);
|
||||
noParams.Add(BCObjectIdentifiers.xmss_mt_with_SHAKE128);
|
||||
noParams.Add(BCObjectIdentifiers.xmss_mt_with_SHAKE256);
|
||||
|
||||
//
|
||||
// SM2
|
||||
//
|
||||
noParams.Add(GMObjectIdentifiers.sm2sign_with_sha256);
|
||||
noParams.Add(GMObjectIdentifiers.sm2sign_with_sm3);
|
||||
|
||||
//
|
||||
// PKCS 1.5 encrypted algorithms
|
||||
//
|
||||
pkcs15RsaEncryption.Add(PkcsObjectIdentifiers.Sha1WithRsaEncryption);
|
||||
pkcs15RsaEncryption.Add(PkcsObjectIdentifiers.Sha224WithRsaEncryption);
|
||||
pkcs15RsaEncryption.Add(PkcsObjectIdentifiers.Sha256WithRsaEncryption);
|
||||
pkcs15RsaEncryption.Add(PkcsObjectIdentifiers.Sha384WithRsaEncryption);
|
||||
pkcs15RsaEncryption.Add(PkcsObjectIdentifiers.Sha512WithRsaEncryption);
|
||||
pkcs15RsaEncryption.Add(PkcsObjectIdentifiers.Sha512_224WithRSAEncryption);
|
||||
pkcs15RsaEncryption.Add(PkcsObjectIdentifiers.Sha512_256WithRSAEncryption);
|
||||
pkcs15RsaEncryption.Add(TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD128);
|
||||
pkcs15RsaEncryption.Add(TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD160);
|
||||
pkcs15RsaEncryption.Add(TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD256);
|
||||
pkcs15RsaEncryption.Add(NistObjectIdentifiers.IdRsassaPkcs1V15WithSha3_224);
|
||||
pkcs15RsaEncryption.Add(NistObjectIdentifiers.IdRsassaPkcs1V15WithSha3_256);
|
||||
pkcs15RsaEncryption.Add(NistObjectIdentifiers.IdRsassaPkcs1V15WithSha3_384);
|
||||
pkcs15RsaEncryption.Add(NistObjectIdentifiers.IdRsassaPkcs1V15WithSha3_512);
|
||||
|
||||
//
|
||||
// explicit params
|
||||
//
|
||||
AlgorithmIdentifier sha1AlgId = new AlgorithmIdentifier(OiwObjectIdentifiers.IdSha1, DerNull.Instance);
|
||||
m_params["SHA1WITHRSAANDMGF1"] = CreatePssParams(sha1AlgId, 20);
|
||||
|
||||
AlgorithmIdentifier sha224AlgId = new AlgorithmIdentifier(NistObjectIdentifiers.IdSha224, DerNull.Instance);
|
||||
m_params["SHA224WITHRSAANDMGF1"] = CreatePssParams(sha224AlgId, 28);
|
||||
|
||||
AlgorithmIdentifier sha256AlgId = new AlgorithmIdentifier(NistObjectIdentifiers.IdSha256, DerNull.Instance);
|
||||
m_params["SHA256WITHRSAANDMGF1"] = CreatePssParams(sha256AlgId, 32);
|
||||
|
||||
AlgorithmIdentifier sha384AlgId = new AlgorithmIdentifier(NistObjectIdentifiers.IdSha384, DerNull.Instance);
|
||||
m_params["SHA384WITHRSAANDMGF1"] = CreatePssParams(sha384AlgId, 48);
|
||||
|
||||
AlgorithmIdentifier sha512AlgId = new AlgorithmIdentifier(NistObjectIdentifiers.IdSha512, DerNull.Instance);
|
||||
m_params["SHA512WITHRSAANDMGF1"] = CreatePssParams(sha512AlgId, 64);
|
||||
|
||||
AlgorithmIdentifier sha3_224AlgId = new AlgorithmIdentifier(NistObjectIdentifiers.IdSha3_224, DerNull.Instance);
|
||||
m_params["SHA3-224WITHRSAANDMGF1"] = CreatePssParams(sha3_224AlgId, 28);
|
||||
|
||||
AlgorithmIdentifier sha3_256AlgId = new AlgorithmIdentifier(NistObjectIdentifiers.IdSha3_256, DerNull.Instance);
|
||||
m_params["SHA3-256WITHRSAANDMGF1"] = CreatePssParams(sha3_256AlgId, 32);
|
||||
|
||||
AlgorithmIdentifier sha3_384AlgId = new AlgorithmIdentifier(NistObjectIdentifiers.IdSha3_384, DerNull.Instance);
|
||||
m_params["SHA3-384WITHRSAANDMGF1"] = CreatePssParams(sha3_384AlgId, 48);
|
||||
|
||||
AlgorithmIdentifier sha3_512AlgId = new AlgorithmIdentifier(NistObjectIdentifiers.IdSha3_512, DerNull.Instance);
|
||||
m_params["SHA3-512WITHRSAANDMGF1"] = CreatePssParams(sha3_512AlgId, 64);
|
||||
|
||||
//
|
||||
// digests
|
||||
//
|
||||
m_digestOids[PkcsObjectIdentifiers.Sha224WithRsaEncryption] = NistObjectIdentifiers.IdSha224;
|
||||
m_digestOids[PkcsObjectIdentifiers.Sha256WithRsaEncryption] = NistObjectIdentifiers.IdSha256;
|
||||
m_digestOids[PkcsObjectIdentifiers.Sha384WithRsaEncryption] = NistObjectIdentifiers.IdSha384;
|
||||
m_digestOids[PkcsObjectIdentifiers.Sha512WithRsaEncryption] = NistObjectIdentifiers.IdSha512;
|
||||
m_digestOids[PkcsObjectIdentifiers.Sha512_224WithRSAEncryption] = NistObjectIdentifiers.IdSha512_224;
|
||||
m_digestOids[PkcsObjectIdentifiers.Sha512_256WithRSAEncryption] = NistObjectIdentifiers.IdSha512_256;
|
||||
m_digestOids[NistObjectIdentifiers.DsaWithSha224] = NistObjectIdentifiers.IdSha224;
|
||||
m_digestOids[NistObjectIdentifiers.DsaWithSha256] = NistObjectIdentifiers.IdSha256;
|
||||
m_digestOids[NistObjectIdentifiers.DsaWithSha384] = NistObjectIdentifiers.IdSha384;
|
||||
m_digestOids[NistObjectIdentifiers.DsaWithSha512] = NistObjectIdentifiers.IdSha512;
|
||||
m_digestOids[NistObjectIdentifiers.IdDsaWithSha3_224] = NistObjectIdentifiers.IdSha3_224;
|
||||
m_digestOids[NistObjectIdentifiers.IdDsaWithSha3_256] = NistObjectIdentifiers.IdSha3_256;
|
||||
m_digestOids[NistObjectIdentifiers.IdDsaWithSha3_384] = NistObjectIdentifiers.IdSha3_384;
|
||||
m_digestOids[NistObjectIdentifiers.IdDsaWithSha3_512] = NistObjectIdentifiers.IdSha3_512;
|
||||
m_digestOids[NistObjectIdentifiers.IdEcdsaWithSha3_224] = NistObjectIdentifiers.IdSha3_224;
|
||||
m_digestOids[NistObjectIdentifiers.IdEcdsaWithSha3_256] = NistObjectIdentifiers.IdSha3_256;
|
||||
m_digestOids[NistObjectIdentifiers.IdEcdsaWithSha3_384] = NistObjectIdentifiers.IdSha3_384;
|
||||
m_digestOids[NistObjectIdentifiers.IdEcdsaWithSha3_512] = NistObjectIdentifiers.IdSha3_512;
|
||||
m_digestOids[NistObjectIdentifiers.IdRsassaPkcs1V15WithSha3_224] = NistObjectIdentifiers.IdSha3_224;
|
||||
m_digestOids[NistObjectIdentifiers.IdRsassaPkcs1V15WithSha3_256] = NistObjectIdentifiers.IdSha3_256;
|
||||
m_digestOids[NistObjectIdentifiers.IdRsassaPkcs1V15WithSha3_384] = NistObjectIdentifiers.IdSha3_384;
|
||||
m_digestOids[NistObjectIdentifiers.IdRsassaPkcs1V15WithSha3_512] = NistObjectIdentifiers.IdSha3_512;
|
||||
|
||||
m_digestOids[PkcsObjectIdentifiers.MD2WithRsaEncryption] = PkcsObjectIdentifiers.MD2;
|
||||
m_digestOids[PkcsObjectIdentifiers.MD4WithRsaEncryption] = PkcsObjectIdentifiers.MD4;
|
||||
m_digestOids[PkcsObjectIdentifiers.MD5WithRsaEncryption] = PkcsObjectIdentifiers.MD5;
|
||||
m_digestOids[PkcsObjectIdentifiers.Sha1WithRsaEncryption] = OiwObjectIdentifiers.IdSha1;
|
||||
m_digestOids[TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD128] = TeleTrusTObjectIdentifiers.RipeMD128;
|
||||
m_digestOids[TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD160] = TeleTrusTObjectIdentifiers.RipeMD160;
|
||||
m_digestOids[TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD256] = TeleTrusTObjectIdentifiers.RipeMD256;
|
||||
m_digestOids[CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x94] = CryptoProObjectIdentifiers.GostR3411;
|
||||
m_digestOids[CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x2001] = CryptoProObjectIdentifiers.GostR3411;
|
||||
m_digestOids[RosstandartObjectIdentifiers.id_tc26_signwithdigest_gost_3410_12_256] = RosstandartObjectIdentifiers.id_tc26_gost_3411_12_256;
|
||||
m_digestOids[RosstandartObjectIdentifiers.id_tc26_signwithdigest_gost_3410_12_512] = RosstandartObjectIdentifiers.id_tc26_gost_3411_12_512;
|
||||
|
||||
m_digestOids[GMObjectIdentifiers.sm2sign_with_sha256] = NistObjectIdentifiers.IdSha256;
|
||||
m_digestOids[GMObjectIdentifiers.sm2sign_with_sm3] = GMObjectIdentifiers.sm3;
|
||||
}
|
||||
|
||||
private static AlgorithmIdentifier Generate(string signatureAlgorithm)
|
||||
{
|
||||
AlgorithmIdentifier sigAlgId;
|
||||
//AlgorithmIdentifier encAlgId;
|
||||
//AlgorithmIdentifier digAlgId;
|
||||
|
||||
if (!m_algorithms.TryGetValue(signatureAlgorithm, out var sigOid))
|
||||
throw new ArgumentException("Unknown signature type requested: " + signatureAlgorithm);
|
||||
|
||||
if (noParams.Contains(sigOid))
|
||||
{
|
||||
sigAlgId = new AlgorithmIdentifier(sigOid);
|
||||
}
|
||||
else if (m_params.TryGetValue(signatureAlgorithm, out var explicitParameters))
|
||||
{
|
||||
sigAlgId = new AlgorithmIdentifier(sigOid, explicitParameters);
|
||||
}
|
||||
else
|
||||
{
|
||||
sigAlgId = new AlgorithmIdentifier(sigOid, DerNull.Instance);
|
||||
}
|
||||
|
||||
//if (pkcs15RsaEncryption.Contains(sigOid))
|
||||
//{
|
||||
// encAlgId = new AlgorithmIdentifier(PkcsObjectIdentifiers.RsaEncryption, DerNull.Instance);
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// encAlgId = sigAlgId;
|
||||
//}
|
||||
|
||||
//if (sigAlgId.Algorithm.Equals(PkcsObjectIdentifiers.IdRsassaPss))
|
||||
//{
|
||||
// digAlgId = ((RsassaPssParameters)sigAlgId.Parameters).HashAlgorithm;
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// digAlgId = new AlgorithmIdentifier(m_digestOids[sigOid], DerNull.Instance);
|
||||
//}
|
||||
|
||||
return sigAlgId;
|
||||
}
|
||||
|
||||
private static RsassaPssParameters CreatePssParams(AlgorithmIdentifier hashAlgId, int saltSize)
|
||||
{
|
||||
return new RsassaPssParameters(
|
||||
hashAlgId,
|
||||
new AlgorithmIdentifier(PkcsObjectIdentifiers.IdMgf1, hashAlgId),
|
||||
new DerInteger(saltSize),
|
||||
new DerInteger(1));
|
||||
}
|
||||
|
||||
public AlgorithmIdentifier Find(string sigAlgName)
|
||||
{
|
||||
return Generate(sigAlgName);
|
||||
}
|
||||
}
|
||||
|
||||
public class DefaultDigestAlgorithmIdentifierFinder
|
||||
{
|
||||
private static readonly IDictionary<DerObjectIdentifier, DerObjectIdentifier> m_digestOids =
|
||||
new Dictionary<DerObjectIdentifier, DerObjectIdentifier>();
|
||||
private static readonly IDictionary<string, DerObjectIdentifier> m_digestNameToOids =
|
||||
new Dictionary<string, DerObjectIdentifier>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
static DefaultDigestAlgorithmIdentifierFinder()
|
||||
{
|
||||
//
|
||||
// digests
|
||||
//
|
||||
m_digestOids.Add(OiwObjectIdentifiers.MD4WithRsaEncryption, PkcsObjectIdentifiers.MD4);
|
||||
m_digestOids.Add(OiwObjectIdentifiers.MD4WithRsa, PkcsObjectIdentifiers.MD4);
|
||||
m_digestOids.Add(OiwObjectIdentifiers.MD5WithRsa, PkcsObjectIdentifiers.MD5);
|
||||
m_digestOids.Add(OiwObjectIdentifiers.Sha1WithRsa, OiwObjectIdentifiers.IdSha1);
|
||||
m_digestOids.Add(OiwObjectIdentifiers.DsaWithSha1, OiwObjectIdentifiers.IdSha1);
|
||||
|
||||
m_digestOids.Add(PkcsObjectIdentifiers.Sha224WithRsaEncryption, NistObjectIdentifiers.IdSha224);
|
||||
m_digestOids.Add(PkcsObjectIdentifiers.Sha256WithRsaEncryption, NistObjectIdentifiers.IdSha256);
|
||||
m_digestOids.Add(PkcsObjectIdentifiers.Sha384WithRsaEncryption, NistObjectIdentifiers.IdSha384);
|
||||
m_digestOids.Add(PkcsObjectIdentifiers.Sha512WithRsaEncryption, NistObjectIdentifiers.IdSha512);
|
||||
m_digestOids.Add(PkcsObjectIdentifiers.Sha512_224WithRSAEncryption, NistObjectIdentifiers.IdSha512_224);
|
||||
m_digestOids.Add(PkcsObjectIdentifiers.Sha512_256WithRSAEncryption, NistObjectIdentifiers.IdSha512_256);
|
||||
|
||||
m_digestOids.Add(NistObjectIdentifiers.IdRsassaPkcs1V15WithSha3_224, NistObjectIdentifiers.IdSha3_224);
|
||||
m_digestOids.Add(NistObjectIdentifiers.IdRsassaPkcs1V15WithSha3_256, NistObjectIdentifiers.IdSha3_256);
|
||||
m_digestOids.Add(NistObjectIdentifiers.IdRsassaPkcs1V15WithSha3_384, NistObjectIdentifiers.IdSha3_384);
|
||||
m_digestOids.Add(NistObjectIdentifiers.IdRsassaPkcs1V15WithSha3_512, NistObjectIdentifiers.IdSha3_512);
|
||||
|
||||
m_digestOids.Add(PkcsObjectIdentifiers.MD2WithRsaEncryption, PkcsObjectIdentifiers.MD2);
|
||||
m_digestOids.Add(PkcsObjectIdentifiers.MD4WithRsaEncryption, PkcsObjectIdentifiers.MD4);
|
||||
m_digestOids.Add(PkcsObjectIdentifiers.MD5WithRsaEncryption, PkcsObjectIdentifiers.MD5);
|
||||
m_digestOids.Add(PkcsObjectIdentifiers.Sha1WithRsaEncryption, OiwObjectIdentifiers.IdSha1);
|
||||
|
||||
m_digestOids.Add(X9ObjectIdentifiers.ECDsaWithSha1, OiwObjectIdentifiers.IdSha1);
|
||||
m_digestOids.Add(X9ObjectIdentifiers.ECDsaWithSha224, NistObjectIdentifiers.IdSha224);
|
||||
m_digestOids.Add(X9ObjectIdentifiers.ECDsaWithSha256, NistObjectIdentifiers.IdSha256);
|
||||
m_digestOids.Add(X9ObjectIdentifiers.ECDsaWithSha384, NistObjectIdentifiers.IdSha384);
|
||||
m_digestOids.Add(X9ObjectIdentifiers.ECDsaWithSha512, NistObjectIdentifiers.IdSha512);
|
||||
m_digestOids.Add(X9ObjectIdentifiers.IdDsaWithSha1, OiwObjectIdentifiers.IdSha1);
|
||||
|
||||
m_digestOids.Add(NistObjectIdentifiers.DsaWithSha224, NistObjectIdentifiers.IdSha224);
|
||||
m_digestOids.Add(NistObjectIdentifiers.DsaWithSha256, NistObjectIdentifiers.IdSha256);
|
||||
m_digestOids.Add(NistObjectIdentifiers.DsaWithSha384, NistObjectIdentifiers.IdSha384);
|
||||
m_digestOids.Add(NistObjectIdentifiers.DsaWithSha512, NistObjectIdentifiers.IdSha512);
|
||||
|
||||
m_digestOids.Add(TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD128, TeleTrusTObjectIdentifiers.RipeMD128);
|
||||
m_digestOids.Add(TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD160, TeleTrusTObjectIdentifiers.RipeMD160);
|
||||
m_digestOids.Add(TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD256, TeleTrusTObjectIdentifiers.RipeMD256);
|
||||
|
||||
m_digestOids.Add(CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x94, CryptoProObjectIdentifiers.GostR3411);
|
||||
m_digestOids.Add(CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x2001, CryptoProObjectIdentifiers.GostR3411);
|
||||
|
||||
m_digestNameToOids.Add("SHA-1", OiwObjectIdentifiers.IdSha1);
|
||||
m_digestNameToOids.Add("SHA-224", NistObjectIdentifiers.IdSha224);
|
||||
m_digestNameToOids.Add("SHA-256", NistObjectIdentifiers.IdSha256);
|
||||
m_digestNameToOids.Add("SHA-384", NistObjectIdentifiers.IdSha384);
|
||||
m_digestNameToOids.Add("SHA-512", NistObjectIdentifiers.IdSha512);
|
||||
m_digestNameToOids.Add("SHA-512/224", NistObjectIdentifiers.IdSha512_224);
|
||||
m_digestNameToOids.Add("SHA-512(224)", NistObjectIdentifiers.IdSha512_224);
|
||||
m_digestNameToOids.Add("SHA-512/256", NistObjectIdentifiers.IdSha512_256);
|
||||
m_digestNameToOids.Add("SHA-512(256)", NistObjectIdentifiers.IdSha512_256);
|
||||
|
||||
m_digestNameToOids.Add("SHA1", OiwObjectIdentifiers.IdSha1);
|
||||
m_digestNameToOids.Add("SHA224", NistObjectIdentifiers.IdSha224);
|
||||
m_digestNameToOids.Add("SHA256", NistObjectIdentifiers.IdSha256);
|
||||
m_digestNameToOids.Add("SHA384", NistObjectIdentifiers.IdSha384);
|
||||
m_digestNameToOids.Add("SHA512", NistObjectIdentifiers.IdSha512);
|
||||
m_digestNameToOids.Add("SHA512/224", NistObjectIdentifiers.IdSha512_224);
|
||||
m_digestNameToOids.Add("SHA512(224)", NistObjectIdentifiers.IdSha512_224);
|
||||
m_digestNameToOids.Add("SHA512/256", NistObjectIdentifiers.IdSha512_256);
|
||||
m_digestNameToOids.Add("SHA512(256)", NistObjectIdentifiers.IdSha512_256);
|
||||
|
||||
m_digestNameToOids.Add("SHA3-224", NistObjectIdentifiers.IdSha3_224);
|
||||
m_digestNameToOids.Add("SHA3-256", NistObjectIdentifiers.IdSha3_256);
|
||||
m_digestNameToOids.Add("SHA3-384", NistObjectIdentifiers.IdSha3_384);
|
||||
m_digestNameToOids.Add("SHA3-512", NistObjectIdentifiers.IdSha3_512);
|
||||
|
||||
m_digestNameToOids.Add("SHAKE-128", NistObjectIdentifiers.IdShake128);
|
||||
m_digestNameToOids.Add("SHAKE-256", NistObjectIdentifiers.IdShake256);
|
||||
|
||||
m_digestNameToOids.Add("GOST3411", CryptoProObjectIdentifiers.GostR3411);
|
||||
|
||||
m_digestNameToOids.Add("MD2", PkcsObjectIdentifiers.MD2);
|
||||
m_digestNameToOids.Add("MD4", PkcsObjectIdentifiers.MD4);
|
||||
m_digestNameToOids.Add("MD5", PkcsObjectIdentifiers.MD5);
|
||||
|
||||
m_digestNameToOids.Add("RIPEMD128", TeleTrusTObjectIdentifiers.RipeMD128);
|
||||
m_digestNameToOids.Add("RIPEMD160", TeleTrusTObjectIdentifiers.RipeMD160);
|
||||
m_digestNameToOids.Add("RIPEMD256", TeleTrusTObjectIdentifiers.RipeMD256);
|
||||
}
|
||||
|
||||
public AlgorithmIdentifier Find(AlgorithmIdentifier sigAlgId)
|
||||
{
|
||||
AlgorithmIdentifier digAlgId;
|
||||
|
||||
if (sigAlgId.Algorithm.Equals(PkcsObjectIdentifiers.IdRsassaPss))
|
||||
{
|
||||
digAlgId = RsassaPssParameters.GetInstance(sigAlgId.Parameters).HashAlgorithm;
|
||||
}
|
||||
else
|
||||
{
|
||||
digAlgId = new AlgorithmIdentifier(m_digestOids[sigAlgId.Algorithm], DerNull.Instance);
|
||||
}
|
||||
|
||||
return digAlgId;
|
||||
}
|
||||
|
||||
public AlgorithmIdentifier Find(string digAlgName)
|
||||
{
|
||||
return new AlgorithmIdentifier(m_digestNameToOids[digAlgName], DerNull.Instance);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class CmsSignedGenerator
|
||||
{
|
||||
/**
|
||||
* Default type for the signed data.
|
||||
*/
|
||||
public static readonly string Data = CmsObjectIdentifiers.Data.Id;
|
||||
|
||||
public static readonly string DigestSha1 = OiwObjectIdentifiers.IdSha1.Id;
|
||||
public static readonly string DigestSha224 = NistObjectIdentifiers.IdSha224.Id;
|
||||
public static readonly string DigestSha256 = NistObjectIdentifiers.IdSha256.Id;
|
||||
public static readonly string DigestSha384 = NistObjectIdentifiers.IdSha384.Id;
|
||||
public static readonly string DigestSha512 = NistObjectIdentifiers.IdSha512.Id;
|
||||
public static readonly string DigestSha512_224 = NistObjectIdentifiers.IdSha512_224.Id;
|
||||
public static readonly string DigestSha512_256 = NistObjectIdentifiers.IdSha512_256.Id;
|
||||
public static readonly string DigestMD5 = PkcsObjectIdentifiers.MD5.Id;
|
||||
public static readonly string DigestGost3411 = CryptoProObjectIdentifiers.GostR3411.Id;
|
||||
public static readonly string DigestRipeMD128 = TeleTrusTObjectIdentifiers.RipeMD128.Id;
|
||||
public static readonly string DigestRipeMD160 = TeleTrusTObjectIdentifiers.RipeMD160.Id;
|
||||
public static readonly string DigestRipeMD256 = TeleTrusTObjectIdentifiers.RipeMD256.Id;
|
||||
|
||||
public static readonly string EncryptionRsa = PkcsObjectIdentifiers.RsaEncryption.Id;
|
||||
public static readonly string EncryptionDsa = X9ObjectIdentifiers.IdDsaWithSha1.Id;
|
||||
public static readonly string EncryptionECDsa = X9ObjectIdentifiers.ECDsaWithSha1.Id;
|
||||
public static readonly string EncryptionRsaPss = PkcsObjectIdentifiers.IdRsassaPss.Id;
|
||||
public static readonly string EncryptionGost3410 = CryptoProObjectIdentifiers.GostR3410x94.Id;
|
||||
public static readonly string EncryptionECGost3410 = CryptoProObjectIdentifiers.GostR3410x2001.Id;
|
||||
public static readonly string EncryptionECGost3410_2012_256 = RosstandartObjectIdentifiers.id_tc26_gost_3410_12_256.Id;
|
||||
public static readonly string EncryptionECGost3410_2012_512 = RosstandartObjectIdentifiers.id_tc26_gost_3410_12_512.Id;
|
||||
|
||||
internal List<Asn1Encodable> _certs = new List<Asn1Encodable>();
|
||||
internal List<Asn1Encodable> _crls = new List<Asn1Encodable>();
|
||||
internal IList<SignerInformation> _signers = new List<SignerInformation>();
|
||||
internal IDictionary<string, byte[]> m_digests =
|
||||
new Dictionary<string, byte[]>(StringComparer.OrdinalIgnoreCase);
|
||||
internal bool _useDerForCerts = false;
|
||||
internal bool _useDerForCrls = false;
|
||||
|
||||
protected readonly SecureRandom m_random;
|
||||
|
||||
protected CmsSignedGenerator()
|
||||
: this(CryptoServicesRegistrar.GetSecureRandom())
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>Constructor allowing specific source of randomness</summary>
|
||||
/// <param name="random">Instance of <c>SecureRandom</c> to use.</param>
|
||||
protected CmsSignedGenerator(SecureRandom random)
|
||||
{
|
||||
if (random == null)
|
||||
throw new ArgumentNullException(nameof(random));
|
||||
|
||||
m_random = random;
|
||||
}
|
||||
|
||||
internal protected virtual IDictionary<CmsAttributeTableParameter, object> GetBaseParameters(
|
||||
DerObjectIdentifier contentType, AlgorithmIdentifier digAlgId, byte[] hash)
|
||||
{
|
||||
var param = new Dictionary<CmsAttributeTableParameter, object>();
|
||||
|
||||
if (contentType != null)
|
||||
{
|
||||
param[CmsAttributeTableParameter.ContentType] = contentType;
|
||||
}
|
||||
|
||||
param[CmsAttributeTableParameter.DigestAlgorithmIdentifier] = digAlgId;
|
||||
param[CmsAttributeTableParameter.Digest] = hash.Clone();
|
||||
|
||||
return param;
|
||||
}
|
||||
|
||||
internal protected virtual Asn1Set GetAttributeSet(
|
||||
Asn1.Cms.AttributeTable attr)
|
||||
{
|
||||
return attr == null
|
||||
? null
|
||||
: new DerSet(attr.ToAsn1EncodableVector());
|
||||
}
|
||||
|
||||
public void AddAttributeCertificate(X509V2AttributeCertificate attrCert)
|
||||
{
|
||||
_certs.Add(new DerTaggedObject(false, 2, attrCert.AttributeCertificate));
|
||||
}
|
||||
|
||||
public void AddAttributeCertificates(IStore<X509V2AttributeCertificate> attrCertStore)
|
||||
{
|
||||
_certs.AddRange(CmsUtilities.GetAttributeCertificatesFromStore(attrCertStore));
|
||||
}
|
||||
|
||||
public void AddCertificate(X509Certificate cert)
|
||||
{
|
||||
_certs.Add(cert.CertificateStructure);
|
||||
}
|
||||
|
||||
public void AddCertificates(IStore<X509Certificate> certStore)
|
||||
{
|
||||
_certs.AddRange(CmsUtilities.GetCertificatesFromStore(certStore));
|
||||
}
|
||||
|
||||
public void AddCrl(X509Crl crl)
|
||||
{
|
||||
_crls.Add(crl.CertificateList);
|
||||
}
|
||||
|
||||
public void AddCrls(IStore<X509Crl> crlStore)
|
||||
{
|
||||
_crls.AddRange(CmsUtilities.GetCrlsFromStore(crlStore));
|
||||
}
|
||||
|
||||
public void AddOtherRevocationInfo(OtherRevocationInfoFormat otherRevocationInfo)
|
||||
{
|
||||
CmsUtilities.ValidateOtherRevocationInfo(otherRevocationInfo);
|
||||
_crls.Add(new DerTaggedObject(false, 1, otherRevocationInfo));
|
||||
}
|
||||
|
||||
public void AddOtherRevocationInfos(IStore<OtherRevocationInfoFormat> otherRevocationInfoStore)
|
||||
{
|
||||
_crls.AddRange(CmsUtilities.GetOtherRevocationInfosFromStore(otherRevocationInfoStore));
|
||||
}
|
||||
|
||||
public void AddOtherRevocationInfos(DerObjectIdentifier otherRevInfoFormat,
|
||||
IStore<Asn1Encodable> otherRevInfoStore)
|
||||
{
|
||||
_crls.AddRange(CmsUtilities.GetOtherRevocationInfosFromStore(otherRevInfoStore, otherRevInfoFormat));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a store of precalculated signers to the generator.
|
||||
*
|
||||
* @param signerStore store of signers
|
||||
*/
|
||||
public void AddSigners(SignerInformationStore signerStore)
|
||||
{
|
||||
foreach (SignerInformation o in signerStore.GetSigners())
|
||||
{
|
||||
_signers.Add(o);
|
||||
AddSignerCallback(o);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a map of oids and byte arrays representing the digests calculated on the content during
|
||||
* the last generate.
|
||||
*
|
||||
* @return a map of oids (as string objects) and byte[] representing digests.
|
||||
*/
|
||||
public IDictionary<string, byte[]> GetGeneratedDigests()
|
||||
{
|
||||
return new Dictionary<string, byte[]>(m_digests, StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
public bool UseDerForCerts
|
||||
{
|
||||
get { return _useDerForCerts; }
|
||||
set { this._useDerForCerts = value; }
|
||||
}
|
||||
|
||||
public bool UseDerForCrls
|
||||
{
|
||||
get { return _useDerForCrls; }
|
||||
set { this._useDerForCrls = value; }
|
||||
}
|
||||
|
||||
internal virtual void AddSignerCallback(
|
||||
SignerInformation si)
|
||||
{
|
||||
}
|
||||
|
||||
internal static SignerIdentifier GetSignerIdentifier(X509Certificate cert)
|
||||
{
|
||||
return new SignerIdentifier(CmsUtilities.GetIssuerAndSerialNumber(cert));
|
||||
}
|
||||
|
||||
internal static SignerIdentifier GetSignerIdentifier(byte[] subjectKeyIdentifier)
|
||||
{
|
||||
return new SignerIdentifier(new DerOctetString(subjectKeyIdentifier));
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 005c41845e2bb2c44b19515d790e39e7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,382 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Cms;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.CryptoPro;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Eac;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Esf;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Nist;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Oiw;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Pkcs;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Rosstandart;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.TeleTrust;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.X509;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.X9;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Security;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Collections;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.X509;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Cms
|
||||
{
|
||||
internal class CmsSignedHelper
|
||||
{
|
||||
internal static readonly CmsSignedHelper Instance = new CmsSignedHelper();
|
||||
|
||||
private static readonly string EncryptionECDsaWithSha1 = X9ObjectIdentifiers.ECDsaWithSha1.Id;
|
||||
private static readonly string EncryptionECDsaWithSha224 = X9ObjectIdentifiers.ECDsaWithSha224.Id;
|
||||
private static readonly string EncryptionECDsaWithSha256 = X9ObjectIdentifiers.ECDsaWithSha256.Id;
|
||||
private static readonly string EncryptionECDsaWithSha384 = X9ObjectIdentifiers.ECDsaWithSha384.Id;
|
||||
private static readonly string EncryptionECDsaWithSha512 = X9ObjectIdentifiers.ECDsaWithSha512.Id;
|
||||
|
||||
private static readonly IDictionary<string, string> m_encryptionAlgs = new Dictionary<string, string>();
|
||||
private static readonly IDictionary<string, string> m_digestAlgs = new Dictionary<string, string>();
|
||||
private static readonly IDictionary<string, string[]> m_digestAliases = new Dictionary<string, string[]>();
|
||||
|
||||
private static readonly HashSet<string> noParams = new HashSet<string>();
|
||||
private static readonly IDictionary<string, string> m_ecAlgorithms = new Dictionary<string, string>();
|
||||
|
||||
private static void AddEntries(DerObjectIdentifier oid, string digest, string encryption)
|
||||
{
|
||||
string alias = oid.Id;
|
||||
m_digestAlgs.Add(alias, digest);
|
||||
m_encryptionAlgs.Add(alias, encryption);
|
||||
}
|
||||
|
||||
static CmsSignedHelper()
|
||||
{
|
||||
AddEntries(NistObjectIdentifiers.DsaWithSha224, "SHA224", "DSA");
|
||||
AddEntries(NistObjectIdentifiers.DsaWithSha256, "SHA256", "DSA");
|
||||
AddEntries(NistObjectIdentifiers.DsaWithSha384, "SHA384", "DSA");
|
||||
AddEntries(NistObjectIdentifiers.DsaWithSha512, "SHA512", "DSA");
|
||||
AddEntries(OiwObjectIdentifiers.DsaWithSha1, "SHA1", "DSA");
|
||||
AddEntries(OiwObjectIdentifiers.MD4WithRsa, "MD4", "RSA");
|
||||
AddEntries(OiwObjectIdentifiers.MD4WithRsaEncryption, "MD4", "RSA");
|
||||
AddEntries(OiwObjectIdentifiers.MD5WithRsa, "MD5", "RSA");
|
||||
AddEntries(OiwObjectIdentifiers.Sha1WithRsa, "SHA1", "RSA");
|
||||
AddEntries(PkcsObjectIdentifiers.MD2WithRsaEncryption, "MD2", "RSA");
|
||||
AddEntries(PkcsObjectIdentifiers.MD4WithRsaEncryption, "MD4", "RSA");
|
||||
AddEntries(PkcsObjectIdentifiers.MD5WithRsaEncryption, "MD5", "RSA");
|
||||
AddEntries(PkcsObjectIdentifiers.Sha1WithRsaEncryption, "SHA1", "RSA");
|
||||
AddEntries(PkcsObjectIdentifiers.Sha224WithRsaEncryption, "SHA224", "RSA");
|
||||
AddEntries(PkcsObjectIdentifiers.Sha256WithRsaEncryption, "SHA256", "RSA");
|
||||
AddEntries(PkcsObjectIdentifiers.Sha384WithRsaEncryption, "SHA384", "RSA");
|
||||
AddEntries(PkcsObjectIdentifiers.Sha512WithRsaEncryption, "SHA512", "RSA");
|
||||
AddEntries(PkcsObjectIdentifiers.Sha512_224WithRSAEncryption, "SHA512(224)", "RSA");
|
||||
AddEntries(PkcsObjectIdentifiers.Sha512_256WithRSAEncryption, "SHA512(256)", "RSA");
|
||||
AddEntries(NistObjectIdentifiers.IdRsassaPkcs1V15WithSha3_224, "SHA3-224", "RSA");
|
||||
AddEntries(NistObjectIdentifiers.IdRsassaPkcs1V15WithSha3_256, "SHA3-256", "RSA");
|
||||
AddEntries(NistObjectIdentifiers.IdRsassaPkcs1V15WithSha3_384, "SHA3-384", "RSA");
|
||||
AddEntries(NistObjectIdentifiers.IdRsassaPkcs1V15WithSha3_512, "SHA3-512", "RSA");
|
||||
AddEntries(X9ObjectIdentifiers.ECDsaWithSha1, "SHA1", "ECDSA");
|
||||
AddEntries(X9ObjectIdentifiers.ECDsaWithSha224, "SHA224", "ECDSA");
|
||||
AddEntries(X9ObjectIdentifiers.ECDsaWithSha256, "SHA256", "ECDSA");
|
||||
AddEntries(X9ObjectIdentifiers.ECDsaWithSha384, "SHA384", "ECDSA");
|
||||
AddEntries(X9ObjectIdentifiers.ECDsaWithSha512, "SHA512", "ECDSA");
|
||||
AddEntries(X9ObjectIdentifiers.IdDsaWithSha1, "SHA1", "DSA");
|
||||
AddEntries(EacObjectIdentifiers.id_TA_ECDSA_SHA_1, "SHA1", "ECDSA");
|
||||
AddEntries(EacObjectIdentifiers.id_TA_ECDSA_SHA_224, "SHA224", "ECDSA");
|
||||
AddEntries(EacObjectIdentifiers.id_TA_ECDSA_SHA_256, "SHA256", "ECDSA");
|
||||
AddEntries(EacObjectIdentifiers.id_TA_ECDSA_SHA_384, "SHA384", "ECDSA");
|
||||
AddEntries(EacObjectIdentifiers.id_TA_ECDSA_SHA_512, "SHA512", "ECDSA");
|
||||
AddEntries(EacObjectIdentifiers.id_TA_RSA_v1_5_SHA_1, "SHA1", "RSA");
|
||||
AddEntries(EacObjectIdentifiers.id_TA_RSA_v1_5_SHA_256, "SHA256", "RSA");
|
||||
AddEntries(EacObjectIdentifiers.id_TA_RSA_PSS_SHA_1, "SHA1", "RSAandMGF1");
|
||||
AddEntries(EacObjectIdentifiers.id_TA_RSA_PSS_SHA_256, "SHA256", "RSAandMGF1");
|
||||
AddEntries(CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x94, "GOST3411", "GOST3410");
|
||||
AddEntries(CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x2001, "GOST3411", "ECGOST3410");
|
||||
AddEntries(RosstandartObjectIdentifiers.id_tc26_signwithdigest_gost_3410_12_256, "GOST3411-2012-256", "ECGOST3410");
|
||||
AddEntries(RosstandartObjectIdentifiers.id_tc26_signwithdigest_gost_3410_12_512, "GOST3411-2012-512", "ECGOST3410");
|
||||
|
||||
m_encryptionAlgs.Add(X9ObjectIdentifiers.IdDsa.Id, "DSA");
|
||||
m_encryptionAlgs.Add(PkcsObjectIdentifiers.RsaEncryption.Id, "RSA");
|
||||
m_encryptionAlgs.Add(TeleTrusTObjectIdentifiers.TeleTrusTRsaSignatureAlgorithm.Id, "RSA");
|
||||
m_encryptionAlgs.Add(X509ObjectIdentifiers.IdEARsa.Id, "RSA");
|
||||
m_encryptionAlgs.Add(CmsSignedGenerator.EncryptionRsaPss, "RSAandMGF1");
|
||||
m_encryptionAlgs.Add(CryptoProObjectIdentifiers.GostR3410x94.Id, "GOST3410");
|
||||
m_encryptionAlgs.Add(CryptoProObjectIdentifiers.GostR3410x2001.Id, "ECGOST3410");
|
||||
m_encryptionAlgs.Add(RosstandartObjectIdentifiers.id_tc26_gost_3410_12_256.Id, "ECGOST3410");
|
||||
m_encryptionAlgs.Add(RosstandartObjectIdentifiers.id_tc26_gost_3410_12_512.Id, "ECGOST3410");
|
||||
m_encryptionAlgs.Add("1.3.6.1.4.1.5849.1.6.2", "ECGOST3410");
|
||||
m_encryptionAlgs.Add("1.3.6.1.4.1.5849.1.1.5", "GOST3410");
|
||||
|
||||
m_digestAlgs.Add(PkcsObjectIdentifiers.MD2.Id, "MD2");
|
||||
m_digestAlgs.Add(PkcsObjectIdentifiers.MD4.Id, "MD4");
|
||||
m_digestAlgs.Add(PkcsObjectIdentifiers.MD5.Id, "MD5");
|
||||
m_digestAlgs.Add(OiwObjectIdentifiers.IdSha1.Id, "SHA1");
|
||||
m_digestAlgs.Add(NistObjectIdentifiers.IdSha224.Id, "SHA224");
|
||||
m_digestAlgs.Add(NistObjectIdentifiers.IdSha256.Id, "SHA256");
|
||||
m_digestAlgs.Add(NistObjectIdentifiers.IdSha384.Id, "SHA384");
|
||||
m_digestAlgs.Add(NistObjectIdentifiers.IdSha512.Id, "SHA512");
|
||||
m_digestAlgs.Add(NistObjectIdentifiers.IdSha512_224.Id, "SHA512(224)");
|
||||
m_digestAlgs.Add(NistObjectIdentifiers.IdSha512_256.Id, "SHA512(256)");
|
||||
m_digestAlgs.Add(NistObjectIdentifiers.IdSha3_224.Id, "SHA3-224");
|
||||
m_digestAlgs.Add(NistObjectIdentifiers.IdSha3_256.Id, "SHA3-256");
|
||||
m_digestAlgs.Add(NistObjectIdentifiers.IdSha3_384.Id, "SHA3-384");
|
||||
m_digestAlgs.Add(NistObjectIdentifiers.IdSha3_512.Id, "SHA3-512");
|
||||
m_digestAlgs.Add(TeleTrusTObjectIdentifiers.RipeMD128.Id, "RIPEMD128");
|
||||
m_digestAlgs.Add(TeleTrusTObjectIdentifiers.RipeMD160.Id, "RIPEMD160");
|
||||
m_digestAlgs.Add(TeleTrusTObjectIdentifiers.RipeMD256.Id, "RIPEMD256");
|
||||
m_digestAlgs.Add(CryptoProObjectIdentifiers.GostR3411.Id, "GOST3411");
|
||||
m_digestAlgs.Add("1.3.6.1.4.1.5849.1.2.1", "GOST3411");
|
||||
m_digestAlgs.Add(RosstandartObjectIdentifiers.id_tc26_gost_3411_12_256.Id, "GOST3411-2012-256");
|
||||
m_digestAlgs.Add(RosstandartObjectIdentifiers.id_tc26_gost_3411_12_512.Id, "GOST3411-2012-512");
|
||||
|
||||
m_digestAliases.Add("SHA1", new string[]{ "SHA-1" });
|
||||
m_digestAliases.Add("SHA224", new string[]{ "SHA-224" });
|
||||
m_digestAliases.Add("SHA256", new string[]{ "SHA-256" });
|
||||
m_digestAliases.Add("SHA384", new string[]{ "SHA-384" });
|
||||
m_digestAliases.Add("SHA512", new string[]{ "SHA-512" });
|
||||
|
||||
noParams.Add(CmsSignedGenerator.EncryptionDsa);
|
||||
//noParams.Add(EncryptionECDsa);
|
||||
noParams.Add(EncryptionECDsaWithSha1);
|
||||
noParams.Add(EncryptionECDsaWithSha224);
|
||||
noParams.Add(EncryptionECDsaWithSha256);
|
||||
noParams.Add(EncryptionECDsaWithSha384);
|
||||
noParams.Add(EncryptionECDsaWithSha512);
|
||||
|
||||
m_ecAlgorithms.Add(CmsSignedGenerator.DigestSha1, EncryptionECDsaWithSha1);
|
||||
m_ecAlgorithms.Add(CmsSignedGenerator.DigestSha224, EncryptionECDsaWithSha224);
|
||||
m_ecAlgorithms.Add(CmsSignedGenerator.DigestSha256, EncryptionECDsaWithSha256);
|
||||
m_ecAlgorithms.Add(CmsSignedGenerator.DigestSha384, EncryptionECDsaWithSha384);
|
||||
m_ecAlgorithms.Add(CmsSignedGenerator.DigestSha512, EncryptionECDsaWithSha512);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the digest algorithm using one of the standard JCA string
|
||||
* representations rather than the algorithm identifier (if possible).
|
||||
*/
|
||||
internal string GetDigestAlgName(string digestAlgOid)
|
||||
{
|
||||
return m_digestAlgs.TryGetValue(digestAlgOid, out var algName) ? algName : digestAlgOid;
|
||||
}
|
||||
|
||||
internal AlgorithmIdentifier GetEncAlgorithmIdentifier(DerObjectIdentifier encOid,
|
||||
Asn1Encodable sigX509Parameters)
|
||||
{
|
||||
if (noParams.Contains(encOid.Id))
|
||||
{
|
||||
return new AlgorithmIdentifier(encOid);
|
||||
}
|
||||
|
||||
return new AlgorithmIdentifier(encOid, sigX509Parameters);
|
||||
}
|
||||
|
||||
internal string[] GetDigestAliases(string algName)
|
||||
{
|
||||
return m_digestAliases.TryGetValue(algName, out var aliases) ? (string[])aliases.Clone() : new string[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the digest encryption algorithm using one of the standard
|
||||
* JCA string representations rather than the algorithm identifier (if
|
||||
* possible).
|
||||
*/
|
||||
internal string GetEncryptionAlgName(string encryptionAlgOid)
|
||||
{
|
||||
return m_encryptionAlgs.TryGetValue(encryptionAlgOid, out var algName) ? algName : encryptionAlgOid;
|
||||
}
|
||||
|
||||
internal IDigest GetDigestInstance(
|
||||
string algorithm)
|
||||
{
|
||||
try
|
||||
{
|
||||
return DigestUtilities.GetDigest(algorithm);
|
||||
}
|
||||
catch (SecurityUtilityException e)
|
||||
{
|
||||
// This is probably superfluous on C#, since no provider infrastructure,
|
||||
// assuming DigestUtilities already knows all the aliases
|
||||
foreach (string alias in GetDigestAliases(algorithm))
|
||||
{
|
||||
try { return DigestUtilities.GetDigest(alias); }
|
||||
catch (SecurityUtilityException) {}
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
internal ISigner GetSignatureInstance(
|
||||
string algorithm)
|
||||
{
|
||||
return SignerUtilities.GetSigner(algorithm);
|
||||
}
|
||||
|
||||
internal AlgorithmIdentifier FixAlgID(
|
||||
AlgorithmIdentifier algId)
|
||||
{
|
||||
if (algId.Parameters == null)
|
||||
return new AlgorithmIdentifier(algId.Algorithm, DerNull.Instance);
|
||||
|
||||
return algId;
|
||||
}
|
||||
|
||||
internal string GetEncOid(
|
||||
AsymmetricKeyParameter key,
|
||||
string digestOID)
|
||||
{
|
||||
string encOID = null;
|
||||
|
||||
if (key is RsaKeyParameters rsaKeyParameters)
|
||||
{
|
||||
if (!rsaKeyParameters.IsPrivate)
|
||||
throw new ArgumentException("Expected RSA private key");
|
||||
|
||||
encOID = CmsSignedGenerator.EncryptionRsa;
|
||||
}
|
||||
else if (key is DsaPrivateKeyParameters)
|
||||
{
|
||||
if (digestOID.Equals(CmsSignedGenerator.DigestSha1))
|
||||
{
|
||||
encOID = CmsSignedGenerator.EncryptionDsa;
|
||||
}
|
||||
else if (digestOID.Equals(CmsSignedGenerator.DigestSha224))
|
||||
{
|
||||
encOID = NistObjectIdentifiers.DsaWithSha224.Id;
|
||||
}
|
||||
else if (digestOID.Equals(CmsSignedGenerator.DigestSha256))
|
||||
{
|
||||
encOID = NistObjectIdentifiers.DsaWithSha256.Id;
|
||||
}
|
||||
else if (digestOID.Equals(CmsSignedGenerator.DigestSha384))
|
||||
{
|
||||
encOID = NistObjectIdentifiers.DsaWithSha384.Id;
|
||||
}
|
||||
else if (digestOID.Equals(CmsSignedGenerator.DigestSha512))
|
||||
{
|
||||
encOID = NistObjectIdentifiers.DsaWithSha512.Id;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException("can't mix DSA with anything but SHA1/SHA2");
|
||||
}
|
||||
}
|
||||
else if (key is ECPrivateKeyParameters ecPrivKey)
|
||||
{
|
||||
string algName = ecPrivKey.AlgorithmName;
|
||||
|
||||
if (algName == "ECGOST3410")
|
||||
{
|
||||
encOID = CmsSignedGenerator.EncryptionECGost3410;
|
||||
}
|
||||
else if (ecPrivKey.Parameters is ECGost3410Parameters ecGost3410Parameters)
|
||||
{
|
||||
var digestParamSet = ecGost3410Parameters.DigestParamSet;
|
||||
if (digestParamSet.Equals(RosstandartObjectIdentifiers.id_tc26_gost_3411_12_256))
|
||||
{
|
||||
encOID = CmsSignedGenerator.EncryptionECGost3410_2012_256;
|
||||
}
|
||||
else if (digestParamSet.Equals(RosstandartObjectIdentifiers.id_tc26_gost_3411_12_512))
|
||||
{
|
||||
encOID = CmsSignedGenerator.EncryptionECGost3410_2012_512;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException("can't determine GOST3410 algorithm");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO Should we insist on algName being one of "EC" or "ECDSA", as Java does?
|
||||
if (!m_ecAlgorithms.TryGetValue(digestOID, out encOID))
|
||||
throw new ArgumentException("can't mix ECDSA with anything but SHA family digests");
|
||||
}
|
||||
}
|
||||
else if (key is Gost3410PrivateKeyParameters)
|
||||
{
|
||||
encOID = CmsSignedGenerator.EncryptionGost3410;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException("Unknown algorithm in CmsSignedGenerator.GetEncOid");
|
||||
}
|
||||
|
||||
return encOID;
|
||||
}
|
||||
|
||||
internal IStore<X509V2AttributeCertificate> GetAttributeCertificates(Asn1Set attrCertSet)
|
||||
{
|
||||
var contents = new List<X509V2AttributeCertificate>();
|
||||
if (attrCertSet != null)
|
||||
{
|
||||
foreach (Asn1Encodable ae in attrCertSet)
|
||||
{
|
||||
if (ae != null && ae.ToAsn1Object() is Asn1TaggedObject t)
|
||||
{
|
||||
if (t.HasContextTag(2))
|
||||
{
|
||||
Asn1Sequence s = Asn1Sequence.GetInstance(t, false);
|
||||
|
||||
contents.Add(new X509V2AttributeCertificate(AttributeCertificate.GetInstance(s)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return CollectionUtilities.CreateStore(contents);
|
||||
}
|
||||
|
||||
internal IStore<X509Certificate> GetCertificates(Asn1Set certSet)
|
||||
{
|
||||
var contents = new List<X509Certificate>();
|
||||
if (certSet != null)
|
||||
{
|
||||
foreach (Asn1Encodable ae in certSet)
|
||||
{
|
||||
if (ae != null && ae.ToAsn1Object() is Asn1Sequence s)
|
||||
{
|
||||
contents.Add(new X509Certificate(X509CertificateStructure.GetInstance(s)));
|
||||
}
|
||||
}
|
||||
}
|
||||
return CollectionUtilities.CreateStore(contents);
|
||||
}
|
||||
|
||||
internal IStore<X509Crl> GetCrls(Asn1Set crlSet)
|
||||
{
|
||||
var contents = new List<X509Crl>();
|
||||
if (crlSet != null)
|
||||
{
|
||||
foreach (Asn1Encodable ae in crlSet)
|
||||
{
|
||||
if (ae != null && ae.ToAsn1Object() is Asn1Sequence s)
|
||||
{
|
||||
contents.Add(new X509Crl(CertificateList.GetInstance(s)));
|
||||
}
|
||||
}
|
||||
}
|
||||
return CollectionUtilities.CreateStore(contents);
|
||||
}
|
||||
|
||||
internal IStore<Asn1Encodable> GetOtherRevInfos(Asn1Set crlSet, DerObjectIdentifier otherRevInfoFormat)
|
||||
{
|
||||
var contents = new List<Asn1Encodable>();
|
||||
if (crlSet != null && otherRevInfoFormat != null)
|
||||
{
|
||||
foreach (Asn1Encodable ae in crlSet)
|
||||
{
|
||||
if (ae != null && ae.ToAsn1Object() is Asn1TaggedObject taggedObject)
|
||||
{
|
||||
if (taggedObject.HasContextTag(1))
|
||||
{
|
||||
var otherRevocationInfo = OtherRevocationInfoFormat.GetInstance(taggedObject, false);
|
||||
|
||||
if (otherRevInfoFormat.Equals(otherRevocationInfo.InfoFormat))
|
||||
{
|
||||
contents.Add(otherRevocationInfo.Info);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return CollectionUtilities.CreateStore(contents);
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f0f0baf6a26286f41b9a981fa79313a2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,35 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Cms
|
||||
{
|
||||
[Serializable]
|
||||
public class CmsStreamException
|
||||
: IOException
|
||||
{
|
||||
public CmsStreamException()
|
||||
: base()
|
||||
{
|
||||
}
|
||||
|
||||
public CmsStreamException(string message)
|
||||
: base(message)
|
||||
{
|
||||
}
|
||||
|
||||
public CmsStreamException(string message, Exception innerException)
|
||||
: base(message, innerException)
|
||||
{
|
||||
}
|
||||
|
||||
protected CmsStreamException(SerializationInfo info, StreamingContext context)
|
||||
: base(info, context)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 65c03251f868f0c4eacde295bcfa8a55
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,79 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Pkcs;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.IO;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Cms
|
||||
{
|
||||
public class CmsTypedStream
|
||||
{
|
||||
private const int BufferSize = 32 * 1024;
|
||||
|
||||
private readonly string _oid;
|
||||
private readonly Stream _in;
|
||||
|
||||
public CmsTypedStream(
|
||||
Stream inStream)
|
||||
: this(PkcsObjectIdentifiers.Data.Id, inStream, BufferSize)
|
||||
{
|
||||
}
|
||||
|
||||
public CmsTypedStream(
|
||||
string oid,
|
||||
Stream inStream)
|
||||
: this(oid, inStream, BufferSize)
|
||||
{
|
||||
}
|
||||
|
||||
public CmsTypedStream(
|
||||
string oid,
|
||||
Stream inStream,
|
||||
int bufSize)
|
||||
{
|
||||
_oid = oid;
|
||||
_in = new FullReaderStream(new BufferedStream(inStream, bufSize));
|
||||
}
|
||||
|
||||
public string ContentType
|
||||
{
|
||||
get { return _oid; }
|
||||
}
|
||||
|
||||
public Stream ContentStream
|
||||
{
|
||||
get { return _in; }
|
||||
}
|
||||
|
||||
public void Drain()
|
||||
{
|
||||
Streams.Drain(_in);
|
||||
_in.Dispose();
|
||||
}
|
||||
|
||||
private class FullReaderStream : FilterStream
|
||||
{
|
||||
internal FullReaderStream(Stream input)
|
||||
: base(input)
|
||||
{
|
||||
}
|
||||
|
||||
public override int Read(byte[] buf, int off, int len)
|
||||
{
|
||||
return Streams.ReadFully(s, buf, off, len);
|
||||
}
|
||||
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || _UNITY_2021_2_OR_NEWER_
|
||||
public override int Read(Span<byte> buffer)
|
||||
{
|
||||
return Streams.ReadFully(s, buffer);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7cb2eb2d53bfddc48ada720945f16136
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,211 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Cms;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Ocsp;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.X509;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Collections;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.IO;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.X509;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Cms
|
||||
{
|
||||
internal class CmsUtilities
|
||||
{
|
||||
// TODO Is there a .NET equivalent to this?
|
||||
// private static readonly Runtime RUNTIME = Runtime.getRuntime();
|
||||
|
||||
internal static int MaximumMemory
|
||||
{
|
||||
get
|
||||
{
|
||||
// TODO Is there a .NET equivalent to this?
|
||||
long maxMem = int.MaxValue;//RUNTIME.maxMemory();
|
||||
|
||||
if (maxMem > int.MaxValue)
|
||||
{
|
||||
return int.MaxValue;
|
||||
}
|
||||
|
||||
return (int)maxMem;
|
||||
}
|
||||
}
|
||||
|
||||
internal static ContentInfo ReadContentInfo(
|
||||
byte[] input)
|
||||
{
|
||||
// enforce limit checking as from a byte array
|
||||
return ReadContentInfo(new Asn1InputStream(input));
|
||||
}
|
||||
|
||||
internal static ContentInfo ReadContentInfo(
|
||||
Stream input)
|
||||
{
|
||||
// enforce some limit checking
|
||||
return ReadContentInfo(new Asn1InputStream(input, MaximumMemory));
|
||||
}
|
||||
|
||||
private static ContentInfo ReadContentInfo(
|
||||
Asn1InputStream aIn)
|
||||
{
|
||||
try
|
||||
{
|
||||
return ContentInfo.GetInstance(aIn.ReadObject());
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new CmsException("IOException reading content.", e);
|
||||
}
|
||||
catch (InvalidCastException e)
|
||||
{
|
||||
throw new CmsException("Malformed content.", e);
|
||||
}
|
||||
catch (ArgumentException e)
|
||||
{
|
||||
throw new CmsException("Malformed content.", e);
|
||||
}
|
||||
}
|
||||
|
||||
internal static byte[] StreamToByteArray(Stream inStream)
|
||||
{
|
||||
return Streams.ReadAll(inStream);
|
||||
}
|
||||
|
||||
internal static byte[] StreamToByteArray(Stream inStream, int limit)
|
||||
{
|
||||
return Streams.ReadAllLimited(inStream, limit);
|
||||
}
|
||||
|
||||
internal static List<Asn1TaggedObject> GetAttributeCertificatesFromStore(
|
||||
IStore<X509V2AttributeCertificate> attrCertStore)
|
||||
{
|
||||
var result = new List<Asn1TaggedObject>();
|
||||
if (attrCertStore != null)
|
||||
{
|
||||
foreach (var attrCert in attrCertStore.EnumerateMatches(null))
|
||||
{
|
||||
result.Add(new DerTaggedObject(false, 2, attrCert.AttributeCertificate));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal static List<X509CertificateStructure> GetCertificatesFromStore(IStore<X509Certificate> certStore)
|
||||
{
|
||||
var result = new List<X509CertificateStructure>();
|
||||
if (certStore != null)
|
||||
{
|
||||
foreach (var cert in certStore.EnumerateMatches(null))
|
||||
{
|
||||
result.Add(cert.CertificateStructure);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal static List<CertificateList> GetCrlsFromStore(IStore<X509Crl> crlStore)
|
||||
{
|
||||
var result = new List<CertificateList>();
|
||||
if (crlStore != null)
|
||||
{
|
||||
foreach (var crl in crlStore.EnumerateMatches(null))
|
||||
{
|
||||
result.Add(crl.CertificateList);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal static List<Asn1TaggedObject> GetOtherRevocationInfosFromStore(
|
||||
IStore<OtherRevocationInfoFormat> otherRevocationInfoStore)
|
||||
{
|
||||
var result = new List<Asn1TaggedObject>();
|
||||
if (otherRevocationInfoStore != null)
|
||||
{
|
||||
foreach (var otherRevocationInfo in otherRevocationInfoStore.EnumerateMatches(null))
|
||||
{
|
||||
ValidateOtherRevocationInfo(otherRevocationInfo);
|
||||
|
||||
result.Add(new DerTaggedObject(false, 1, otherRevocationInfo));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal static List<DerTaggedObject> GetOtherRevocationInfosFromStore(IStore<Asn1Encodable> otherRevInfoStore,
|
||||
DerObjectIdentifier otherRevInfoFormat)
|
||||
{
|
||||
var result = new List<DerTaggedObject>();
|
||||
if (otherRevInfoStore != null && otherRevInfoFormat != null)
|
||||
{
|
||||
foreach (var otherRevInfo in otherRevInfoStore.EnumerateMatches(null))
|
||||
{
|
||||
var otherRevocationInfo = new OtherRevocationInfoFormat(otherRevInfoFormat, otherRevInfo);
|
||||
|
||||
ValidateOtherRevocationInfo(otherRevocationInfo);
|
||||
|
||||
result.Add(new DerTaggedObject(false, 1, otherRevocationInfo));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal static Asn1Set CreateBerSetFromList(IEnumerable<Asn1Encodable> elements)
|
||||
{
|
||||
Asn1EncodableVector v = new Asn1EncodableVector();
|
||||
|
||||
foreach (Asn1Encodable element in elements)
|
||||
{
|
||||
v.Add(element);
|
||||
}
|
||||
|
||||
return new BerSet(v);
|
||||
}
|
||||
|
||||
internal static Asn1Set CreateDerSetFromList(IEnumerable<Asn1Encodable> elements)
|
||||
{
|
||||
Asn1EncodableVector v = new Asn1EncodableVector();
|
||||
|
||||
foreach (Asn1Encodable element in elements)
|
||||
{
|
||||
v.Add(element);
|
||||
}
|
||||
|
||||
return new DerSet(v);
|
||||
}
|
||||
|
||||
internal static Stream CreateBerOctetOutputStream(Stream s, int tagNo, bool isExplicit, int bufferSize)
|
||||
{
|
||||
BerOctetStringGenerator octGen = new BerOctetStringGenerator(s, tagNo, isExplicit);
|
||||
return octGen.GetOctetOutputStream(bufferSize);
|
||||
}
|
||||
|
||||
internal static TbsCertificateStructure GetTbsCertificateStructure(X509Certificate cert)
|
||||
{
|
||||
return TbsCertificateStructure.GetInstance(Asn1Object.FromByteArray(cert.GetTbsCertificate()));
|
||||
}
|
||||
|
||||
internal static IssuerAndSerialNumber GetIssuerAndSerialNumber(X509Certificate cert)
|
||||
{
|
||||
TbsCertificateStructure tbsCert = GetTbsCertificateStructure(cert);
|
||||
return new IssuerAndSerialNumber(tbsCert.Issuer, tbsCert.SerialNumber.Value);
|
||||
}
|
||||
|
||||
internal static void ValidateOtherRevocationInfo(OtherRevocationInfoFormat otherRevocationInfo)
|
||||
{
|
||||
if (CmsObjectIdentifiers.id_ri_ocsp_response.Equals(otherRevocationInfo.InfoFormat))
|
||||
{
|
||||
OcspResponse ocspResponse = OcspResponse.GetInstance(otherRevocationInfo.Info);
|
||||
|
||||
if (OcspResponseStatus.Successful != ocspResponse.ResponseStatus.IntValueExact)
|
||||
throw new ArgumentException("cannot add unsuccessful OCSP response to CMS SignedData");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 67354a24f57564445b672cc8ecb0d55a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,32 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Security;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Cms
|
||||
{
|
||||
internal class CounterSignatureDigestCalculator
|
||||
: IDigestCalculator
|
||||
{
|
||||
private readonly string alg;
|
||||
private readonly byte[] data;
|
||||
|
||||
internal CounterSignatureDigestCalculator(
|
||||
string alg,
|
||||
byte[] data)
|
||||
{
|
||||
this.alg = alg;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public byte[] GetDigest()
|
||||
{
|
||||
IDigest digest = CmsSignedHelper.Instance.GetDigestInstance(alg);
|
||||
return DigestUtilities.DoFinal(digest, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0dc404fbdaec35e45ba416368a1f3d44
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,92 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Cms;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Cms
|
||||
{
|
||||
/**
|
||||
* Default authenticated attributes generator.
|
||||
*/
|
||||
public class DefaultAuthenticatedAttributeTableGenerator
|
||||
: CmsAttributeTableGenerator
|
||||
{
|
||||
private readonly IDictionary<DerObjectIdentifier, object> m_table;
|
||||
|
||||
/**
|
||||
* Initialise to use all defaults
|
||||
*/
|
||||
public DefaultAuthenticatedAttributeTableGenerator()
|
||||
{
|
||||
m_table = new Dictionary<DerObjectIdentifier, object>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise with some extra attributes or overrides.
|
||||
*
|
||||
* @param attributeTable initial attribute table to use.
|
||||
*/
|
||||
public DefaultAuthenticatedAttributeTableGenerator(
|
||||
AttributeTable attributeTable)
|
||||
{
|
||||
if (attributeTable != null)
|
||||
{
|
||||
m_table = attributeTable.ToDictionary();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_table = new Dictionary<DerObjectIdentifier, object>();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a standard attribute table from the passed in parameters - this will
|
||||
* normally include contentType and messageDigest. If the constructor
|
||||
* using an AttributeTable was used, entries in it for contentType and
|
||||
* messageDigest will override the generated ones.
|
||||
*
|
||||
* @param parameters source parameters for table generation.
|
||||
*
|
||||
* @return a filled in IDictionary of attributes.
|
||||
*/
|
||||
protected virtual IDictionary<DerObjectIdentifier, object> CreateStandardAttributeTable(
|
||||
IDictionary<CmsAttributeTableParameter, object> parameters)
|
||||
{
|
||||
var std = new Dictionary<DerObjectIdentifier, object>(m_table);
|
||||
|
||||
if (!std.ContainsKey(CmsAttributes.ContentType))
|
||||
{
|
||||
DerObjectIdentifier contentType = (DerObjectIdentifier)
|
||||
parameters[CmsAttributeTableParameter.ContentType];
|
||||
Asn1.Cms.Attribute attr = new Asn1.Cms.Attribute(CmsAttributes.ContentType,
|
||||
new DerSet(contentType));
|
||||
std[attr.AttrType] = attr;
|
||||
}
|
||||
|
||||
if (!std.ContainsKey(CmsAttributes.MessageDigest))
|
||||
{
|
||||
byte[] messageDigest = (byte[])parameters[CmsAttributeTableParameter.Digest];
|
||||
Asn1.Cms.Attribute attr = new Asn1.Cms.Attribute(CmsAttributes.MessageDigest,
|
||||
new DerSet(new DerOctetString(messageDigest)));
|
||||
std[attr.AttrType] = attr;
|
||||
}
|
||||
|
||||
return std;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param parameters source parameters
|
||||
* @return the populated attribute table
|
||||
*/
|
||||
public virtual AttributeTable GetAttributes(IDictionary<CmsAttributeTableParameter, object> parameters)
|
||||
{
|
||||
var table = CreateStandardAttributeTable(parameters);
|
||||
return new AttributeTable(table);
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0ff46025627cc3f4db1238e4c51595a1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,107 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Cms;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Cms
|
||||
{
|
||||
/**
|
||||
* Default signed attributes generator.
|
||||
*/
|
||||
public class DefaultSignedAttributeTableGenerator
|
||||
: CmsAttributeTableGenerator
|
||||
{
|
||||
private readonly IDictionary<DerObjectIdentifier, object> m_table;
|
||||
|
||||
/**
|
||||
* Initialise to use all defaults
|
||||
*/
|
||||
public DefaultSignedAttributeTableGenerator()
|
||||
{
|
||||
m_table = new Dictionary<DerObjectIdentifier, object>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise with some extra attributes or overrides.
|
||||
*
|
||||
* @param attributeTable initial attribute table to use.
|
||||
*/
|
||||
public DefaultSignedAttributeTableGenerator(AttributeTable attributeTable)
|
||||
{
|
||||
if (attributeTable != null)
|
||||
{
|
||||
m_table = attributeTable.ToDictionary();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_table = new Dictionary<DerObjectIdentifier, object>();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a standard attribute table from the passed in parameters - this will
|
||||
* normally include contentType, signingTime, and messageDigest. If the constructor
|
||||
* using an AttributeTable was used, entries in it for contentType, signingTime, and
|
||||
* messageDigest will override the generated ones.
|
||||
*
|
||||
* @param parameters source parameters for table generation.
|
||||
*
|
||||
* @return a filled in Dictionary of attributes.
|
||||
*/
|
||||
protected virtual IDictionary<DerObjectIdentifier, object> CreateStandardAttributeTable(
|
||||
IDictionary<CmsAttributeTableParameter, object> parameters)
|
||||
{
|
||||
var std = new Dictionary<DerObjectIdentifier, object>(m_table);
|
||||
DoCreateStandardAttributeTable(parameters, std);
|
||||
return std;
|
||||
}
|
||||
|
||||
private void DoCreateStandardAttributeTable(IDictionary<CmsAttributeTableParameter, object> parameters,
|
||||
IDictionary<DerObjectIdentifier, object> std)
|
||||
{
|
||||
// contentType will be absent if we're trying to generate a counter signature.
|
||||
|
||||
if (parameters.ContainsKey(CmsAttributeTableParameter.ContentType))
|
||||
{
|
||||
if (!std.ContainsKey(CmsAttributes.ContentType))
|
||||
{
|
||||
DerObjectIdentifier contentType = (DerObjectIdentifier)
|
||||
parameters[CmsAttributeTableParameter.ContentType];
|
||||
Asn1.Cms.Attribute attr = new Asn1.Cms.Attribute(CmsAttributes.ContentType,
|
||||
new DerSet(contentType));
|
||||
std[attr.AttrType] = attr;
|
||||
}
|
||||
}
|
||||
|
||||
if (!std.ContainsKey(CmsAttributes.SigningTime))
|
||||
{
|
||||
Asn1.Cms.Attribute attr = new Asn1.Cms.Attribute(CmsAttributes.SigningTime,
|
||||
new DerSet(new Time(DateTime.UtcNow)));
|
||||
std[attr.AttrType] = attr;
|
||||
}
|
||||
|
||||
if (!std.ContainsKey(CmsAttributes.MessageDigest))
|
||||
{
|
||||
byte[] messageDigest = (byte[])parameters[CmsAttributeTableParameter.Digest];
|
||||
Asn1.Cms.Attribute attr = new Asn1.Cms.Attribute(CmsAttributes.MessageDigest,
|
||||
new DerSet(new DerOctetString(messageDigest)));
|
||||
std[attr.AttrType] = attr;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param parameters source parameters
|
||||
* @return the populated attribute table
|
||||
*/
|
||||
public virtual AttributeTable GetAttributes(IDictionary<CmsAttributeTableParameter, object> parameters)
|
||||
{
|
||||
var table = CreateStandardAttributeTable(parameters);
|
||||
return new AttributeTable(table);
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0436e2d77a8dae845a14d9535027953c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,94 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.X509;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Utilities;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Security;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Cms
|
||||
{
|
||||
internal class EnvelopedDataHelper
|
||||
{
|
||||
//private static readonly IDictionary<DerObjectIdentifier, string> BaseCipherNames =
|
||||
// new Dictionary<DerObjectIdentifier, string>();
|
||||
//private static readonly IDictionary<DerObjectIdentifier, string> MacAlgNames =
|
||||
// new Dictionary<DerObjectIdentifier, string>();
|
||||
//private static readonly IDictionary<DerObjectIdentifier, string> PrfDigests =
|
||||
// new Dictionary<DerObjectIdentifier, string>();
|
||||
|
||||
//static EnvelopedDataHelper()
|
||||
//{
|
||||
// PrfDigests.Add(PkcsObjectIdentifiers.IdHmacWithSha1, "SHA-1");
|
||||
// PrfDigests.Add(PkcsObjectIdentifiers.IdHmacWithSha224, "SHA-224");
|
||||
// PrfDigests.Add(PkcsObjectIdentifiers.IdHmacWithSha256, "SHA-256");
|
||||
// PrfDigests.Add(PkcsObjectIdentifiers.IdHmacWithSha384, "SHA-384");
|
||||
// PrfDigests.Add(PkcsObjectIdentifiers.IdHmacWithSha512, "SHA-512");
|
||||
|
||||
// BaseCipherNames.Add(PkcsObjectIdentifiers.DesEde3Cbc, "DESEDE");
|
||||
// BaseCipherNames.Add(NistObjectIdentifiers.IdAes128Cbc, "AES");
|
||||
// BaseCipherNames.Add(NistObjectIdentifiers.IdAes192Cbc, "AES");
|
||||
// BaseCipherNames.Add(NistObjectIdentifiers.IdAes256Cbc, "AES");
|
||||
|
||||
// MacAlgNames.Add(PkcsObjectIdentifiers.DesEde3Cbc, "DESEDEMac");
|
||||
// MacAlgNames.Add(NistObjectIdentifiers.IdAes128Cbc, "AESMac");
|
||||
// MacAlgNames.Add(NistObjectIdentifiers.IdAes192Cbc, "AESMac");
|
||||
// MacAlgNames.Add(NistObjectIdentifiers.IdAes256Cbc, "AESMac");
|
||||
// MacAlgNames.Add(PkcsObjectIdentifiers.RC2Cbc, "RC2Mac");
|
||||
//}
|
||||
|
||||
//internal static IDigest GetPrf(AlgorithmIdentifier algID)
|
||||
//{
|
||||
// string digestName = (string)PrfDigests[algID];
|
||||
|
||||
// return DigestUtilities.GetDigest(digestName);
|
||||
//}
|
||||
|
||||
//internal static IWrapper CreateRfc3211Wrapper(DerObjectIdentifier algorithm)
|
||||
//{
|
||||
// if (NistObjectIdentifiers.IdAes128Cbc.Equals(algorithm)
|
||||
// || NistObjectIdentifiers.IdAes192Cbc.Equals(algorithm)
|
||||
// || NistObjectIdentifiers.IdAes256Cbc.Equals(algorithm))
|
||||
// {
|
||||
// return new Rfc3211WrapEngine(AesUtilities.CreateEngine());
|
||||
// }
|
||||
// else if (PkcsObjectIdentifiers.DesEde3Cbc.Equals(algorithm))
|
||||
// {
|
||||
// return new Rfc3211WrapEngine(new DesEdeEngine());
|
||||
// }
|
||||
// else if (OiwObjectIdentifiers.DesCbc.Equals(algorithm))
|
||||
// {
|
||||
// return new Rfc3211WrapEngine(new DesEngine());
|
||||
// }
|
||||
// else if (PkcsObjectIdentifiers.RC2Cbc.Equals(algorithm))
|
||||
// {
|
||||
// return new Rfc3211WrapEngine(new RC2Engine());
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// throw new CmsException("cannot recognise wrapper: " + algorithm);
|
||||
// }
|
||||
//}
|
||||
|
||||
public static object CreateContentCipher(bool forEncryption, ICipherParameters encKey,
|
||||
AlgorithmIdentifier encryptionAlgID)
|
||||
{
|
||||
return CipherFactory.CreateContentCipher(forEncryption, encKey, encryptionAlgID);
|
||||
}
|
||||
|
||||
public AlgorithmIdentifier GenerateEncryptionAlgID(DerObjectIdentifier encryptionOID, KeyParameter encKey,
|
||||
SecureRandom random)
|
||||
{
|
||||
return AlgorithmIdentifierFactory.GenerateEncryptionAlgID(encryptionOID, encKey.GetKey().Length * 8, random);
|
||||
}
|
||||
|
||||
public CipherKeyGenerator CreateKeyGenerator(DerObjectIdentifier algorithm, SecureRandom random)
|
||||
{
|
||||
return CipherKeyGeneratorFactory.CreateKeyGenerator(algorithm, random);
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c8039bbad55ce4b46bd7fc355bbab885
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,13 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Cms
|
||||
{
|
||||
internal interface IDigestCalculator
|
||||
{
|
||||
byte[] GetDigest();
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5d9dc3e4ade64ee40b172d9d67f0830c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,142 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Cms;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Kisa;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Nist;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Ntt;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Pkcs;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.X509;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Security;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Cms
|
||||
{
|
||||
internal class KekRecipientInfoGenerator : RecipientInfoGenerator
|
||||
{
|
||||
private static readonly CmsEnvelopedHelper Helper = CmsEnvelopedHelper.Instance;
|
||||
|
||||
private KeyParameter keyEncryptionKey;
|
||||
// TODO Can get this from keyEncryptionKey?
|
||||
private string keyEncryptionKeyOID;
|
||||
private KekIdentifier kekIdentifier;
|
||||
|
||||
// Derived
|
||||
private AlgorithmIdentifier keyEncryptionAlgorithm;
|
||||
|
||||
internal KekRecipientInfoGenerator()
|
||||
{
|
||||
}
|
||||
|
||||
internal KekIdentifier KekIdentifier
|
||||
{
|
||||
set { this.kekIdentifier = value; }
|
||||
}
|
||||
|
||||
internal KeyParameter KeyEncryptionKey
|
||||
{
|
||||
set
|
||||
{
|
||||
this.keyEncryptionKey = value;
|
||||
this.keyEncryptionAlgorithm = DetermineKeyEncAlg(keyEncryptionKeyOID, keyEncryptionKey);
|
||||
}
|
||||
}
|
||||
|
||||
internal string KeyEncryptionKeyOID
|
||||
{
|
||||
set { this.keyEncryptionKeyOID = value; }
|
||||
}
|
||||
|
||||
public RecipientInfo Generate(KeyParameter contentEncryptionKey, SecureRandom random)
|
||||
{
|
||||
byte[] keyBytes = contentEncryptionKey.GetKey();
|
||||
|
||||
IWrapper keyWrapper = Helper.CreateWrapper(keyEncryptionAlgorithm.Algorithm.Id);
|
||||
keyWrapper.Init(true, new ParametersWithRandom(keyEncryptionKey, random));
|
||||
Asn1OctetString encryptedKey = new DerOctetString(
|
||||
keyWrapper.Wrap(keyBytes, 0, keyBytes.Length));
|
||||
|
||||
return new RecipientInfo(new KekRecipientInfo(kekIdentifier, keyEncryptionAlgorithm, encryptedKey));
|
||||
}
|
||||
|
||||
private static AlgorithmIdentifier DetermineKeyEncAlg(
|
||||
string algorithm, KeyParameter key)
|
||||
{
|
||||
if (Org.BouncyCastle.Utilities.Platform.StartsWith(algorithm, "DES"))
|
||||
{
|
||||
return new AlgorithmIdentifier(
|
||||
PkcsObjectIdentifiers.IdAlgCms3DesWrap,
|
||||
DerNull.Instance);
|
||||
}
|
||||
else if (Org.BouncyCastle.Utilities.Platform.StartsWith(algorithm, "RC2"))
|
||||
{
|
||||
return new AlgorithmIdentifier(
|
||||
PkcsObjectIdentifiers.IdAlgCmsRC2Wrap,
|
||||
new DerInteger(58));
|
||||
}
|
||||
else if (Org.BouncyCastle.Utilities.Platform.StartsWith(algorithm, "AES"))
|
||||
{
|
||||
int length = key.GetKey().Length * 8;
|
||||
DerObjectIdentifier wrapOid;
|
||||
|
||||
if (length == 128)
|
||||
{
|
||||
wrapOid = NistObjectIdentifiers.IdAes128Wrap;
|
||||
}
|
||||
else if (length == 192)
|
||||
{
|
||||
wrapOid = NistObjectIdentifiers.IdAes192Wrap;
|
||||
}
|
||||
else if (length == 256)
|
||||
{
|
||||
wrapOid = NistObjectIdentifiers.IdAes256Wrap;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException("illegal keysize in AES");
|
||||
}
|
||||
|
||||
return new AlgorithmIdentifier(wrapOid); // parameters absent
|
||||
}
|
||||
else if (Org.BouncyCastle.Utilities.Platform.StartsWith(algorithm, "SEED"))
|
||||
{
|
||||
// parameters absent
|
||||
return new AlgorithmIdentifier(KisaObjectIdentifiers.IdNpkiAppCmsSeedWrap);
|
||||
}
|
||||
else if (Org.BouncyCastle.Utilities.Platform.StartsWith(algorithm, "CAMELLIA"))
|
||||
{
|
||||
int length = key.GetKey().Length * 8;
|
||||
DerObjectIdentifier wrapOid;
|
||||
|
||||
if (length == 128)
|
||||
{
|
||||
wrapOid = NttObjectIdentifiers.IdCamellia128Wrap;
|
||||
}
|
||||
else if (length == 192)
|
||||
{
|
||||
wrapOid = NttObjectIdentifiers.IdCamellia192Wrap;
|
||||
}
|
||||
else if (length == 256)
|
||||
{
|
||||
wrapOid = NttObjectIdentifiers.IdCamellia256Wrap;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException("illegal keysize in Camellia");
|
||||
}
|
||||
|
||||
return new AlgorithmIdentifier(wrapOid); // parameters must be absent
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException("unknown algorithm");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 764accd23d3d15147a4cf8f10a88f687
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,66 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
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.Parameters;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Security;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Cms
|
||||
{
|
||||
/**
|
||||
* the RecipientInfo class for a recipient who has been sent a message
|
||||
* encrypted using a secret key known to the other side.
|
||||
*/
|
||||
public class KekRecipientInformation
|
||||
: RecipientInformation
|
||||
{
|
||||
private KekRecipientInfo info;
|
||||
|
||||
internal KekRecipientInformation(
|
||||
KekRecipientInfo info,
|
||||
CmsSecureReadable secureReadable)
|
||||
: base(info.KeyEncryptionAlgorithm, secureReadable)
|
||||
{
|
||||
this.info = info;
|
||||
this.rid = new RecipientID();
|
||||
|
||||
KekIdentifier kekId = info.KekID;
|
||||
|
||||
rid.KeyIdentifier = kekId.KeyIdentifier.GetOctets();
|
||||
}
|
||||
|
||||
/**
|
||||
* decrypt the content and return an input stream.
|
||||
*/
|
||||
public override CmsTypedStream GetContentStream(
|
||||
ICipherParameters key)
|
||||
{
|
||||
try
|
||||
{
|
||||
byte[] encryptedKey = info.EncryptedKey.GetOctets();
|
||||
IWrapper keyWrapper = WrapperUtilities.GetWrapper(keyEncAlg.Algorithm.Id);
|
||||
|
||||
keyWrapper.Init(false, key);
|
||||
|
||||
KeyParameter sKey = ParameterUtilities.CreateKeyParameter(
|
||||
GetContentAlgorithmName(), keyWrapper.Unwrap(encryptedKey, 0, encryptedKey.Length));
|
||||
|
||||
return GetContentFromSessionKey(sKey);
|
||||
}
|
||||
catch (SecurityUtilityException e)
|
||||
{
|
||||
throw new CmsException("couldn't create cipher.", e);
|
||||
}
|
||||
catch (InvalidKeyException e)
|
||||
{
|
||||
throw new CmsException("key invalid in message.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a668dd24874b8c047b20f583f86df772
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,174 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Cms;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Cms.Ecc;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.X509;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.X9;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Math;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Security;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.X509;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Cms
|
||||
{
|
||||
internal class KeyAgreeRecipientInfoGenerator : RecipientInfoGenerator
|
||||
{
|
||||
private static readonly CmsEnvelopedHelper Helper = CmsEnvelopedHelper.Instance;
|
||||
|
||||
private DerObjectIdentifier keyAgreementOID;
|
||||
private DerObjectIdentifier keyEncryptionOID;
|
||||
private IList<X509Certificate> recipientCerts;
|
||||
private AsymmetricCipherKeyPair senderKeyPair;
|
||||
|
||||
internal KeyAgreeRecipientInfoGenerator()
|
||||
{
|
||||
}
|
||||
|
||||
internal DerObjectIdentifier KeyAgreementOID
|
||||
{
|
||||
set { this.keyAgreementOID = value; }
|
||||
}
|
||||
|
||||
internal DerObjectIdentifier KeyEncryptionOID
|
||||
{
|
||||
set { this.keyEncryptionOID = value; }
|
||||
}
|
||||
|
||||
internal IEnumerable<X509Certificate> RecipientCerts
|
||||
{
|
||||
set { this.recipientCerts = new List<X509Certificate>(value); }
|
||||
}
|
||||
|
||||
internal AsymmetricCipherKeyPair SenderKeyPair
|
||||
{
|
||||
set { this.senderKeyPair = value; }
|
||||
}
|
||||
|
||||
public RecipientInfo Generate(KeyParameter contentEncryptionKey, SecureRandom random)
|
||||
{
|
||||
byte[] keyBytes = contentEncryptionKey.GetKey();
|
||||
|
||||
AsymmetricKeyParameter senderPublicKey = senderKeyPair.Public;
|
||||
ICipherParameters senderPrivateParams = senderKeyPair.Private;
|
||||
|
||||
|
||||
OriginatorIdentifierOrKey originator;
|
||||
try
|
||||
{
|
||||
originator = new OriginatorIdentifierOrKey(
|
||||
CreateOriginatorPublicKey(senderPublicKey));
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new InvalidKeyException("cannot extract originator public key: " + e);
|
||||
}
|
||||
|
||||
|
||||
Asn1OctetString ukm = null;
|
||||
if (keyAgreementOID.Id.Equals(CmsEnvelopedGenerator.ECMqvSha1Kdf))
|
||||
{
|
||||
try
|
||||
{
|
||||
IAsymmetricCipherKeyPairGenerator ephemKPG =
|
||||
GeneratorUtilities.GetKeyPairGenerator(keyAgreementOID);
|
||||
ephemKPG.Init(
|
||||
((ECPublicKeyParameters)senderPublicKey).CreateKeyGenerationParameters(random));
|
||||
|
||||
AsymmetricCipherKeyPair ephemKP = ephemKPG.GenerateKeyPair();
|
||||
|
||||
ukm = new DerOctetString(
|
||||
new MQVuserKeyingMaterial(
|
||||
CreateOriginatorPublicKey(ephemKP.Public), null));
|
||||
|
||||
senderPrivateParams = new MqvPrivateParameters(
|
||||
(ECPrivateKeyParameters)senderPrivateParams,
|
||||
(ECPrivateKeyParameters)ephemKP.Private,
|
||||
(ECPublicKeyParameters)ephemKP.Public);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new InvalidKeyException("cannot extract MQV ephemeral public key: " + e);
|
||||
}
|
||||
catch (SecurityUtilityException e)
|
||||
{
|
||||
throw new InvalidKeyException("cannot determine MQV ephemeral key pair parameters from public key: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DerSequence paramSeq = new DerSequence(
|
||||
keyEncryptionOID,
|
||||
DerNull.Instance);
|
||||
AlgorithmIdentifier keyEncAlg = new AlgorithmIdentifier(keyAgreementOID, paramSeq);
|
||||
|
||||
|
||||
Asn1EncodableVector recipientEncryptedKeys = new Asn1EncodableVector();
|
||||
foreach (X509Certificate recipientCert in recipientCerts)
|
||||
{
|
||||
TbsCertificateStructure tbsCert;
|
||||
try
|
||||
{
|
||||
tbsCert = TbsCertificateStructure.GetInstance(
|
||||
Asn1Object.FromByteArray(recipientCert.GetTbsCertificate()));
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw new ArgumentException("can't extract TBS structure from certificate");
|
||||
}
|
||||
|
||||
// TODO Should there be a SubjectKeyIdentifier-based alternative?
|
||||
IssuerAndSerialNumber issuerSerial = new IssuerAndSerialNumber(
|
||||
tbsCert.Issuer, tbsCert.SerialNumber.Value);
|
||||
KeyAgreeRecipientIdentifier karid = new KeyAgreeRecipientIdentifier(issuerSerial);
|
||||
|
||||
ICipherParameters recipientPublicParams = recipientCert.GetPublicKey();
|
||||
if (keyAgreementOID.Id.Equals(CmsEnvelopedGenerator.ECMqvSha1Kdf))
|
||||
{
|
||||
recipientPublicParams = new MqvPublicParameters(
|
||||
(ECPublicKeyParameters)recipientPublicParams,
|
||||
(ECPublicKeyParameters)recipientPublicParams);
|
||||
}
|
||||
|
||||
// Use key agreement to choose a wrap key for this recipient
|
||||
IBasicAgreement keyAgreement = AgreementUtilities.GetBasicAgreementWithKdf(
|
||||
keyAgreementOID, keyEncryptionOID.Id);
|
||||
keyAgreement.Init(new ParametersWithRandom(senderPrivateParams, random));
|
||||
BigInteger agreedValue = keyAgreement.CalculateAgreement(recipientPublicParams);
|
||||
|
||||
int keyEncryptionKeySize = GeneratorUtilities.GetDefaultKeySize(keyEncryptionOID) / 8;
|
||||
byte[] keyEncryptionKeyBytes = X9IntegerConverter.IntegerToBytes(agreedValue, keyEncryptionKeySize);
|
||||
KeyParameter keyEncryptionKey = ParameterUtilities.CreateKeyParameter(
|
||||
keyEncryptionOID, keyEncryptionKeyBytes);
|
||||
|
||||
// Wrap the content encryption key with the agreement key
|
||||
IWrapper keyWrapper = Helper.CreateWrapper(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));
|
||||
}
|
||||
|
||||
return new RecipientInfo(new KeyAgreeRecipientInfo(originator, ukm, keyEncAlg,
|
||||
new DerSequence(recipientEncryptedKeys)));
|
||||
}
|
||||
|
||||
private static OriginatorPublicKey CreateOriginatorPublicKey(
|
||||
AsymmetricKeyParameter publicKey)
|
||||
{
|
||||
SubjectPublicKeyInfo spki = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(publicKey);
|
||||
return new OriginatorPublicKey(
|
||||
new AlgorithmIdentifier(spki.AlgorithmID.Algorithm, DerNull.Instance),
|
||||
spki.PublicKeyData.GetBytes());
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 123a2fced714ba64db37e4e782038e10
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,226 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Cms;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Cms.Ecc;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Pkcs;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.X509;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.X9;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Math;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Pkcs;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Security;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Cms
|
||||
{
|
||||
/**
|
||||
* the RecipientInfo class for a recipient who has been sent a message
|
||||
* encrypted using key agreement.
|
||||
*/
|
||||
public class KeyAgreeRecipientInformation
|
||||
: RecipientInformation
|
||||
{
|
||||
private KeyAgreeRecipientInfo info;
|
||||
private Asn1OctetString encryptedKey;
|
||||
|
||||
internal static void ReadRecipientInfo(IList<RecipientInformation> infos, KeyAgreeRecipientInfo info,
|
||||
CmsSecureReadable secureReadable)
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (Asn1Encodable rek in info.RecipientEncryptedKeys)
|
||||
{
|
||||
RecipientEncryptedKey id = RecipientEncryptedKey.GetInstance(rek.ToAsn1Object());
|
||||
|
||||
RecipientID rid = new RecipientID();
|
||||
|
||||
Asn1.Cms.KeyAgreeRecipientIdentifier karid = id.Identifier;
|
||||
|
||||
Asn1.Cms.IssuerAndSerialNumber iAndSN = karid.IssuerAndSerialNumber;
|
||||
if (iAndSN != null)
|
||||
{
|
||||
rid.Issuer = iAndSN.Name;
|
||||
rid.SerialNumber = iAndSN.SerialNumber.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
Asn1.Cms.RecipientKeyIdentifier rKeyID = karid.RKeyID;
|
||||
|
||||
// Note: 'date' and 'other' fields of RecipientKeyIdentifier appear to be only informational
|
||||
|
||||
rid.SubjectKeyIdentifier = rKeyID.SubjectKeyIdentifier.GetOctets();
|
||||
}
|
||||
|
||||
infos.Add(new KeyAgreeRecipientInformation(info, rid, id.EncryptedKey,
|
||||
secureReadable));
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new ArgumentException("invalid rid in KeyAgreeRecipientInformation", e);
|
||||
}
|
||||
}
|
||||
|
||||
internal KeyAgreeRecipientInformation(
|
||||
KeyAgreeRecipientInfo info,
|
||||
RecipientID rid,
|
||||
Asn1OctetString encryptedKey,
|
||||
CmsSecureReadable secureReadable)
|
||||
: base(info.KeyEncryptionAlgorithm, secureReadable)
|
||||
{
|
||||
this.info = info;
|
||||
this.rid = rid;
|
||||
this.encryptedKey = encryptedKey;
|
||||
}
|
||||
|
||||
private AsymmetricKeyParameter GetSenderPublicKey(
|
||||
AsymmetricKeyParameter receiverPrivateKey,
|
||||
OriginatorIdentifierOrKey originator)
|
||||
{
|
||||
OriginatorPublicKey opk = originator.OriginatorPublicKey;
|
||||
if (opk != null)
|
||||
{
|
||||
return GetPublicKeyFromOriginatorPublicKey(receiverPrivateKey, opk);
|
||||
}
|
||||
|
||||
OriginatorID origID = new OriginatorID();
|
||||
|
||||
Asn1.Cms.IssuerAndSerialNumber iAndSN = originator.IssuerAndSerialNumber;
|
||||
if (iAndSN != null)
|
||||
{
|
||||
origID.Issuer = iAndSN.Name;
|
||||
origID.SerialNumber = iAndSN.SerialNumber.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
SubjectKeyIdentifier ski = originator.SubjectKeyIdentifier;
|
||||
|
||||
origID.SubjectKeyIdentifier = ski.GetKeyIdentifier();
|
||||
}
|
||||
|
||||
return GetPublicKeyFromOriginatorID(origID);
|
||||
}
|
||||
|
||||
private AsymmetricKeyParameter GetPublicKeyFromOriginatorPublicKey(
|
||||
AsymmetricKeyParameter receiverPrivateKey,
|
||||
OriginatorPublicKey originatorPublicKey)
|
||||
{
|
||||
PrivateKeyInfo privInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(receiverPrivateKey);
|
||||
SubjectPublicKeyInfo pubInfo = new SubjectPublicKeyInfo(
|
||||
privInfo.PrivateKeyAlgorithm,
|
||||
originatorPublicKey.PublicKey.GetBytes());
|
||||
return PublicKeyFactory.CreateKey(pubInfo);
|
||||
}
|
||||
|
||||
private AsymmetricKeyParameter GetPublicKeyFromOriginatorID(
|
||||
OriginatorID origID)
|
||||
{
|
||||
// TODO Support all alternatives for OriginatorIdentifierOrKey
|
||||
// see RFC 3852 6.2.2
|
||||
throw new CmsException("No support for 'originator' as IssuerAndSerialNumber or SubjectKeyIdentifier");
|
||||
}
|
||||
|
||||
private KeyParameter CalculateAgreedWrapKey(
|
||||
string wrapAlg,
|
||||
AsymmetricKeyParameter senderPublicKey,
|
||||
AsymmetricKeyParameter receiverPrivateKey)
|
||||
{
|
||||
DerObjectIdentifier agreeAlgID = keyEncAlg.Algorithm;
|
||||
|
||||
ICipherParameters senderPublicParams = senderPublicKey;
|
||||
ICipherParameters receiverPrivateParams = receiverPrivateKey;
|
||||
|
||||
if (agreeAlgID.Id.Equals(CmsEnvelopedGenerator.ECMqvSha1Kdf))
|
||||
{
|
||||
byte[] ukmEncoding = info.UserKeyingMaterial.GetOctets();
|
||||
MQVuserKeyingMaterial ukm = MQVuserKeyingMaterial.GetInstance(
|
||||
Asn1Object.FromByteArray(ukmEncoding));
|
||||
|
||||
AsymmetricKeyParameter ephemeralKey = GetPublicKeyFromOriginatorPublicKey(
|
||||
receiverPrivateKey, ukm.EphemeralPublicKey);
|
||||
|
||||
senderPublicParams = new MqvPublicParameters(
|
||||
(ECPublicKeyParameters)senderPublicParams,
|
||||
(ECPublicKeyParameters)ephemeralKey);
|
||||
receiverPrivateParams = new MqvPrivateParameters(
|
||||
(ECPrivateKeyParameters)receiverPrivateParams,
|
||||
(ECPrivateKeyParameters)receiverPrivateParams);
|
||||
}
|
||||
|
||||
IBasicAgreement agreement = AgreementUtilities.GetBasicAgreementWithKdf(
|
||||
agreeAlgID, wrapAlg);
|
||||
agreement.Init(receiverPrivateParams);
|
||||
BigInteger agreedValue = agreement.CalculateAgreement(senderPublicParams);
|
||||
|
||||
int wrapKeySize = GeneratorUtilities.GetDefaultKeySize(wrapAlg) / 8;
|
||||
byte[] wrapKeyBytes = X9IntegerConverter.IntegerToBytes(agreedValue, wrapKeySize);
|
||||
return ParameterUtilities.CreateKeyParameter(wrapAlg, wrapKeyBytes);
|
||||
}
|
||||
|
||||
private KeyParameter UnwrapSessionKey(
|
||||
string wrapAlg,
|
||||
KeyParameter agreedKey)
|
||||
{
|
||||
byte[] encKeyOctets = encryptedKey.GetOctets();
|
||||
|
||||
IWrapper keyCipher = WrapperUtilities.GetWrapper(wrapAlg);
|
||||
keyCipher.Init(false, agreedKey);
|
||||
byte[] sKeyBytes = keyCipher.Unwrap(encKeyOctets, 0, encKeyOctets.Length);
|
||||
return ParameterUtilities.CreateKeyParameter(GetContentAlgorithmName(), sKeyBytes);
|
||||
}
|
||||
|
||||
internal KeyParameter GetSessionKey(
|
||||
AsymmetricKeyParameter receiverPrivateKey)
|
||||
{
|
||||
try
|
||||
{
|
||||
string wrapAlg = DerObjectIdentifier.GetInstance(
|
||||
Asn1Sequence.GetInstance(keyEncAlg.Parameters)[0]).Id;
|
||||
|
||||
AsymmetricKeyParameter senderPublicKey = GetSenderPublicKey(
|
||||
receiverPrivateKey, info.Originator);
|
||||
|
||||
KeyParameter agreedWrapKey = CalculateAgreedWrapKey(wrapAlg,
|
||||
senderPublicKey, receiverPrivateKey);
|
||||
|
||||
return UnwrapSessionKey(wrapAlg, agreedWrapKey);
|
||||
}
|
||||
catch (SecurityUtilityException e)
|
||||
{
|
||||
throw new CmsException("couldn't create cipher.", e);
|
||||
}
|
||||
catch (InvalidKeyException e)
|
||||
{
|
||||
throw new CmsException("key invalid in message.", e);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new CmsException("originator key invalid.", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* decrypt the content and return an input stream.
|
||||
*/
|
||||
public override CmsTypedStream GetContentStream(
|
||||
ICipherParameters key)
|
||||
{
|
||||
if (!(key is AsymmetricKeyParameter receiverPrivateKey))
|
||||
throw new ArgumentException("KeyAgreement requires asymmetric key", "key");
|
||||
|
||||
if (!receiverPrivateKey.IsPrivate)
|
||||
throw new ArgumentException("Expected private key", "key");
|
||||
|
||||
KeyParameter sKey = GetSessionKey(receiverPrivateKey);
|
||||
|
||||
return GetContentFromSessionKey(sKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 16d9a42147799fc408b9bb9ff87d2d6d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,72 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
|
||||
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.Parameters;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Security;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.X509;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Cms
|
||||
{
|
||||
public class KeyTransRecipientInfoGenerator
|
||||
: RecipientInfoGenerator
|
||||
{
|
||||
private readonly IKeyWrapper m_keyWrapper;
|
||||
|
||||
private IssuerAndSerialNumber m_issuerAndSerialNumber;
|
||||
private Asn1OctetString m_subjectKeyIdentifier;
|
||||
|
||||
public KeyTransRecipientInfoGenerator(X509Certificate recipCert, IKeyWrapper keyWrapper)
|
||||
: this(new IssuerAndSerialNumber(recipCert.IssuerDN, new DerInteger(recipCert.SerialNumber)), keyWrapper)
|
||||
{
|
||||
}
|
||||
|
||||
public KeyTransRecipientInfoGenerator(IssuerAndSerialNumber issuerAndSerial, IKeyWrapper keyWrapper)
|
||||
{
|
||||
m_issuerAndSerialNumber = issuerAndSerial;
|
||||
m_keyWrapper = keyWrapper;
|
||||
}
|
||||
|
||||
public KeyTransRecipientInfoGenerator(byte[] subjectKeyID, IKeyWrapper keyWrapper)
|
||||
{
|
||||
m_subjectKeyIdentifier = new DerOctetString(subjectKeyID);
|
||||
m_keyWrapper = keyWrapper;
|
||||
}
|
||||
|
||||
public RecipientInfo Generate(KeyParameter contentEncryptionKey, SecureRandom random)
|
||||
{
|
||||
AlgorithmIdentifier keyEncryptionAlgorithm = AlgorithmDetails;
|
||||
|
||||
byte[] encryptedKeyBytes = GenerateWrappedKey(contentEncryptionKey);
|
||||
|
||||
RecipientIdentifier recipId;
|
||||
if (m_issuerAndSerialNumber != null)
|
||||
{
|
||||
recipId = new RecipientIdentifier(m_issuerAndSerialNumber);
|
||||
}
|
||||
else
|
||||
{
|
||||
recipId = new RecipientIdentifier(m_subjectKeyIdentifier);
|
||||
}
|
||||
|
||||
return new RecipientInfo(new KeyTransRecipientInfo(recipId, keyEncryptionAlgorithm,
|
||||
new DerOctetString(encryptedKeyBytes)));
|
||||
}
|
||||
|
||||
protected virtual AlgorithmIdentifier AlgorithmDetails
|
||||
{
|
||||
get { return (AlgorithmIdentifier)m_keyWrapper.AlgorithmDetails; }
|
||||
}
|
||||
|
||||
protected virtual byte[] GenerateWrappedKey(KeyParameter contentEncryptionKey)
|
||||
{
|
||||
return m_keyWrapper.Wrap(contentEncryptionKey.GetKey()).Collect();
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 62cf515f439ab014faae9f84218999b4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,136 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Cms;
|
||||
using Asn1Pkcs = BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Pkcs;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.X509;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Security;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.X509;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Pkcs;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Operators;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Cms
|
||||
{
|
||||
/**
|
||||
* the KeyTransRecipientInformation class for a recipient who has been sent a secret
|
||||
* key encrypted using their public key that needs to be used to
|
||||
* extract the message.
|
||||
*/
|
||||
public class KeyTransRecipientInformation
|
||||
: RecipientInformation
|
||||
{
|
||||
private KeyTransRecipientInfo info;
|
||||
|
||||
internal KeyTransRecipientInformation(
|
||||
KeyTransRecipientInfo info,
|
||||
CmsSecureReadable secureReadable)
|
||||
: base(info.KeyEncryptionAlgorithm, secureReadable)
|
||||
{
|
||||
this.info = info;
|
||||
this.rid = new RecipientID();
|
||||
|
||||
RecipientIdentifier r = info.RecipientIdentifier;
|
||||
|
||||
try
|
||||
{
|
||||
if (r.IsTagged)
|
||||
{
|
||||
Asn1OctetString octs = Asn1OctetString.GetInstance(r.ID);
|
||||
|
||||
rid.SubjectKeyIdentifier = octs.GetOctets();
|
||||
}
|
||||
else
|
||||
{
|
||||
Asn1.Cms.IssuerAndSerialNumber iAnds = Asn1.Cms.IssuerAndSerialNumber.GetInstance(r.ID);
|
||||
|
||||
rid.Issuer = iAnds.Name;
|
||||
rid.SerialNumber = iAnds.SerialNumber.Value;
|
||||
}
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
throw new ArgumentException("invalid rid in KeyTransRecipientInformation");
|
||||
}
|
||||
}
|
||||
|
||||
private string GetExchangeEncryptionAlgorithmName(
|
||||
AlgorithmIdentifier algo)
|
||||
{
|
||||
DerObjectIdentifier oid = algo.Algorithm;
|
||||
|
||||
if (Asn1Pkcs.PkcsObjectIdentifiers.RsaEncryption.Equals(oid))
|
||||
{
|
||||
return "RSA//PKCS1Padding";
|
||||
} else if (Asn1Pkcs.PkcsObjectIdentifiers.IdRsaesOaep.Equals(oid))
|
||||
{
|
||||
Asn1Pkcs.RsaesOaepParameters rsaParams = Asn1Pkcs.RsaesOaepParameters.GetInstance(algo.Parameters);
|
||||
return "RSA//OAEPWITH"+DigestUtilities.GetAlgorithmName(rsaParams.HashAlgorithm.Algorithm)+"ANDMGF1Padding";
|
||||
}
|
||||
|
||||
return oid.Id;
|
||||
}
|
||||
|
||||
internal KeyParameter UnwrapKey(ICipherParameters key)
|
||||
{
|
||||
byte[] encryptedKey = info.EncryptedKey.GetOctets();
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
if (keyEncAlg.Algorithm.Equals(PkcsObjectIdentifiers.IdRsaesOaep))
|
||||
{
|
||||
IKeyUnwrapper keyWrapper = new Asn1KeyUnwrapper(keyEncAlg.Algorithm, keyEncAlg.Parameters, key);
|
||||
|
||||
return ParameterUtilities.CreateKeyParameter(
|
||||
GetContentAlgorithmName(), keyWrapper.Unwrap(encryptedKey, 0, encryptedKey.Length).Collect());
|
||||
}
|
||||
else
|
||||
{
|
||||
string keyExchangeAlgorithm = GetExchangeEncryptionAlgorithmName(keyEncAlg);
|
||||
IWrapper keyWrapper = WrapperUtilities.GetWrapper(keyExchangeAlgorithm);
|
||||
keyWrapper.Init(false, key);
|
||||
|
||||
// FIXME Support for MAC algorithm parameters similar to cipher parameters
|
||||
return ParameterUtilities.CreateKeyParameter(
|
||||
GetContentAlgorithmName(), keyWrapper.Unwrap(encryptedKey, 0, encryptedKey.Length));
|
||||
}
|
||||
}
|
||||
catch (SecurityUtilityException e)
|
||||
{
|
||||
throw new CmsException("couldn't create cipher.", e);
|
||||
}
|
||||
catch (InvalidKeyException e)
|
||||
{
|
||||
throw new CmsException("key invalid in message.", e);
|
||||
}
|
||||
// catch (IllegalBlockSizeException e)
|
||||
catch (DataLengthException e)
|
||||
{
|
||||
throw new CmsException("illegal blocksize in message.", e);
|
||||
}
|
||||
// catch (BadPaddingException e)
|
||||
catch (InvalidCipherTextException e)
|
||||
{
|
||||
throw new CmsException("bad padding in message.", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* decrypt the content and return it as a byte array.
|
||||
*/
|
||||
public override CmsTypedStream GetContentStream(
|
||||
ICipherParameters key)
|
||||
{
|
||||
KeyParameter sKey = UnwrapKey(key);
|
||||
|
||||
return GetContentFromSessionKey(sKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e0e4c1fe9df46304aad8da6377a731b3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,55 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.X509;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Math;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.X509.Store;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Cms
|
||||
{
|
||||
/**
|
||||
* a basic index for an originator.
|
||||
*/
|
||||
public class OriginatorID
|
||||
: X509CertStoreSelector
|
||||
{
|
||||
public override int GetHashCode()
|
||||
{
|
||||
int code = Arrays.GetHashCode(this.SubjectKeyIdentifier);
|
||||
|
||||
BigInteger serialNumber = this.SerialNumber;
|
||||
if (serialNumber != null)
|
||||
{
|
||||
code ^= serialNumber.GetHashCode();
|
||||
}
|
||||
|
||||
X509Name issuer = this.Issuer;
|
||||
if (issuer != null)
|
||||
{
|
||||
code ^= issuer.GetHashCode();
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
public override bool Equals(
|
||||
object obj)
|
||||
{
|
||||
if (obj == this)
|
||||
return false;
|
||||
|
||||
OriginatorID id = obj as OriginatorID;
|
||||
|
||||
if (id == null)
|
||||
return false;
|
||||
|
||||
return Arrays.AreEqual(SubjectKeyIdentifier, id.SubjectKeyIdentifier)
|
||||
&& Org.BouncyCastle.Utilities.Platform.Equals(SerialNumber, id.SerialNumber)
|
||||
&& IssuersMatch(Issuer, id.Issuer);
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 88730f33bf66f0a448ad35da8082b31d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user