diff --git a/crypto/src/bcpg/ArmoredOutputStream.cs b/crypto/src/bcpg/ArmoredOutputStream.cs
index b3a32c6f5..5d4b6b5a7 100644
--- a/crypto/src/bcpg/ArmoredOutputStream.cs
+++ b/crypto/src/bcpg/ArmoredOutputStream.cs
@@ -36,46 +36,46 @@ namespace Org.BouncyCastle.Bcpg
* encode the input data producing a base 64 encoded byte array.
*/
private static void Encode(
- Stream outStream,
- int[] data,
- int len)
+ Stream outStream,
+ int[] data,
+ int len)
{
- Debug.Assert(len > 0);
- Debug.Assert(len < 4);
+ Debug.Assert(len > 0);
+ Debug.Assert(len < 4);
- byte[] bs = new byte[4];
- int d1 = data[0];
- bs[0] = encodingTable[(d1 >> 2) & 0x3f];
+ byte[] bs = new byte[4];
+ int d1 = data[0];
+ bs[0] = encodingTable[(d1 >> 2) & 0x3f];
- switch (len)
+ switch (len)
{
- case 1:
- {
- bs[1] = encodingTable[(d1 << 4) & 0x3f];
- bs[2] = (byte)'=';
- bs[3] = (byte)'=';
- break;
- }
- case 2:
- {
- int d2 = data[1];
- bs[1] = encodingTable[((d1 << 4) | (d2 >> 4)) & 0x3f];
- bs[2] = encodingTable[(d2 << 2) & 0x3f];
- bs[3] = (byte)'=';
- break;
- }
- case 3:
- {
- int d2 = data[1];
- int d3 = data[2];
- bs[1] = encodingTable[((d1 << 4) | (d2 >> 4)) & 0x3f];
- bs[2] = encodingTable[((d2 << 2) | (d3 >> 6)) & 0x3f];
- bs[3] = encodingTable[d3 & 0x3f];
- break;
- }
+ case 1:
+ {
+ bs[1] = encodingTable[(d1 << 4) & 0x3f];
+ bs[2] = (byte)'=';
+ bs[3] = (byte)'=';
+ break;
+ }
+ case 2:
+ {
+ int d2 = data[1];
+ bs[1] = encodingTable[((d1 << 4) | (d2 >> 4)) & 0x3f];
+ bs[2] = encodingTable[(d2 << 2) & 0x3f];
+ bs[3] = (byte)'=';
+ break;
+ }
+ case 3:
+ {
+ int d2 = data[1];
+ int d3 = data[2];
+ bs[1] = encodingTable[((d1 << 4) | (d2 >> 4)) & 0x3f];
+ bs[2] = encodingTable[((d2 << 2) | (d3 >> 6)) & 0x3f];
+ bs[3] = encodingTable[d3 & 0x3f];
+ break;
+ }
}
- outStream.Write(bs, 0, bs.Length);
+ outStream.Write(bs, 0, bs.Length);
}
private readonly Stream outStream;
@@ -91,18 +91,18 @@ namespace Org.BouncyCastle.Bcpg
private string type;
- private static readonly string nl = Platform.NewLine;
- private static readonly string headerStart = "-----BEGIN PGP ";
- private static readonly string headerTail = "-----";
- private static readonly string footerStart = "-----END PGP ";
- private static readonly string footerTail = "-----";
+ private static readonly string nl = Platform.NewLine;
+ private static readonly string headerStart = "-----BEGIN PGP ";
+ private static readonly string headerTail = "-----";
+ private static readonly string footerStart = "-----END PGP ";
+ private static readonly string footerTail = "-----";
private static readonly string version = "BCPG C# v"
- + Assembly.GetExecutingAssembly().GetName().Version;
+ + Assembly.GetExecutingAssembly().GetName().Version;
- private readonly IDictionary headers;
+ private readonly IDictionary headers;
- public ArmoredOutputStream(Stream outStream)
+ public ArmoredOutputStream(Stream outStream)
{
this.outStream = outStream;
this.headers = Platform.CreateHashtable();
@@ -174,10 +174,10 @@ namespace Org.BouncyCastle.Bcpg
throw new IOException("unknown hash algorithm tag in beginClearText: " + hashAlgorithm);
}
- DoWrite("-----BEGIN PGP SIGNED MESSAGE-----" + nl);
+ DoWrite("-----BEGIN PGP SIGNED MESSAGE-----" + nl);
DoWrite("Hash: " + hash + nl + nl);
- clearText = true;
+ clearText = true;
newLine = true;
lastb = 0;
}
@@ -218,7 +218,7 @@ namespace Org.BouncyCastle.Bcpg
{
bool newPacket = (b & 0x40) != 0;
- int tag;
+ int tag;
if (newPacket)
{
tag = b & 0x3f;
@@ -241,7 +241,7 @@ namespace Org.BouncyCastle.Bcpg
break;
default:
type = "MESSAGE";
- break;
+ break;
}
DoWrite(headerStart + type + headerTail + nl);
@@ -277,23 +277,23 @@ namespace Org.BouncyCastle.Bcpg
}
/**
- * <b>Note</b>: close does nor close the underlying stream. So it is possible to write
+ * <b>Note</b>: Close() does not close the underlying stream. So it is possible to write
* multiple objects using armoring to a single stream.
*/
public override void Close()
{
if (type != null)
{
- if (bufPtr > 0)
- {
- Encode(outStream, buf, bufPtr);
- }
+ if (bufPtr > 0)
+ {
+ Encode(outStream, buf, bufPtr);
+ }
DoWrite(nl + '=');
int crcV = crc.Value;
- buf[0] = ((crcV >> 16) & 0xff);
+ buf[0] = ((crcV >> 16) & 0xff);
buf[1] = ((crcV >> 8) & 0xff);
buf[2] = (crcV & 0xff);
@@ -309,22 +309,22 @@ namespace Org.BouncyCastle.Bcpg
type = null;
start = true;
- base.Close();
- }
+ base.Close();
+ }
}
- private void WriteHeaderEntry(
- string name,
- string v)
+ private void WriteHeaderEntry(
+ string name,
+ string v)
{
DoWrite(name + ": " + v + nl);
}
- private void DoWrite(
- string s)
+ private void DoWrite(
+ string s)
{
byte[] bs = Strings.ToAsciiByteArray(s);
- outStream.Write(bs, 0, bs.Length);
+ outStream.Write(bs, 0, bs.Length);
}
}
}
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>
diff --git a/crypto/src/openpgp/PgpKeyRingGenerator.cs b/crypto/src/openpgp/PgpKeyRingGenerator.cs
index e85fc2eef..92ea394a2 100644
--- a/crypto/src/openpgp/PgpKeyRingGenerator.cs
+++ b/crypto/src/openpgp/PgpKeyRingGenerator.cs
@@ -15,6 +15,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
private IList keys = Platform.CreateArrayList();
private string id;
private SymmetricKeyAlgorithmTag encAlgorithm;
+ private HashAlgorithmTag hashAlgorithm;
private int certificationLevel;
private char[] passPhrase;
private bool useSha1;
@@ -84,6 +85,45 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
keys.Add(new PgpSecretKey(certificationLevel, masterKey, id, encAlgorithm, passPhrase, useSha1, hashedPackets, unhashedPackets, rand));
}
+ /// <summary>
+ /// Create a new key ring generator.
+ /// </summary>
+ /// <param name="certificationLevel">The certification level for keys on this ring.</param>
+ /// <param name="masterKey">The master key pair.</param>
+ /// <param name="id">The id to be associated with the ring.</param>
+ /// <param name="encAlgorithm">The algorithm to be used to protect secret keys.</param>
+ /// <param name="hashAlgorithm">The hash algorithm.</param>
+ /// <param name="passPhrase">The passPhrase to be used to protect secret keys.</param>
+ /// <param name="useSha1">Checksum the secret keys with SHA1 rather than the older 16 bit checksum.</param>
+ /// <param name="hashedPackets">Packets to be included in the certification hash.</param>
+ /// <param name="unhashedPackets">Packets to be attached unhashed to the certification.</param>
+ /// <param name="rand">input secured random.</param>
+ public PgpKeyRingGenerator(
+ int certificationLevel,
+ PgpKeyPair masterKey,
+ string id,
+ SymmetricKeyAlgorithmTag encAlgorithm,
+ HashAlgorithmTag hashAlgorithm,
+ char[] passPhrase,
+ bool useSha1,
+ PgpSignatureSubpacketVector hashedPackets,
+ PgpSignatureSubpacketVector unhashedPackets,
+ SecureRandom rand)
+ {
+ this.certificationLevel = certificationLevel;
+ this.masterKey = masterKey;
+ this.id = id;
+ this.encAlgorithm = encAlgorithm;
+ this.passPhrase = passPhrase;
+ this.useSha1 = useSha1;
+ this.hashedPacketVector = hashedPackets;
+ this.unhashedPacketVector = unhashedPackets;
+ this.rand = rand;
+ this.hashAlgorithm = hashAlgorithm;
+
+ keys.Add(new PgpSecretKey(certificationLevel, masterKey, id, encAlgorithm, hashAlgorithm, passPhrase, useSha1, hashedPackets, unhashedPackets, rand));
+ }
+
/// <summary>Add a subkey to the key ring to be generated with default certification.</summary>
public void AddSubKey(
PgpKeyPair keyPair)
@@ -91,6 +131,17 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
AddSubKey(keyPair, this.hashedPacketVector, this.unhashedPacketVector);
}
+
+ /// <summary>
+ /// Add a subkey to the key ring to be generated with default certification.
+ /// </summary>
+ /// <param name="keyPair">The key pair.</param>
+ /// <param name="hashAlgorithm">The hash algorithm.</param>
+ public void AddSubKey(PgpKeyPair keyPair, HashAlgorithmTag hashAlgorithm)
+ {
+ this.AddSubKey(keyPair, this.hashedPacketVector, this.unhashedPacketVector, hashAlgorithm);
+ }
+
/// <summary>
/// Add a subkey with specific hashed and unhashed packets associated with it and
/// default certification.
@@ -133,6 +184,50 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
}
}
+ /// <summary>
+ /// Add a subkey with specific hashed and unhashed packets associated with it and
+ /// default certification.
+ /// </summary>
+ /// <param name="keyPair">Public/private key pair.</param>
+ /// <param name="hashedPackets">Hashed packet values to be included in certification.</param>
+ /// <param name="unhashedPackets">Unhashed packets values to be included in certification.</param>
+ /// <param name="hashAlgorithm">The hash algorithm.</param>
+ /// <exception cref="Org.BouncyCastle.Bcpg.OpenPgp.PgpException">exception adding subkey: </exception>
+ /// <exception cref="PgpException"></exception>
+ public void AddSubKey(
+ PgpKeyPair keyPair,
+ PgpSignatureSubpacketVector hashedPackets,
+ PgpSignatureSubpacketVector unhashedPackets,
+ HashAlgorithmTag hashAlgorithm)
+ {
+ try
+ {
+ var sGen = new PgpSignatureGenerator(masterKey.PublicKey.Algorithm, hashAlgorithm);
+
+ //
+ // Generate the certification
+ //
+ sGen.InitSign(PgpSignature.SubkeyBinding, masterKey.PrivateKey);
+
+ sGen.SetHashedSubpackets(hashedPackets);
+ sGen.SetUnhashedSubpackets(unhashedPackets);
+
+ IList subSigs = Platform.CreateArrayList();
+ subSigs.Add(sGen.GenerateCertification(masterKey.PublicKey, keyPair.PublicKey));
+
+ keys.Add(new PgpSecretKey(keyPair.PrivateKey, new PgpPublicKey(keyPair.PublicKey, null, subSigs), encAlgorithm, passPhrase, useSha1, rand));
+ }
+ catch (PgpException)
+ {
+ throw;
+ }
+ catch (Exception e)
+ {
+ throw new PgpException("exception adding subkey: ", e);
+ }
+ }
+
+
/// <summary>Return the secret key ring.</summary>
public PgpSecretKeyRing GenerateSecretKeyRing()
{
diff --git a/crypto/src/openpgp/PgpSecretKey.cs b/crypto/src/openpgp/PgpSecretKey.cs
index 980f9222b..1027393ce 100644
--- a/crypto/src/openpgp/PgpSecretKey.cs
+++ b/crypto/src/openpgp/PgpSecretKey.cs
@@ -166,6 +166,21 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
{
}
+ public PgpSecretKey(
+ int certificationLevel,
+ PgpKeyPair keyPair,
+ string id,
+ SymmetricKeyAlgorithmTag encAlgorithm,
+ HashAlgorithmTag hashAlgorithm,
+ char[] passPhrase,
+ bool useSha1,
+ PgpSignatureSubpacketVector hashedPackets,
+ PgpSignatureSubpacketVector unhashedPackets,
+ SecureRandom rand)
+ : this(keyPair.PrivateKey, CertifiedPublicKey(certificationLevel, keyPair, id, hashedPackets, unhashedPackets, hashAlgorithm), encAlgorithm, passPhrase, useSha1, rand, true)
+ {
+ }
+
private static PgpPublicKey CertifiedPublicKey(
int certificationLevel,
PgpKeyPair keyPair,
@@ -202,6 +217,44 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
}
}
+
+ private static PgpPublicKey CertifiedPublicKey(
+ int certificationLevel,
+ PgpKeyPair keyPair,
+ string id,
+ PgpSignatureSubpacketVector hashedPackets,
+ PgpSignatureSubpacketVector unhashedPackets,
+ HashAlgorithmTag hashAlgorithm)
+ {
+ PgpSignatureGenerator sGen;
+ try
+ {
+ sGen = new PgpSignatureGenerator(keyPair.PublicKey.Algorithm, hashAlgorithm);
+ }
+ catch (Exception e)
+ {
+ throw new PgpException("Creating signature generator: " + e.Message, e);
+ }
+
+ //
+ // Generate the certification
+ //
+ sGen.InitSign(certificationLevel, keyPair.PrivateKey);
+
+ sGen.SetHashedSubpackets(hashedPackets);
+ sGen.SetUnhashedSubpackets(unhashedPackets);
+
+ try
+ {
+ PgpSignature certification = sGen.GenerateCertification(id, keyPair.PublicKey);
+ return PgpPublicKey.AddCertification(keyPair.PublicKey, id, certification);
+ }
+ catch (Exception e)
+ {
+ throw new PgpException("Exception doing certification: " + e.Message, e);
+ }
+ }
+
public PgpSecretKey(
int certificationLevel,
PublicKeyAlgorithmTag algorithm,
@@ -611,6 +664,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
SymmetricKeyAlgorithmTag newEncAlgorithm,
SecureRandom rand)
{
+
if (key.IsPrivateKeyEmpty)
throw new PgpException("no private key in this SecretKey - public key present only.");
|