diff --git a/crypto/src/cms/CMSSignedDataGenerator.cs b/crypto/src/cms/CMSSignedDataGenerator.cs
index 114b9631d..201cfc5c4 100644
--- a/crypto/src/cms/CMSSignedDataGenerator.cs
+++ b/crypto/src/cms/CMSSignedDataGenerator.cs
@@ -6,11 +6,11 @@ using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.Cms;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto;
-using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Security.Certificates;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.X509;
+using Org.BouncyCastle.Crypto.Operators;
namespace Org.BouncyCastle.Cms
{
@@ -43,7 +43,7 @@ namespace Org.BouncyCastle.Cms
{
private readonly CmsSignedGenerator outer;
- private readonly AsymmetricKeyParameter key;
+ private readonly ISignatureCalculator sigCalc;
private readonly SignerIdentifier signerIdentifier;
private readonly string digestOID;
private readonly string encOID;
@@ -61,8 +61,12 @@ namespace Org.BouncyCastle.Cms
CmsAttributeTableGenerator unsAttr,
Asn1.Cms.AttributeTable baseSignedTable)
{
+ string digestName = Helper.GetDigestAlgName(digestOID);
+
+ string signatureName = digestName + "with" + Helper.GetEncryptionAlgName(encOID);
+
this.outer = outer;
- this.key = key;
+ this.sigCalc = new Asn1SignatureCalculator(signatureName, key);
this.signerIdentifier = signerIdentifier;
this.digestOID = digestOID;
this.encOID = encOID;
@@ -71,7 +75,25 @@ namespace Org.BouncyCastle.Cms
this.baseSignedTable = baseSignedTable;
}
- internal AlgorithmIdentifier DigestAlgorithmID
+ internal SignerInf(
+ CmsSignedGenerator outer,
+ ISignatureCalculator 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); }
}
@@ -95,8 +117,7 @@ namespace Org.BouncyCastle.Cms
string digestName = Helper.GetDigestAlgName(digestOID);
string signatureName = digestName + "with" + Helper.GetEncryptionAlgName(encOID);
- ISigner sig = Helper.GetSignatureInstance(signatureName);
-
+
byte[] hash;
if (outer._digests.Contains(digestOID))
{
@@ -113,11 +134,12 @@ namespace Org.BouncyCastle.Cms
outer._digests.Add(digestOID, hash.Clone());
}
- sig.Init(true, new ParametersWithRandom(key, random));
+ IStreamCalculator calculator = sigCalc.CreateCalculator();
+
#if NETCF_1_0 || NETCF_2_0 || SILVERLIGHT
- Stream sigStr = new SigOutputStream(sig);
+ Stream sigStr = new SigOutputStream(calculator.Stream);
#else
- Stream sigStr = new BufferedStream(new SigOutputStream(sig));
+ Stream sigStr = new BufferedStream(calculator.Stream);
#endif
Asn1Set signedAttr = null;
@@ -152,7 +174,7 @@ namespace Org.BouncyCastle.Cms
}
sigStr.Close();
- byte[] sigBytes = sig.GenerateSignature();
+ byte[] sigBytes = ((IBlockResult)calculator.GetResult()).DoFinal();
Asn1Set unsignedAttr = null;
if (unsAttr != null)
@@ -170,7 +192,7 @@ namespace Org.BouncyCastle.Cms
// TODO[RSAPSS] Need the ability to specify non-default parameters
Asn1Encodable sigX509Parameters = SignerUtilities.GetDefaultX509Parameters(signatureName);
- AlgorithmIdentifier encAlgId = CmsSignedGenerator.GetEncAlgorithmIdentifier(
+ AlgorithmIdentifier encAlgId = Helper.GetEncAlgorithmIdentifier(
new DerObjectIdentifier(encOID), sigX509Parameters);
return new SignerInfo(signerIdentifier, digAlgId,
@@ -203,7 +225,7 @@ namespace Org.BouncyCastle.Cms
X509Certificate cert,
string digestOID)
{
- AddSigner(privateKey, cert, GetEncOid(privateKey, digestOID), digestOID);
+ AddSigner(privateKey, cert, Helper.GetEncOid(privateKey, digestOID), digestOID);
}
/**
@@ -234,7 +256,7 @@ namespace Org.BouncyCastle.Cms
byte[] subjectKeyID,
string digestOID)
{
- AddSigner(privateKey, subjectKeyID, GetEncOid(privateKey, digestOID), digestOID);
+ AddSigner(privateKey, subjectKeyID, Helper.GetEncOid(privateKey, digestOID), digestOID);
}
/**
@@ -267,7 +289,7 @@ namespace Org.BouncyCastle.Cms
Asn1.Cms.AttributeTable signedAttr,
Asn1.Cms.AttributeTable unsignedAttr)
{
- AddSigner(privateKey, cert, GetEncOid(privateKey, digestOID), digestOID,
+ AddSigner(privateKey, cert, Helper.GetEncOid(privateKey, digestOID), digestOID,
signedAttr, unsignedAttr);
}
@@ -311,7 +333,7 @@ namespace Org.BouncyCastle.Cms
Asn1.Cms.AttributeTable signedAttr,
Asn1.Cms.AttributeTable unsignedAttr)
{
- AddSigner(privateKey, subjectKeyID, GetEncOid(privateKey, digestOID), digestOID,
+ AddSigner(privateKey, subjectKeyID, Helper.GetEncOid(privateKey, digestOID), digestOID,
signedAttr, unsignedAttr);
}
@@ -349,7 +371,7 @@ namespace Org.BouncyCastle.Cms
CmsAttributeTableGenerator signedAttrGen,
CmsAttributeTableGenerator unsignedAttrGen)
{
- AddSigner(privateKey, cert, GetEncOid(privateKey, digestOID), digestOID,
+ AddSigner(privateKey, cert, Helper.GetEncOid(privateKey, digestOID), digestOID,
signedAttrGen, unsignedAttrGen);
}
@@ -378,7 +400,7 @@ namespace Org.BouncyCastle.Cms
CmsAttributeTableGenerator signedAttrGen,
CmsAttributeTableGenerator unsignedAttrGen)
{
- AddSigner(privateKey, subjectKeyID, GetEncOid(privateKey, digestOID), digestOID,
+ AddSigner(privateKey, subjectKeyID, Helper.GetEncOid(privateKey, digestOID), digestOID,
signedAttrGen, unsignedAttrGen);
}
@@ -397,7 +419,13 @@ namespace Org.BouncyCastle.Cms
signedAttrGen, unsignedAttrGen, null);
}
- private void doAddSigner(
+ 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,
diff --git a/crypto/src/cms/CMSSignedDataStreamGenerator.cs b/crypto/src/cms/CMSSignedDataStreamGenerator.cs
index 743e9c6c1..223fdb39d 100644
--- a/crypto/src/cms/CMSSignedDataStreamGenerator.cs
+++ b/crypto/src/cms/CMSSignedDataStreamGenerator.cs
@@ -52,10 +52,10 @@ namespace Org.BouncyCastle.Cms
private class DigestAndSignerInfoGeneratorHolder
{
- internal readonly SignerInfoGenerator signerInf;
+ internal readonly ISignerInfoGenerator signerInf;
internal readonly string digestOID;
- internal DigestAndSignerInfoGeneratorHolder(SignerInfoGenerator signerInf, String digestOID)
+ internal DigestAndSignerInfoGeneratorHolder(ISignerInfoGenerator signerInf, String digestOID)
{
this.signerInf = signerInf;
this.digestOID = digestOID;
@@ -67,7 +67,7 @@ namespace Org.BouncyCastle.Cms
}
}
- private class SignerInfoGeneratorImpl : SignerInfoGenerator
+ private class SignerInfoGeneratorImpl : ISignerInfoGenerator
{
private readonly CmsSignedDataStreamGenerator outer;
@@ -215,7 +215,7 @@ namespace Org.BouncyCastle.Cms
// TODO[RSAPSS] Need the ability to specify non-default parameters
Asn1Encodable sigX509Parameters = SignerUtilities.GetDefaultX509Parameters(signatureName);
- AlgorithmIdentifier digestEncryptionAlgorithm = CmsSignedGenerator.GetEncAlgorithmIdentifier(
+ AlgorithmIdentifier digestEncryptionAlgorithm = Helper.GetEncAlgorithmIdentifier(
new DerObjectIdentifier(_encOID), sigX509Parameters);
return new SignerInfo(_signerIdentifier, digestAlgorithm,
@@ -347,7 +347,7 @@ namespace Org.BouncyCastle.Cms
CmsAttributeTableGenerator signedAttrGenerator,
CmsAttributeTableGenerator unsignedAttrGenerator)
{
- AddSigner(privateKey, cert, GetEncOid(privateKey, digestOid), digestOid,
+ AddSigner(privateKey, cert, Helper.GetEncOid(privateKey, digestOid), digestOid,
signedAttrGenerator, unsignedAttrGenerator);
}
@@ -420,7 +420,7 @@ namespace Org.BouncyCastle.Cms
CmsAttributeTableGenerator signedAttrGenerator,
CmsAttributeTableGenerator unsignedAttrGenerator)
{
- AddSigner(privateKey, subjectKeyID, GetEncOid(privateKey, digestOid),
+ AddSigner(privateKey, subjectKeyID, Helper.GetEncOid(privateKey, digestOid),
digestOid, signedAttrGenerator, unsignedAttrGenerator);
}
diff --git a/crypto/src/cms/CMSSignedGenerator.cs b/crypto/src/cms/CMSSignedGenerator.cs
index f272c830e..0fb1f314d 100644
--- a/crypto/src/cms/CMSSignedGenerator.cs
+++ b/crypto/src/cms/CMSSignedGenerator.cs
@@ -16,12 +16,106 @@ using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.Collections;
-using Org.BouncyCastle.Utilities.IO;
using Org.BouncyCastle.X509;
using Org.BouncyCastle.X509.Store;
namespace Org.BouncyCastle.Cms
{
+ public class DefaultDigestAlgorithmIdentifierFinder
+ {
+ private static readonly IDictionary digestOids = Platform.CreateHashtable();
+ private static readonly IDictionary digestNameToOids = Platform.CreateHashtable();
+
+ static DefaultDigestAlgorithmIdentifierFinder()
+ {
+ //
+ // digests
+ //
+ digestOids.Add(OiwObjectIdentifiers.MD4WithRsaEncryption, PkcsObjectIdentifiers.MD4);
+ digestOids.Add(OiwObjectIdentifiers.MD4WithRsa, PkcsObjectIdentifiers.MD4);
+ digestOids.Add(OiwObjectIdentifiers.Sha1WithRsa, OiwObjectIdentifiers.IdSha1);
+
+ digestOids.Add(PkcsObjectIdentifiers.Sha224WithRsaEncryption, NistObjectIdentifiers.IdSha224);
+ digestOids.Add(PkcsObjectIdentifiers.Sha256WithRsaEncryption, NistObjectIdentifiers.IdSha256);
+ digestOids.Add(PkcsObjectIdentifiers.Sha384WithRsaEncryption, NistObjectIdentifiers.IdSha384);
+ digestOids.Add(PkcsObjectIdentifiers.Sha512WithRsaEncryption, NistObjectIdentifiers.IdSha512);
+ digestOids.Add(PkcsObjectIdentifiers.MD2WithRsaEncryption, PkcsObjectIdentifiers.MD2);
+ digestOids.Add(PkcsObjectIdentifiers.MD4WithRsaEncryption, PkcsObjectIdentifiers.MD4);
+ digestOids.Add(PkcsObjectIdentifiers.MD5WithRsaEncryption, PkcsObjectIdentifiers.MD5);
+ digestOids.Add(PkcsObjectIdentifiers.Sha1WithRsaEncryption, OiwObjectIdentifiers.IdSha1);
+
+ digestOids.Add(X9ObjectIdentifiers.ECDsaWithSha1, OiwObjectIdentifiers.IdSha1);
+ digestOids.Add(X9ObjectIdentifiers.ECDsaWithSha224, NistObjectIdentifiers.IdSha224);
+ digestOids.Add(X9ObjectIdentifiers.ECDsaWithSha256, NistObjectIdentifiers.IdSha256);
+ digestOids.Add(X9ObjectIdentifiers.ECDsaWithSha384, NistObjectIdentifiers.IdSha384);
+ digestOids.Add(X9ObjectIdentifiers.ECDsaWithSha512, NistObjectIdentifiers.IdSha512);
+ digestOids.Add(X9ObjectIdentifiers.IdDsaWithSha1, OiwObjectIdentifiers.IdSha1);
+
+ digestOids.Add(NistObjectIdentifiers.DsaWithSha224, NistObjectIdentifiers.IdSha224);
+ digestOids.Add(NistObjectIdentifiers.DsaWithSha256, NistObjectIdentifiers.IdSha256);
+ digestOids.Add(NistObjectIdentifiers.DsaWithSha384, NistObjectIdentifiers.IdSha384);
+ digestOids.Add(NistObjectIdentifiers.DsaWithSha512, NistObjectIdentifiers.IdSha512);
+
+ digestOids.Add(TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD128, TeleTrusTObjectIdentifiers.RipeMD128);
+ digestOids.Add(TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD160, TeleTrusTObjectIdentifiers.RipeMD160);
+ digestOids.Add(TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD256, TeleTrusTObjectIdentifiers.RipeMD256);
+
+ digestOids.Add(CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x94, CryptoProObjectIdentifiers.GostR3411);
+ digestOids.Add(CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x2001, CryptoProObjectIdentifiers.GostR3411);
+
+ digestNameToOids.Add("SHA-1", OiwObjectIdentifiers.IdSha1);
+ digestNameToOids.Add("SHA-224", NistObjectIdentifiers.IdSha224);
+ digestNameToOids.Add("SHA-256", NistObjectIdentifiers.IdSha256);
+ digestNameToOids.Add("SHA-384", NistObjectIdentifiers.IdSha384);
+ digestNameToOids.Add("SHA-512", NistObjectIdentifiers.IdSha512);
+
+ digestNameToOids.Add("SHA1", OiwObjectIdentifiers.IdSha1);
+ digestNameToOids.Add("SHA224", NistObjectIdentifiers.IdSha224);
+ digestNameToOids.Add("SHA256", NistObjectIdentifiers.IdSha256);
+ digestNameToOids.Add("SHA384", NistObjectIdentifiers.IdSha384);
+ digestNameToOids.Add("SHA512", NistObjectIdentifiers.IdSha512);
+
+ digestNameToOids.Add("SHA3-224", NistObjectIdentifiers.IdSha3_224);
+ digestNameToOids.Add("SHA3-256", NistObjectIdentifiers.IdSha3_256);
+ digestNameToOids.Add("SHA3-384", NistObjectIdentifiers.IdSha3_384);
+ digestNameToOids.Add("SHA3-512", NistObjectIdentifiers.IdSha3_512);
+
+ digestNameToOids.Add("SHAKE-128", NistObjectIdentifiers.IdShake128);
+ digestNameToOids.Add("SHAKE-256", NistObjectIdentifiers.IdShake256);
+
+ digestNameToOids.Add("GOST3411", CryptoProObjectIdentifiers.GostR3411);
+
+ digestNameToOids.Add("MD2", PkcsObjectIdentifiers.MD2);
+ digestNameToOids.Add("MD4", PkcsObjectIdentifiers.MD4);
+ digestNameToOids.Add("MD5", PkcsObjectIdentifiers.MD5);
+
+ digestNameToOids.Add("RIPEMD128", TeleTrusTObjectIdentifiers.RipeMD128);
+ digestNameToOids.Add("RIPEMD160", TeleTrusTObjectIdentifiers.RipeMD160);
+ 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((DerObjectIdentifier)digestOids[sigAlgId.Algorithm], DerNull.Instance);
+ }
+
+ return digAlgId;
+ }
+
+ public AlgorithmIdentifier find(String digAlgName)
+ {
+ return new AlgorithmIdentifier((DerObjectIdentifier)digestNameToOids[digAlgName], DerNull.Instance);
+ }
+ }
+
public class CmsSignedGenerator
{
/**
@@ -29,233 +123,145 @@ namespace Org.BouncyCastle.Cms
*/
public static readonly string Data = CmsObjectIdentifiers.Data.Id;
- public static readonly string DigestSha1 = OiwObjectIdentifiers.IdSha1.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 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 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 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;
- 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 ISet noParams = new HashSet();
- private static readonly IDictionary ecAlgorithms = Platform.CreateHashtable();
-
- static CmsSignedGenerator()
- {
- noParams.Add(EncryptionDsa);
-// noParams.Add(EncryptionECDsa);
- noParams.Add(EncryptionECDsaWithSha1);
- noParams.Add(EncryptionECDsaWithSha224);
- noParams.Add(EncryptionECDsaWithSha256);
- noParams.Add(EncryptionECDsaWithSha384);
- noParams.Add(EncryptionECDsaWithSha512);
-
- ecAlgorithms.Add(DigestSha1, EncryptionECDsaWithSha1);
- ecAlgorithms.Add(DigestSha224, EncryptionECDsaWithSha224);
- ecAlgorithms.Add(DigestSha256, EncryptionECDsaWithSha256);
- ecAlgorithms.Add(DigestSha384, EncryptionECDsaWithSha384);
- ecAlgorithms.Add(DigestSha512, EncryptionECDsaWithSha512);
- }
-
- internal IList _certs = Platform.CreateArrayList();
+ internal IList _certs = Platform.CreateArrayList();
internal IList _crls = Platform.CreateArrayList();
- internal IList _signers = Platform.CreateArrayList();
- internal IDictionary _digests = Platform.CreateHashtable();
-
- protected readonly SecureRandom rand;
-
- protected CmsSignedGenerator()
- : this(new SecureRandom())
- {
- }
-
- /// <summary>Constructor allowing specific source of randomness</summary>
- /// <param name="rand">Instance of <c>SecureRandom</c> to use.</param>
- protected CmsSignedGenerator(
- SecureRandom rand)
- {
- this.rand = rand;
- }
-
- protected string GetEncOid(
- AsymmetricKeyParameter key,
- string digestOID)
+ internal IList _signers = Platform.CreateArrayList();
+ internal IDictionary _digests = Platform.CreateHashtable();
+
+ protected readonly SecureRandom rand;
+
+ protected CmsSignedGenerator()
+ : this(new SecureRandom())
{
- string encOID = null;
-
- if (key is RsaKeyParameters)
- {
- if (!((RsaKeyParameters) key).IsPrivate)
- throw new ArgumentException("Expected RSA private key");
-
- encOID = EncryptionRsa;
- }
- else if (key is DsaPrivateKeyParameters)
- {
- if (!digestOID.Equals(DigestSha1))
- throw new ArgumentException("can't mix DSA with anything but SHA1");
-
- encOID = EncryptionDsa;
- }
- else if (key is ECPrivateKeyParameters)
- {
- ECPrivateKeyParameters ecPrivKey = (ECPrivateKeyParameters) key;
- string algName = ecPrivKey.AlgorithmName;
-
- if (algName == "ECGOST3410")
- {
- encOID = EncryptionECGost3410;
- }
- else
- {
- // TODO Should we insist on algName being one of "EC" or "ECDSA", as Java does?
- encOID = (string) ecAlgorithms[digestOID];
-
- if (encOID == null)
- throw new ArgumentException("can't mix ECDSA with anything but SHA family digests");
- }
- }
- else if (key is Gost3410PrivateKeyParameters)
- {
- encOID = EncryptionGost3410;
- }
- else
- {
- throw new ArgumentException("Unknown algorithm in CmsSignedGenerator.GetEncOid");
- }
-
- return encOID;
}
- internal static AlgorithmIdentifier GetEncAlgorithmIdentifier(
- DerObjectIdentifier encOid,
- Asn1Encodable sigX509Parameters)
- {
- if (noParams.Contains(encOid.Id))
- {
- return new AlgorithmIdentifier(encOid);
- }
-
- return new AlgorithmIdentifier(encOid, sigX509Parameters);
- }
-
- internal protected virtual IDictionary GetBaseParameters(
- DerObjectIdentifier contentType,
- AlgorithmIdentifier digAlgId,
- byte[] hash)
- {
- IDictionary param = Platform.CreateHashtable();
+ /// <summary>Constructor allowing specific source of randomness</summary>
+ /// <param name="rand">Instance of <c>SecureRandom</c> to use.</param>
+ protected CmsSignedGenerator(
+ SecureRandom rand)
+ {
+ this.rand = rand;
+ }
+
+ internal protected virtual IDictionary GetBaseParameters(
+ DerObjectIdentifier contentType,
+ AlgorithmIdentifier digAlgId,
+ byte[] hash)
+ {
+ IDictionary param = Platform.CreateHashtable();
if (contentType != null)
{
param[CmsAttributeTableParameter.ContentType] = contentType;
}
- param[CmsAttributeTableParameter.DigestAlgorithmIdentifier] = digAlgId;
+ param[CmsAttributeTableParameter.DigestAlgorithmIdentifier] = digAlgId;
param[CmsAttributeTableParameter.Digest] = hash.Clone();
return param;
- }
+ }
- internal protected virtual Asn1Set GetAttributeSet(
+ internal protected virtual Asn1Set GetAttributeSet(
Asn1.Cms.AttributeTable attr)
{
- return attr == null
- ? null
- : new DerSet(attr.ToAsn1EncodableVector());
+ return attr == null
+ ? null
+ : new DerSet(attr.ToAsn1EncodableVector());
}
- public void AddCertificates(
- IX509Store certStore)
- {
+ public void AddCertificates(
+ IX509Store certStore)
+ {
CollectionUtilities.AddRange(_certs, CmsUtilities.GetCertificatesFromStore(certStore));
}
- public void AddCrls(
- IX509Store crlStore)
- {
+ public void AddCrls(
+ IX509Store crlStore)
+ {
CollectionUtilities.AddRange(_crls, CmsUtilities.GetCrlsFromStore(crlStore));
- }
+ }
- /**
+ /**
* Add the attribute certificates contained in the passed in store to the
* generator.
*
* @param store a store of Version 2 attribute certificates
* @throws CmsException if an error occurse processing the store.
*/
- public void AddAttributeCertificates(
- IX509Store store)
- {
- try
- {
- foreach (IX509AttributeCertificate attrCert in store.GetMatches(null))
- {
- _certs.Add(new DerTaggedObject(false, 2,
- AttributeCertificate.GetInstance(Asn1Object.FromByteArray(attrCert.GetEncoded()))));
- }
- }
- catch (Exception e)
- {
- throw new CmsException("error processing attribute certs", e);
- }
- }
-
- /**
+ public void AddAttributeCertificates(
+ IX509Store store)
+ {
+ try
+ {
+ foreach (IX509AttributeCertificate attrCert in store.GetMatches(null))
+ {
+ _certs.Add(new DerTaggedObject(false, 2,
+ AttributeCertificate.GetInstance(Asn1Object.FromByteArray(attrCert.GetEncoded()))));
+ }
+ }
+ catch (Exception e)
+ {
+ throw new CmsException("error processing attribute certs", e);
+ }
+ }
+
+ /**
* 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);
- }
- }
-
- /**
+ 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 GetGeneratedDigests()
- {
- return Platform.CreateHashtable(_digests);
- }
-
- 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));
- }
- }
+ public IDictionary GetGeneratedDigests()
+ {
+ return Platform.CreateHashtable(_digests);
+ }
+
+ 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));
+ }
+ }
}
diff --git a/crypto/src/cms/CMSSignedHelper.cs b/crypto/src/cms/CMSSignedHelper.cs
index b3406fc06..23657ef86 100644
--- a/crypto/src/cms/CMSSignedHelper.cs
+++ b/crypto/src/cms/CMSSignedHelper.cs
@@ -18,6 +18,8 @@ using Org.BouncyCastle.Security.Certificates;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.X509;
using Org.BouncyCastle.X509.Store;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities.Collections;
namespace Org.BouncyCastle.Cms
{
@@ -25,11 +27,20 @@ namespace Org.BouncyCastle.Cms
{
internal static readonly CmsSignedHelper Instance = new CmsSignedHelper();
- private static readonly IDictionary encryptionAlgs = Platform.CreateHashtable();
+ 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 encryptionAlgs = Platform.CreateHashtable();
private static readonly IDictionary digestAlgs = Platform.CreateHashtable();
private static readonly IDictionary digestAliases = Platform.CreateHashtable();
- private static void AddEntries(DerObjectIdentifier oid, string digest, string encryption)
+ private static readonly ISet noParams = new HashSet();
+ private static readonly IDictionary ecAlgorithms = Platform.CreateHashtable();
+
+ private static void AddEntries(DerObjectIdentifier oid, string digest, string encryption)
{
string alias = oid.Id;
digestAlgs.Add(alias, digest);
@@ -100,7 +111,21 @@ namespace Org.BouncyCastle.Cms
digestAliases.Add("SHA256", new string[] { "SHA-256" });
digestAliases.Add("SHA384", new string[] { "SHA-384" });
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);
+
+ ecAlgorithms.Add(CmsSignedGenerator.DigestSha1, EncryptionECDsaWithSha1);
+ ecAlgorithms.Add(CmsSignedGenerator.DigestSha224, EncryptionECDsaWithSha224);
+ ecAlgorithms.Add(CmsSignedGenerator.DigestSha256, EncryptionECDsaWithSha256);
+ ecAlgorithms.Add(CmsSignedGenerator.DigestSha384, EncryptionECDsaWithSha384);
+ ecAlgorithms.Add(CmsSignedGenerator.DigestSha512, EncryptionECDsaWithSha512);
+ }
/**
* Return the digest algorithm using one of the standard JCA string
@@ -119,7 +144,19 @@ namespace Org.BouncyCastle.Cms
return digestAlgOid;
}
- internal string[] GetDigestAliases(
+ 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)
{
string[] aliases = (string[]) digestAliases[algName];
@@ -315,5 +352,75 @@ namespace Org.BouncyCastle.Cms
return algId;
}
+
+ internal string GetEncOid(
+ AsymmetricKeyParameter key,
+ string digestOID)
+ {
+ string encOID = null;
+
+ if (key is RsaKeyParameters)
+ {
+ if (!((RsaKeyParameters)key).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)
+ {
+ ECPrivateKeyParameters ecPrivKey = (ECPrivateKeyParameters)key;
+ string algName = ecPrivKey.AlgorithmName;
+
+ if (algName == "ECGOST3410")
+ {
+ encOID = CmsSignedGenerator.EncryptionECGost3410;
+ }
+ else
+ {
+ // TODO Should we insist on algName being one of "EC" or "ECDSA", as Java does?
+ encOID = (string)ecAlgorithms[digestOID];
+
+ if (encOID == null)
+ 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;
+ }
}
}
diff --git a/crypto/src/cms/SignerInfoGenerator.cs b/crypto/src/cms/SignerInfoGenerator.cs
index f78cf2c01..62db40ad8 100644
--- a/crypto/src/cms/SignerInfoGenerator.cs
+++ b/crypto/src/cms/SignerInfoGenerator.cs
@@ -3,12 +3,165 @@ using System;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.Cms;
using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.X509;
namespace Org.BouncyCastle.Cms
{
- internal interface SignerInfoGenerator
- {
- SignerInfo Generate(DerObjectIdentifier contentType, AlgorithmIdentifier digestAlgorithm,
- byte[] calculatedDigest);
- }
+ internal interface ISignerInfoGenerator
+ {
+ SignerInfo Generate(DerObjectIdentifier contentType, AlgorithmIdentifier digestAlgorithm,
+ byte[] calculatedDigest);
+ }
+
+ public class SignerInfoGenerator
+ {
+ internal X509Certificate certificate;
+ internal ISignatureCalculator contentSigner;
+ internal SignerIdentifier sigId;
+ internal CmsAttributeTableGenerator signedGen;
+ internal CmsAttributeTableGenerator unsignedGen;
+ private bool isDirectSignature;
+
+ internal SignerInfoGenerator(SignerIdentifier sigId, ISignatureCalculator contentSigner): this(sigId, contentSigner, false)
+ {
+
+ }
+
+ internal SignerInfoGenerator(SignerIdentifier sigId, ISignatureCalculator contentSigner, bool isDirectSignature)
+ {
+ this.sigId = sigId;
+ this.contentSigner = contentSigner;
+ this.isDirectSignature = isDirectSignature;
+ if (this.isDirectSignature)
+ {
+ this.signedGen = null;
+ this.unsignedGen = null;
+ }
+ else
+ {
+ this.signedGen = new DefaultSignedAttributeTableGenerator();
+ this.unsignedGen = null;
+ }
+ }
+
+ internal SignerInfoGenerator(SignerIdentifier sigId, ISignatureCalculator contentSigner, CmsAttributeTableGenerator signedGen, CmsAttributeTableGenerator unsignedGen)
+ {
+ this.sigId = sigId;
+ this.contentSigner = contentSigner;
+ this.signedGen = signedGen;
+ this.unsignedGen = unsignedGen;
+ this.isDirectSignature = false;
+ }
+
+ internal void setAssociatedCertificate(X509Certificate certificate)
+ {
+ this.certificate = certificate;
+ }
+ }
+
+ public class SignerInfoGeneratorBuilder
+ {
+ private bool directSignature;
+ private CmsAttributeTableGenerator signedGen;
+ private CmsAttributeTableGenerator unsignedGen;
+
+ public SignerInfoGeneratorBuilder()
+ {
+ }
+
+ /**
+ * If the passed in flag is true, the signer signature will be based on the data, not
+ * a collection of signed attributes, and no signed attributes will be included.
+ *
+ * @return the builder object
+ */
+ public SignerInfoGeneratorBuilder SetDirectSignature(bool hasNoSignedAttributes)
+ {
+ this.directSignature = hasNoSignedAttributes;
+
+ return this;
+ }
+
+ /**
+ * Provide a custom signed attribute generator.
+ *
+ * @param signedGen a generator of signed attributes.
+ * @return the builder object
+ */
+ public SignerInfoGeneratorBuilder WithSignedAttributeGenerator(CmsAttributeTableGenerator signedGen)
+ {
+ this.signedGen = signedGen;
+
+ return this;
+ }
+
+ /**
+ * Provide a generator of unsigned attributes.
+ *
+ * @param unsignedGen a generator for signed attributes.
+ * @return the builder object
+ */
+ public SignerInfoGeneratorBuilder WithUnsignedAttributeGenerator(CmsAttributeTableGenerator unsignedGen)
+ {
+ this.unsignedGen = unsignedGen;
+
+ return this;
+ }
+
+ /**
+ * Build a generator with the passed in certHolder issuer and serial number as the signerIdentifier.
+ *
+ * @param contentSigner operator for generating the final signature in the SignerInfo with.
+ * @param certHolder carrier for the X.509 certificate related to the contentSigner.
+ * @return a SignerInfoGenerator
+ * @throws OperatorCreationException if the generator cannot be built.
+ */
+ public SignerInfoGenerator Build(ISignatureCalculator contentSigner, X509Certificate certificate)
+ {
+ SignerIdentifier sigId = new SignerIdentifier(new IssuerAndSerialNumber(certificate.IssuerDN, new DerInteger(certificate.SerialNumber)));
+
+ SignerInfoGenerator sigInfoGen = CreateGenerator(contentSigner, sigId);
+
+ sigInfoGen.setAssociatedCertificate(certificate);
+
+ return sigInfoGen;
+ }
+
+ /**
+ * Build a generator with the passed in subjectKeyIdentifier as the signerIdentifier. If used you should
+ * try to follow the calculation described in RFC 5280 section 4.2.1.2.
+ *
+ * @param contentSigner operator for generating the final signature in the SignerInfo with.
+ * @param subjectKeyIdentifier key identifier to identify the public key for verifying the signature.
+ * @return a SignerInfoGenerator
+ * @throws OperatorCreationException if the generator cannot be built.
+ */
+ public SignerInfoGenerator Build(ISignatureCalculator contentSigner, byte[] subjectKeyIdentifier)
+ {
+ SignerIdentifier sigId = new SignerIdentifier(new DerOctetString(subjectKeyIdentifier));
+
+ return CreateGenerator(contentSigner, sigId);
+ }
+
+ private SignerInfoGenerator CreateGenerator(ISignatureCalculator contentSigner, SignerIdentifier sigId)
+ {
+ if (directSignature)
+ {
+ return new SignerInfoGenerator(sigId, contentSigner, true);
+ }
+
+ if (signedGen != null || unsignedGen != null)
+ {
+ if (signedGen == null)
+ {
+ signedGen = new DefaultSignedAttributeTableGenerator();
+ }
+
+ return new SignerInfoGenerator(sigId, contentSigner, signedGen, unsignedGen);
+ }
+
+ return new SignerInfoGenerator(sigId, contentSigner);
+ }
+ }
}
diff --git a/crypto/src/crypto/operators/Asn1Signature.cs b/crypto/src/crypto/operators/Asn1Signature.cs
index 0fd37b275..ba070f4fc 100644
--- a/crypto/src/crypto/operators/Asn1Signature.cs
+++ b/crypto/src/crypto/operators/Asn1Signature.cs
@@ -544,7 +544,7 @@ namespace Org.BouncyCastle.Crypto.Operators
public ISignatureVerifier CreateSignatureVerifier(Object algorithmDetails)
{
- return new Asn1SignatureVerifier ((AlgorithmIdentifier)algorithmDetails, publicKey);
+ return new Asn1SignatureVerifier ((AlgorithmIdentifier)algorithmDetails, publicKey);
}
/// <summary>
|