diff --git a/crypto/src/asn1/misc/MiscObjectIdentifiers.cs b/crypto/src/asn1/misc/MiscObjectIdentifiers.cs
index d344393dd..1ff19e737 100644
--- a/crypto/src/asn1/misc/MiscObjectIdentifiers.cs
+++ b/crypto/src/asn1/misc/MiscObjectIdentifiers.cs
@@ -50,6 +50,8 @@ namespace Org.BouncyCastle.Asn1.Misc
public static readonly string Entrust = "1.2.840.113533.7";
public static readonly DerObjectIdentifier EntrustVersionExtension = new DerObjectIdentifier(Entrust + ".65.0");
+ public static readonly DerObjectIdentifier cast5CBC = new DerObjectIdentifier(Entrust+ ".66.10");
+
//
// Ascom
//
diff --git a/crypto/src/cmp/RevocationDetails.cs b/crypto/src/cmp/RevocationDetails.cs
new file mode 100644
index 000000000..6e1cb34c3
--- /dev/null
+++ b/crypto/src/cmp/RevocationDetails.cs
@@ -0,0 +1,39 @@
+using Org.BouncyCastle.Asn1.Cmp;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Cmp
+{
+ public class RevocationDetails
+ {
+ private RevDetails revDetails;
+
+ public RevocationDetails(RevDetails revDetails)
+ {
+ this.revDetails = revDetails;
+ }
+
+ public X509Name Subject
+ {
+ get { return revDetails.CertDetails.Subject; }
+ }
+
+ public X509Name Issuer
+ {
+ get { return revDetails.CertDetails.Issuer; }
+ }
+
+ public BigInteger SerialNumber
+ {
+ get
+ {
+ return revDetails.CertDetails.SerialNumber.Value; // getCertDetails().getSerialNumber().getValue();
+ }
+ }
+
+ public RevDetails ToASN1Structure()
+ {
+ return revDetails;
+ }
+ }
+}
\ No newline at end of file
diff --git a/crypto/src/cmp/RevocationDetailsBuilder.cs b/crypto/src/cmp/RevocationDetailsBuilder.cs
new file mode 100644
index 000000000..464c0bb13
--- /dev/null
+++ b/crypto/src/cmp/RevocationDetailsBuilder.cs
@@ -0,0 +1,58 @@
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Cmp;
+using Org.BouncyCastle.Asn1.Crmf;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Cmp
+{
+ public class RevocationDetailsBuilder
+ {
+ private readonly CertTemplateBuilder _templateBuilder = new CertTemplateBuilder();
+
+ public RevocationDetailsBuilder SetPublicKey(SubjectPublicKeyInfo publicKey)
+ {
+ if (publicKey != null)
+ {
+ _templateBuilder.SetPublicKey(publicKey);
+ }
+
+ return this;
+ }
+
+ public RevocationDetailsBuilder SetIssuer(X509Name issuer)
+ {
+ if (issuer != null)
+ {
+ _templateBuilder.SetIssuer(issuer);
+ }
+
+ return this;
+ }
+
+ public RevocationDetailsBuilder SetSerialNumber(BigInteger serialNumber)
+ {
+ if (serialNumber != null)
+ {
+ _templateBuilder.SetSerialNumber(new DerInteger(serialNumber));
+ }
+
+ return this;
+ }
+
+ public RevocationDetailsBuilder SetSubject(X509Name subject)
+ {
+ if (subject != null)
+ {
+ _templateBuilder.SetSubject(subject);
+ }
+
+ return this;
+ }
+
+ public RevocationDetails build()
+ {
+ return new RevocationDetails(new RevDetails(_templateBuilder.Build()));
+ }
+ }
+}
\ No newline at end of file
diff --git a/crypto/src/cms/CMSEnvelopedDataGenerator.cs b/crypto/src/cms/CMSEnvelopedDataGenerator.cs
index d260e998a..8ba41161e 100644
--- a/crypto/src/cms/CMSEnvelopedDataGenerator.cs
+++ b/crypto/src/cms/CMSEnvelopedDataGenerator.cs
@@ -144,7 +144,7 @@ namespace Org.BouncyCastle.Cms
try
{
CipherKeyGenerator keyGen = GeneratorUtilities.GetKeyGenerator(encryptionOid);
-
+
keyGen.Init(new KeyGenerationParameters(rand, keyGen.DefaultStrength));
return Generate(content, encryptionOid, keyGen);
@@ -155,6 +155,75 @@ namespace Org.BouncyCastle.Cms
}
}
+
+ public CmsEnvelopedData Generate(CmsProcessable content, ICipherBuilderWithKey cipherBuilder)
+ {
+ AlgorithmIdentifier encAlgId = null;
+ KeyParameter encKey;
+ Asn1OctetString encContent;
+
+ try
+ {
+ encKey = (KeyParameter) cipherBuilder.Key;
+
+ MemoryStream collector = new MemoryStream();
+ Stream bOut = cipherBuilder.BuildCipher(collector).Stream;
+ content.Write(bOut);
+ Platform.Dispose(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, rand));
+ }
+ 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(Platform.CreateHashtable());
+
+ 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,
diff --git a/crypto/src/cms/CMSEnvelopedGenerator.cs b/crypto/src/cms/CMSEnvelopedGenerator.cs
index f92ae3824..ed7e1edee 100644
--- a/crypto/src/cms/CMSEnvelopedGenerator.cs
+++ b/crypto/src/cms/CMSEnvelopedGenerator.cs
@@ -263,6 +263,16 @@ namespace Org.BouncyCastle.Cms
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,
diff --git a/crypto/src/cms/CMSProcessableByteArray.cs b/crypto/src/cms/CMSProcessableByteArray.cs
index a6ab9b6a2..b09935dd8 100644
--- a/crypto/src/cms/CMSProcessableByteArray.cs
+++ b/crypto/src/cms/CMSProcessableByteArray.cs
@@ -1,5 +1,7 @@
using System;
using System.IO;
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Cms;
namespace Org.BouncyCastle.Cms
{
@@ -9,13 +11,26 @@ namespace Org.BouncyCastle.Cms
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);
diff --git a/crypto/src/cms/EnvelopedDataHelper.cs b/crypto/src/cms/EnvelopedDataHelper.cs
new file mode 100644
index 000000000..89ec79691
--- /dev/null
+++ b/crypto/src/cms/EnvelopedDataHelper.cs
@@ -0,0 +1,123 @@
+using System.Collections;
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.Oiw;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Operators;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Utilities;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Cms
+{
+ public class EnvelopedDataHelper
+ {
+ private static readonly IDictionary BaseCipherNames = Platform.CreateHashtable();
+ private static readonly IDictionary MacAlgNames = Platform.CreateHashtable();
+
+ private static readonly IDictionary prfs = Platform.CreateHashtable();
+
+
+ public delegate IDigest DigestCreator();
+
+ static EnvelopedDataHelper()
+ {
+ prfs.Add(PkcsObjectIdentifiers.IdHmacWithSha1, new DigestProvider(delegate () { return new Sha1Digest(); }));
+ prfs.Add(PkcsObjectIdentifiers.IdHmacWithSha224, new DigestProvider(delegate () { return new Sha224Digest(); }));
+ prfs.Add(PkcsObjectIdentifiers.IdHmacWithSha256, new DigestProvider(delegate () { return new Sha256Digest(); }));
+ prfs.Add(PkcsObjectIdentifiers.IdHmacWithSha384, new DigestProvider(delegate () { return new Sha384Digest(); }));
+ prfs.Add(PkcsObjectIdentifiers.IdHmacWithSha512, new DigestProvider(delegate () { return new Sha512Digest(); }));
+
+
+ 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");
+ }
+
+ static IDigest GetPrf(AlgorithmIdentifier algID)
+ {
+ return ((DigestCreator)prfs[algID]).Invoke();
+ }
+
+
+ static IWrapper CreateRFC3211Wrapper(DerObjectIdentifier algorithm)
+
+ {
+ if (NistObjectIdentifiers.IdAes128Cbc.Equals(algorithm)
+ || NistObjectIdentifiers.IdAes192Cbc.Equals(algorithm)
+ || NistObjectIdentifiers.IdAes256Cbc.Equals(algorithm))
+ {
+ return new Rfc3211WrapEngine(new AesEngine());
+ }
+ 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);
+ }
+
+
+ }
+
+ // This exists because we can't directly put a delegate in a map as it is
+ // not an object.
+ internal class DigestProvider
+ {
+ private readonly EnvelopedDataHelper.DigestCreator creator;
+
+ public DigestProvider(EnvelopedDataHelper.DigestCreator creator)
+ {
+ this.creator = creator;
+ }
+
+ public IDigest Create()
+ {
+ return creator.Invoke();
+ }
+ }
+}
\ No newline at end of file
diff --git a/crypto/src/cms/RecipientInfoGenerator.cs b/crypto/src/cms/RecipientInfoGenerator.cs
index c41db6122..75f5dcc33 100644
--- a/crypto/src/cms/RecipientInfoGenerator.cs
+++ b/crypto/src/cms/RecipientInfoGenerator.cs
@@ -6,7 +6,7 @@ using Org.BouncyCastle.Security;
namespace Org.BouncyCastle.Cms
{
- interface RecipientInfoGenerator
+ public interface RecipientInfoGenerator
{
/// <summary>
/// Generate a RecipientInfo object for the given key.
diff --git a/crypto/src/crmf/CertificateRequestMessage.cs b/crypto/src/crmf/CertificateRequestMessage.cs
index 087e8a933..5b5d37c9e 100644
--- a/crypto/src/crmf/CertificateRequestMessage.cs
+++ b/crypto/src/crmf/CertificateRequestMessage.cs
@@ -211,8 +211,8 @@ namespace Org.BouncyCastle.Crmf
calculator.Stream.Write(b,0,b.Length);
}
else
- {
- byte[] b = certReqMsg.GetDerEncoded();
+ {
+ byte[] b = certReqMsg.CertReq.GetDerEncoded();
calculator.Stream.Write(b,0,b.Length);
}
diff --git a/crypto/src/crmf/CertificateRequestMessageBuilder.cs b/crypto/src/crmf/CertificateRequestMessageBuilder.cs
index 384f6a965..9c3cf954d 100644
--- a/crypto/src/crmf/CertificateRequestMessageBuilder.cs
+++ b/crypto/src/crmf/CertificateRequestMessageBuilder.cs
@@ -95,6 +95,12 @@ namespace Org.BouncyCastle.Crmf
return this;
}
+ public CertificateRequestMessageBuilder AddControl(IControl control)
+ {
+ _controls.Add(control);
+ return this;
+ }
+
public CertificateRequestMessageBuilder SetProofOfPossessionSignKeySigner(ISignatureFactory popoSignatureFactory)
{
if (_popoPrivKey != null || _popRaVerified != null || _agreeMac != null)
@@ -102,7 +108,8 @@ namespace Org.BouncyCastle.Crmf
throw new InvalidOperationException("only one proof of possession is allowed.");
}
- this._popoType = ProofOfPossession.TYPE_KEY_ENCIPHERMENT;
+ this._popSigner = popoSignatureFactory;
+
return this;
}
diff --git a/crypto/src/crmf/PKIArchiveControlBuilder.cs b/crypto/src/crmf/PKIArchiveControlBuilder.cs
new file mode 100644
index 000000000..f43ecd4ec
--- /dev/null
+++ b/crypto/src/crmf/PKIArchiveControlBuilder.cs
@@ -0,0 +1,61 @@
+using System;
+using System.IO;
+using Org.BouncyCastle.Asn1.Cms;
+using Org.BouncyCastle.Asn1.Crmf;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Cms;
+using Org.BouncyCastle.Crypto;
+
+namespace Org.BouncyCastle.Crmf
+{
+ public class PKIArchiveControlBuilder
+ {
+ private CmsEnvelopedDataGenerator envGen;
+ private CmsProcessableByteArray keyContent;
+
+ /// <summary>
+ ///Basic constructor - specify the contents of the PKIArchiveControl structure.
+ /// </summary>
+ /// <param name="privateKeyInfo">the private key to be archived.</param>
+ /// <param name="generalName">the general name to be associated with the private key.</param>
+ ///
+ public PKIArchiveControlBuilder(PrivateKeyInfo privateKeyInfo, GeneralName generalName)
+ {
+ EncKeyWithID encKeyWithID = new EncKeyWithID(privateKeyInfo, generalName);
+
+ try
+ {
+ this.keyContent = new CmsProcessableByteArray(CrmfObjectIdentifiers.id_ct_encKeyWithID, encKeyWithID.GetEncoded());
+ }
+ catch (IOException e)
+ {
+ throw new InvalidOperationException("unable to encode key and general name info");
+ }
+
+ this.envGen = new CmsEnvelopedDataGenerator();
+ }
+
+
+
+
+ ///<summary>Add a recipient generator to this control.</summary>
+ ///<param name="recipientGen"> recipient generator created for a specific recipient.</param>
+ ///<returns>this builder object.</returns>
+ public PKIArchiveControlBuilder AddRecipientGenerator(RecipientInfoGenerator recipientGen)
+ {
+ envGen.AddRecipientInfoGenerator(recipientGen);
+ return this;
+ }
+
+ /// <summary>Build the PKIArchiveControl using the passed in encryptor to encrypt its contents.</summary>
+ /// <param name="contentEncryptor">a suitable content encryptor.</param>
+ /// <returns>a PKIArchiveControl object.</returns>
+ public PkiArchiveControl Build(ICipherBuilderWithKey contentEncryptor)
+ {
+ CmsEnvelopedData envContent = envGen.Generate(keyContent, contentEncryptor);
+ EnvelopedData envD = EnvelopedData.GetInstance(envContent.ContentInfo.Content);
+ return new PkiArchiveControl(new PkiArchiveOptions(new EncryptedKey(envD)));
+ }
+}
+}
\ No newline at end of file
diff --git a/crypto/src/crypto/operators/Asn1Signature.cs b/crypto/src/crypto/operators/Asn1Signature.cs
index 3962a4a15..66050789e 100644
--- a/crypto/src/crypto/operators/Asn1Signature.cs
+++ b/crypto/src/crypto/operators/Asn1Signature.cs
@@ -12,6 +12,7 @@ using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Asn1.X9;
using Org.BouncyCastle.Crypto.IO;
using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Signers;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.Collections;
@@ -346,7 +347,8 @@ namespace Org.BouncyCastle.Crypto.Operators
}
public IStreamCalculator CreateCalculator()
- {
+ {
+
ISigner verifier = SignerUtilities.InitSigner(X509Utilities.GetSignatureName(algID), false, publicKey, null);
return new DefaultVerifierCalculator(verifier);
diff --git a/crypto/src/crypto/operators/CipherFactory.cs b/crypto/src/crypto/operators/CipherFactory.cs
new file mode 100644
index 000000000..11a9faef9
--- /dev/null
+++ b/crypto/src/crypto/operators/CipherFactory.cs
@@ -0,0 +1,146 @@
+using System;
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Kisa;
+using Org.BouncyCastle.Asn1.Misc;
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.Ntt;
+using Org.BouncyCastle.Asn1.Oiw;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Modes;
+using Org.BouncyCastle.Crypto.Paddings;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Operators
+{
+ public class CipherFactory
+ {
+ private 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
+ };
+
+ public static object CreateContentCipher(bool forEncryption, ICipherParameters encKey,
+ AlgorithmIdentifier encryptionAlgID)
+ {
+ DerObjectIdentifier encAlg = encryptionAlgID.Algorithm;
+
+ if (encAlg.Equals(PkcsObjectIdentifiers.Rc4))
+ {
+ IStreamCipher cipher = new RC4Engine();
+
+ cipher.Init(forEncryption, encKey);
+
+ return cipher;
+ }
+ else
+ {
+ BufferedBlockCipher cipher = CreateCipher(encryptionAlgID.Algorithm);
+
+ Asn1Object sParams = encryptionAlgID.Parameters.ToAsn1Object();
+
+ if (sParams != null && !(sParams is DerNull))
+ {
+ if (encAlg.Equals(PkcsObjectIdentifiers.DesEde3Cbc)
+ || encAlg.Equals(AlgorithmIdentifierFactory.IDEA_CBC)
+ || encAlg.Equals(NistObjectIdentifiers.IdAes128Cbc)
+ || encAlg.Equals(NistObjectIdentifiers.IdAes192Cbc)
+ || encAlg.Equals(NistObjectIdentifiers.IdAes256Cbc)
+ || encAlg.Equals(NttObjectIdentifiers.IdCamellia128Cbc)
+ || encAlg.Equals(NttObjectIdentifiers.IdCamellia192Cbc)
+ || encAlg.Equals(NttObjectIdentifiers.IdCamellia256Cbc)
+ || encAlg.Equals(KisaObjectIdentifiers.IdSeedCbc)
+ || encAlg.Equals(OiwObjectIdentifiers.DesCbc))
+ {
+ cipher.Init(forEncryption, new ParametersWithIV(encKey,
+ Asn1OctetString.GetInstance(sParams).GetOctets()));
+ }
+ else if (encAlg.Equals(AlgorithmIdentifierFactory.CAST5_CBC))
+ {
+ Cast5CbcParameters cbcParams = Cast5CbcParameters.GetInstance(sParams);
+
+ cipher.Init(forEncryption, new ParametersWithIV(encKey, cbcParams.GetIV()));
+ }
+ else if (encAlg.Equals(PkcsObjectIdentifiers.RC2Cbc))
+ {
+ RC2CbcParameter cbcParams = RC2CbcParameter.GetInstance(sParams);
+
+ cipher.Init(forEncryption, new ParametersWithIV(new RC2Parameters(((KeyParameter)encKey).GetKey(), rc2Ekb[cbcParams.RC2ParameterVersion.IntValue]), cbcParams.GetIV()));
+ }
+ else
+ {
+ throw new InvalidOperationException("cannot match parameters");
+ }
+ }
+ else
+ {
+ if (encAlg.Equals(PkcsObjectIdentifiers.DesEde3Cbc)
+ || encAlg.Equals(AlgorithmIdentifierFactory.IDEA_CBC)
+ || encAlg.Equals(AlgorithmIdentifierFactory.CAST5_CBC))
+ {
+ cipher.Init(forEncryption, new ParametersWithIV(encKey, new byte[8]));
+ }
+ else
+ {
+ cipher.Init(forEncryption, encKey);
+ }
+ }
+
+ return cipher;
+ }
+
+ }
+
+ private static BufferedBlockCipher CreateCipher(DerObjectIdentifier algorithm)
+ {
+ IBlockCipher cipher;
+
+ if (NistObjectIdentifiers.IdAes128Cbc.Equals(algorithm)
+ || NistObjectIdentifiers.IdAes192Cbc.Equals(algorithm)
+ || NistObjectIdentifiers.IdAes256Cbc.Equals(algorithm))
+ {
+ cipher = new CbcBlockCipher(new AesEngine());
+ }
+ else if (PkcsObjectIdentifiers.DesEde3Cbc.Equals(algorithm))
+ {
+ cipher = new CbcBlockCipher(new DesEdeEngine());
+ }
+ else if (OiwObjectIdentifiers.DesCbc.Equals(algorithm))
+ {
+ cipher = new CbcBlockCipher(new DesEngine());
+ }
+ else if (PkcsObjectIdentifiers.RC2Cbc.Equals(algorithm))
+ {
+ cipher = new CbcBlockCipher(new RC2Engine());
+ }
+ else if (MiscObjectIdentifiers.cast5CBC.Equals(algorithm))
+ {
+ cipher = new CbcBlockCipher(new Cast5Engine());
+ }
+ else
+ {
+ throw new InvalidOperationException("cannot recognise cipher: " + algorithm);
+ }
+
+ return new PaddedBufferedBlockCipher(cipher, new Pkcs7Padding());
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/crypto/src/crypto/operators/CmsContentEncryptorBuilder.cs b/crypto/src/crypto/operators/CmsContentEncryptorBuilder.cs
new file mode 100644
index 000000000..f7ddf4db6
--- /dev/null
+++ b/crypto/src/crypto/operators/CmsContentEncryptorBuilder.cs
@@ -0,0 +1,155 @@
+using System.Collections;
+using System.IO;
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.Ntt;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Cms;
+using Org.BouncyCastle.Crypto.IO;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Operators
+{
+ public class CmsContentEncryptorBuilder
+ {
+ private static readonly IDictionary keySizes = Platform.CreateHashtable();
+
+ static CmsContentEncryptorBuilder()
+ {
+ keySizes[NistObjectIdentifiers.IdAes128Cbc] = 128;
+ keySizes[NistObjectIdentifiers.IdAes192Cbc] =192;
+ keySizes[NistObjectIdentifiers.IdAes256Cbc] =256;
+
+
+ keySizes[NttObjectIdentifiers.IdCamellia128Cbc] =128;
+ keySizes[NttObjectIdentifiers.IdCamellia192Cbc] =192;
+ keySizes[NttObjectIdentifiers.IdCamellia256Cbc] =256;
+ }
+
+ private static int getKeySize(DerObjectIdentifier oid)
+ {
+ if (keySizes.Contains(oid))
+ {
+ return (int)keySizes[oid];
+ }
+
+ return -1;
+ }
+
+ private readonly DerObjectIdentifier encryptionOID;
+ private readonly int keySize;
+
+
+ private EnvelopedDataHelper helper = new EnvelopedDataHelper();
+ private SecureRandom random;
+
+ public CmsContentEncryptorBuilder(DerObjectIdentifier encryptionOID):this(encryptionOID, getKeySize(encryptionOID)) {
+ }
+
+ public CmsContentEncryptorBuilder(DerObjectIdentifier encryptionOID, int keySize)
+ {
+ this.encryptionOID = encryptionOID;
+ this.keySize = keySize;
+ }
+
+ public ICipherBuilderWithKey Build()
+ {
+ return new DefaultCipherBuilderWithKey(encryptionOID,keySize,random,new EnvelopedDataHelper());
+ }
+
+ }
+
+ public class DefaultCipherBuilderWithKey:ICipherBuilderWithKey
+ {
+
+ private readonly KeyParameter encKey;
+ private AlgorithmIdentifier algorithmIdentifier;
+
+
+
+
+ public DefaultCipherBuilderWithKey(DerObjectIdentifier encryptionOID, int keySize, SecureRandom random,EnvelopedDataHelper helper)
+ {
+ if (random == null)
+ {
+ random= new SecureRandom();
+ }
+
+ CipherKeyGenerator keyGen = helper.CreateKeyGenerator(encryptionOID, random);
+ encKey = new KeyParameter(keyGen.GenerateKey());
+ algorithmIdentifier = helper.GenerateEncryptionAlgID(encryptionOID, encKey, random);
+ // cipher = EnvelopedDataHelper.CreateContentCipher(true, encKey, algorithmIdentifier);
+ }
+
+
+ public object AlgorithmDetails
+ {
+ get { return algorithmIdentifier; }
+ }
+ public int GetMaxOutputSize(int inputLen)
+ {
+ throw new System.NotImplementedException();
+ }
+
+ public ICipher BuildCipher(Stream stream)
+ {
+
+ object cipher = EnvelopedDataHelper.CreateContentCipher(true, encKey, algorithmIdentifier);
+
+ //
+ // BufferedBlockCipher
+ // IStreamCipher
+ //
+
+ if (cipher is IStreamCipher)
+ {
+ cipher = new BufferedStreamCipher((IStreamCipher)cipher);
+ }
+
+ if (stream == null)
+ {
+ stream = new MemoryStream();
+ }
+
+ return new BufferedCipherWrapper((IBufferedCipher)cipher,stream);
+ }
+
+ public ICipherParameters Key
+ {
+ get { return encKey; }
+ }
+ }
+
+ public class BufferedCipherWrapper : ICipher
+ {
+ private readonly IBufferedCipher bufferedCipher;
+ private readonly CipherStream stream;
+
+ public BufferedCipherWrapper(IBufferedCipher bufferedCipher, Stream source)
+ {
+ this.bufferedCipher = bufferedCipher;
+ stream = new CipherStream(source, bufferedCipher, bufferedCipher);
+ }
+
+ public int GetMaxOutputSize(int inputLen)
+ {
+ return bufferedCipher.GetOutputSize(inputLen);
+ }
+
+ public int GetUpdateOutputSize(int inputLen)
+ {
+ return bufferedCipher.GetUpdateOutputSize(inputLen);
+ }
+
+ public Stream Stream
+ {
+ get { return stream; }
+ }
+ }
+
+
+
+
+}
\ No newline at end of file
diff --git a/crypto/src/crypto/util/AlgorithmIdentifierFactory.cs b/crypto/src/crypto/util/AlgorithmIdentifierFactory.cs
new file mode 100644
index 000000000..73458f0ea
--- /dev/null
+++ b/crypto/src/crypto/util/AlgorithmIdentifierFactory.cs
@@ -0,0 +1,105 @@
+using System;
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Kisa;
+using Org.BouncyCastle.Asn1.Misc;
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.Ntt;
+using Org.BouncyCastle.Asn1.Oiw;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Utilities
+{
+ public class AlgorithmIdentifierFactory
+ {
+ public static readonly DerObjectIdentifier IDEA_CBC = new DerObjectIdentifier("1.3.6.1.4.1.188.7.1.1.2");
+ public static readonly DerObjectIdentifier CAST5_CBC = new DerObjectIdentifier("1.2.840.113533.7.66.10");
+
+ private 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
+ };
+
+
+ /**
+ * Create an AlgorithmIdentifier for the passed in encryption algorithm.
+ *
+ * @param encryptionOID OID for the encryption algorithm
+ * @param keySize key size in bits (-1 if unknown)
+ * @param random SecureRandom to use for parameter generation.
+ * @return a full AlgorithmIdentifier including parameters
+ * @throws IllegalArgumentException if encryptionOID cannot be matched
+ */
+ public static AlgorithmIdentifier GenerateEncryptionAlgID(DerObjectIdentifier encryptionOID, int keySize, SecureRandom random)
+
+ {
+ if (encryptionOID.Equals(NistObjectIdentifiers.IdAes128Cbc)
+ || encryptionOID.Equals(NistObjectIdentifiers.IdAes192Cbc)
+ || encryptionOID.Equals(NistObjectIdentifiers.IdAes256Cbc)
+ || encryptionOID.Equals(NttObjectIdentifiers.IdCamellia128Cbc)
+ || encryptionOID.Equals(NttObjectIdentifiers.IdCamellia192Cbc)
+ || encryptionOID.Equals(NttObjectIdentifiers.IdCamellia256Cbc)
+ || encryptionOID.Equals(KisaObjectIdentifiers.IdSeedCbc))
+ {
+ byte[] iv = new byte[16];
+
+ random.NextBytes(iv);
+
+ return new AlgorithmIdentifier(encryptionOID, new DerOctetString(iv));
+ }
+ else if (encryptionOID.Equals(PkcsObjectIdentifiers.DesEde3Cbc)
+ || encryptionOID.Equals(IDEA_CBC)
+ || encryptionOID.Equals(OiwObjectIdentifiers.DesCbc))
+ {
+ byte[] iv = new byte[8];
+
+ random.NextBytes(iv);
+
+ return new AlgorithmIdentifier(encryptionOID, new DerOctetString(iv));
+ }
+ else if (encryptionOID.Equals(CAST5_CBC))
+ {
+ byte[] iv = new byte[8];
+
+ random.NextBytes(iv);
+
+ Cast5CbcParameters cbcParams = new Cast5CbcParameters(iv, keySize);
+
+ return new AlgorithmIdentifier(encryptionOID, cbcParams);
+ }
+ else if (encryptionOID.Equals(PkcsObjectIdentifiers.Rc4))
+ {
+ return new AlgorithmIdentifier(encryptionOID, DerNull.Instance);
+ }
+ else if (encryptionOID.Equals(PkcsObjectIdentifiers.RC2Cbc))
+ {
+ byte[] iv = new byte[8];
+
+ random.NextBytes(iv);
+
+ RC2CbcParameter cbcParams = new RC2CbcParameter(rc2Table[128], iv);
+
+ return new AlgorithmIdentifier(encryptionOID, cbcParams);
+ }
+ else
+ {
+ throw new InvalidOperationException("unable to match algorithm");
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/crypto/src/crypto/util/CipherKeyGeneratorFactory.cs b/crypto/src/crypto/util/CipherKeyGeneratorFactory.cs
new file mode 100644
index 000000000..7a24a01a8
--- /dev/null
+++ b/crypto/src/crypto/util/CipherKeyGeneratorFactory.cs
@@ -0,0 +1,101 @@
+using System;
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Kisa;
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.Ntt;
+using Org.BouncyCastle.Asn1.Oiw;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Utilities
+{
+ public class CipherKeyGeneratorFactory
+ {
+
+ /**
+ * Create a key generator for the passed in Object Identifier.
+ *
+ * @param algorithm the Object Identifier indicating the algorithn the generator is for.
+ * @param random a source of random to initialise the generator with.
+ * @return an initialised CipherKeyGenerator.
+ * @throws IllegalArgumentException if the algorithm cannot be identified.
+ */
+ public static CipherKeyGenerator CreateKeyGenerator(DerObjectIdentifier algorithm, SecureRandom random)
+
+ {
+ if (NistObjectIdentifiers.IdAes128Cbc.Equals(algorithm))
+ {
+ return createCipherKeyGenerator(random, 128);
+ }
+ else if (NistObjectIdentifiers.IdAes192Cbc.Equals(algorithm))
+ {
+ return createCipherKeyGenerator(random, 192);
+ }
+ else if (NistObjectIdentifiers.IdAes256Cbc.Equals(algorithm))
+ {
+ return createCipherKeyGenerator(random, 256);
+ }
+ else if (PkcsObjectIdentifiers.DesEde3Cbc.Equals(algorithm))
+ {
+ DesEdeKeyGenerator keyGen = new DesEdeKeyGenerator();
+
+ keyGen.Init(new KeyGenerationParameters(random, 192));
+
+ return keyGen;
+ }
+ else if (NttObjectIdentifiers.IdCamellia128Cbc.Equals(algorithm))
+ {
+ return createCipherKeyGenerator(random, 128);
+ }
+ else if (NttObjectIdentifiers.IdCamellia192Cbc.Equals(algorithm))
+ {
+ return createCipherKeyGenerator(random, 192);
+ }
+ else if (NttObjectIdentifiers.IdCamellia256Cbc.Equals(algorithm))
+ {
+ return createCipherKeyGenerator(random, 256);
+ }
+ else if (KisaObjectIdentifiers.IdSeedCbc.Equals(algorithm))
+ {
+ return createCipherKeyGenerator(random, 128);
+ }
+ else if (AlgorithmIdentifierFactory.CAST5_CBC.Equals(algorithm))
+ {
+ return createCipherKeyGenerator(random, 128);
+ }
+ else if (OiwObjectIdentifiers.DesCbc.Equals(algorithm))
+ {
+ DesKeyGenerator keyGen = new DesKeyGenerator();
+
+ keyGen.Init(new KeyGenerationParameters(random, 64));
+
+ return keyGen;
+ }
+ else if (PkcsObjectIdentifiers.Rc4.Equals(algorithm))
+ {
+ return createCipherKeyGenerator(random, 128);
+ }
+ else if (PkcsObjectIdentifiers.RC2Cbc.Equals(algorithm))
+ {
+ return createCipherKeyGenerator(random, 128);
+ }
+ else
+ {
+ throw new InvalidOperationException("cannot recognise cipher: " + algorithm);
+ }
+ }
+
+
+
+
+ private static CipherKeyGenerator createCipherKeyGenerator(SecureRandom random, int keySize)
+ {
+ CipherKeyGenerator keyGen = new CipherKeyGenerator();
+
+ keyGen.Init(new KeyGenerationParameters(random, keySize));
+
+ return keyGen;
+ }
+ }
+}
\ No newline at end of file
|