diff options
author | MW <megan@cryptoworkshop.com> | 2019-01-17 16:16:20 +1100 |
---|---|---|
committer | MW <megan@cryptoworkshop.com> | 2019-01-17 16:16:20 +1100 |
commit | 3d578b981aad94eaee07fa444dd11f9323026e94 (patch) | |
tree | d64141ae1163cafb69a4e3fc26ab90b538d98ef6 /crypto/src | |
parent | Missing from previous commit (diff) | |
download | BouncyCastle.NET-ed25519-3d578b981aad94eaee07fa444dd11f9323026e94.tar.xz |
CMS ArchiveControl
Diffstat (limited to 'crypto/src')
-rw-r--r-- | crypto/src/asn1/misc/MiscObjectIdentifiers.cs | 2 | ||||
-rw-r--r-- | crypto/src/cmp/RevocationDetails.cs | 39 | ||||
-rw-r--r-- | crypto/src/cmp/RevocationDetailsBuilder.cs | 58 | ||||
-rw-r--r-- | crypto/src/cms/CMSEnvelopedDataGenerator.cs | 71 | ||||
-rw-r--r-- | crypto/src/cms/CMSEnvelopedGenerator.cs | 10 | ||||
-rw-r--r-- | crypto/src/cms/CMSProcessableByteArray.cs | 17 | ||||
-rw-r--r-- | crypto/src/cms/EnvelopedDataHelper.cs | 123 | ||||
-rw-r--r-- | crypto/src/cms/RecipientInfoGenerator.cs | 2 | ||||
-rw-r--r-- | crypto/src/crmf/CertificateRequestMessage.cs | 4 | ||||
-rw-r--r-- | crypto/src/crmf/CertificateRequestMessageBuilder.cs | 9 | ||||
-rw-r--r-- | crypto/src/crmf/PKIArchiveControlBuilder.cs | 61 | ||||
-rw-r--r-- | crypto/src/crypto/operators/Asn1Signature.cs | 4 | ||||
-rw-r--r-- | crypto/src/crypto/operators/CipherFactory.cs | 146 | ||||
-rw-r--r-- | crypto/src/crypto/operators/CmsContentEncryptorBuilder.cs | 155 | ||||
-rw-r--r-- | crypto/src/crypto/util/AlgorithmIdentifierFactory.cs | 105 | ||||
-rw-r--r-- | crypto/src/crypto/util/CipherKeyGeneratorFactory.cs | 101 |
16 files changed, 900 insertions, 7 deletions
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 |