From 714e5ef11e2ea6f0aa6cdd0dcb9987d8a7faea54 Mon Sep 17 00:00:00 2001 From: David Hook Date: Fri, 18 Jan 2019 12:37:12 +1100 Subject: added use of IKeyWrapper for managing CMS KeyTransRecipient --- crypto/src/asn1/pkcs/PKCSObjectIdentifiers.cs | 2 +- crypto/src/cms/EnvelopedDataHelper.cs | 6 +- crypto/src/cms/KeyTransRecipientInfoGenerator.cs | 174 ++++++++++++--------- crypto/src/crmf/EncryptedValueBuilder.cs | 1 + crypto/src/crypto/operators/Asn1CipherBuilder.cs | 100 ++++++++++++ crypto/src/crypto/operators/Asn1KeyWrapper.cs | 48 ++++++ crypto/src/crypto/operators/CipherFactory.cs | 146 ----------------- .../crypto/operators/CmsContentEncryptorBuilder.cs | 101 +----------- .../operators/CmsKeyTransRecipientInfoGenerator.cs | 36 +++++ .../src/crypto/util/AlgorithmIdentifierFactory.cs | 2 +- crypto/src/crypto/util/CipherFactory.cs | 151 ++++++++++++++++++ .../src/crypto/util/CipherKeyGeneratorFactory.cs | 10 +- 12 files changed, 454 insertions(+), 323 deletions(-) create mode 100644 crypto/src/crypto/operators/Asn1CipherBuilder.cs create mode 100644 crypto/src/crypto/operators/Asn1KeyWrapper.cs delete mode 100644 crypto/src/crypto/operators/CipherFactory.cs create mode 100644 crypto/src/crypto/operators/CmsKeyTransRecipientInfoGenerator.cs create mode 100644 crypto/src/crypto/util/CipherFactory.cs diff --git a/crypto/src/asn1/pkcs/PKCSObjectIdentifiers.cs b/crypto/src/asn1/pkcs/PKCSObjectIdentifiers.cs index 615091f7c..a991585f6 100644 --- a/crypto/src/asn1/pkcs/PKCSObjectIdentifiers.cs +++ b/crypto/src/asn1/pkcs/PKCSObjectIdentifiers.cs @@ -62,7 +62,7 @@ namespace Org.BouncyCastle.Asn1.Pkcs public static readonly DerObjectIdentifier DesEde3Cbc = new DerObjectIdentifier(EncryptionAlgorithm + ".7"); public static readonly DerObjectIdentifier RC2Cbc = new DerObjectIdentifier(EncryptionAlgorithm + ".2"); - public static readonly DerObjectIdentifier Rc4 = new DerObjectIdentifier(EncryptionAlgorithm + ".4"); + public static readonly DerObjectIdentifier rc4 = new DerObjectIdentifier(EncryptionAlgorithm + ".4"); // // object identifiers for digests diff --git a/crypto/src/cms/EnvelopedDataHelper.cs b/crypto/src/cms/EnvelopedDataHelper.cs index 89ec79691..fe5bc2a97 100644 --- a/crypto/src/cms/EnvelopedDataHelper.cs +++ b/crypto/src/cms/EnvelopedDataHelper.cs @@ -12,10 +12,11 @@ using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Crypto.Utilities; using Org.BouncyCastle.Security; using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Crypto.Utilites; namespace Org.BouncyCastle.Cms { - public class EnvelopedDataHelper + internal class EnvelopedDataHelper { private static readonly IDictionary BaseCipherNames = Platform.CreateHashtable(); private static readonly IDictionary MacAlgNames = Platform.CreateHashtable(); @@ -90,7 +91,6 @@ namespace Org.BouncyCastle.Cms public AlgorithmIdentifier GenerateEncryptionAlgID(DerObjectIdentifier encryptionOID, KeyParameter encKey, SecureRandom random) - { return AlgorithmIdentifierFactory.GenerateEncryptionAlgID(encryptionOID, encKey.GetKey().Length * 8, random); } @@ -120,4 +120,4 @@ namespace Org.BouncyCastle.Cms return creator.Invoke(); } } -} \ No newline at end of file +} diff --git a/crypto/src/cms/KeyTransRecipientInfoGenerator.cs b/crypto/src/cms/KeyTransRecipientInfoGenerator.cs index a1d8fbfa8..b18d18153 100644 --- a/crypto/src/cms/KeyTransRecipientInfoGenerator.cs +++ b/crypto/src/cms/KeyTransRecipientInfoGenerator.cs @@ -11,77 +11,109 @@ using Org.BouncyCastle.X509; namespace Org.BouncyCastle.Cms { - internal class KeyTransRecipientInfoGenerator : RecipientInfoGenerator - { - private static readonly CmsEnvelopedHelper Helper = CmsEnvelopedHelper.Instance; - - private TbsCertificateStructure recipientTbsCert; - private AsymmetricKeyParameter recipientPublicKey; - private Asn1OctetString subjectKeyIdentifier; - - // Derived fields - private SubjectPublicKeyInfo info; - - internal KeyTransRecipientInfoGenerator() - { - } - - internal X509Certificate RecipientCert - { - set - { - this.recipientTbsCert = CmsUtilities.GetTbsCertificateStructure(value); - this.recipientPublicKey = value.GetPublicKey(); - this.info = recipientTbsCert.SubjectPublicKeyInfo; - } - } - - internal AsymmetricKeyParameter RecipientPublicKey - { - set - { - this.recipientPublicKey = value; - - try - { - info = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo( - recipientPublicKey); - } - catch (IOException) - { - throw new ArgumentException("can't extract key algorithm from this key"); - } - } - } - - internal Asn1OctetString SubjectKeyIdentifier - { - set { this.subjectKeyIdentifier = value; } - } - - public RecipientInfo Generate(KeyParameter contentEncryptionKey, SecureRandom random) - { - byte[] keyBytes = contentEncryptionKey.GetKey(); - AlgorithmIdentifier keyEncryptionAlgorithm = info.AlgorithmID; + public class KeyTransRecipientInfoGenerator : RecipientInfoGenerator + { + private static readonly CmsEnvelopedHelper Helper = CmsEnvelopedHelper.Instance; + + private TbsCertificateStructure recipientTbsCert; + private AsymmetricKeyParameter recipientPublicKey; + private Asn1OctetString subjectKeyIdentifier; + + // Derived fields + private SubjectPublicKeyInfo info; + private IssuerAndSerialNumber issuerAndSerialNumber; + private SecureRandom random; + + internal KeyTransRecipientInfoGenerator() + { + } + + protected KeyTransRecipientInfoGenerator(IssuerAndSerialNumber issuerAndSerialNumber) + { + this.issuerAndSerialNumber = issuerAndSerialNumber; + } + + protected KeyTransRecipientInfoGenerator(byte[] subjectKeyIdentifier) + { + this.subjectKeyIdentifier = new DerOctetString(subjectKeyIdentifier); + } + + internal X509Certificate RecipientCert + { + set + { + this.recipientTbsCert = CmsUtilities.GetTbsCertificateStructure(value); + this.recipientPublicKey = value.GetPublicKey(); + this.info = recipientTbsCert.SubjectPublicKeyInfo; + } + } + + internal AsymmetricKeyParameter RecipientPublicKey + { + set + { + this.recipientPublicKey = value; + + try + { + info = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo( + recipientPublicKey); + } + catch (IOException) + { + throw new ArgumentException("can't extract key algorithm from this key"); + } + } + } + + internal Asn1OctetString SubjectKeyIdentifier + { + set { this.subjectKeyIdentifier = value; } + } + + public RecipientInfo Generate(KeyParameter contentEncryptionKey, SecureRandom random) + { + byte[] keyBytes = contentEncryptionKey.GetKey(); + AlgorithmIdentifier keyEncryptionAlgorithm = this.AlgorithmDetails; + + this.random = random; + + IWrapper keyWrapper = Helper.CreateWrapper(keyEncryptionAlgorithm.Algorithm.Id); + keyWrapper.Init(true, new ParametersWithRandom(recipientPublicKey, random)); + byte[] encryptedKeyBytes = keyWrapper.Wrap(keyBytes, 0, keyBytes.Length); + + RecipientIdentifier recipId; + if (recipientTbsCert != null) + { + IssuerAndSerialNumber issuerAndSerial = new IssuerAndSerialNumber( + recipientTbsCert.Issuer, recipientTbsCert.SerialNumber.Value); + recipId = new RecipientIdentifier(issuerAndSerial); + } + else + { + recipId = new RecipientIdentifier(subjectKeyIdentifier); + } + + return new RecipientInfo(new KeyTransRecipientInfo(recipId, keyEncryptionAlgorithm, + new DerOctetString(encryptedKeyBytes))); + } + + protected virtual AlgorithmIdentifier AlgorithmDetails + { + get + { + return info.AlgorithmID; + } + } + + protected virtual byte[] GenerateWrappedKey(KeyParameter contentEncryptionKey) + { + byte[] keyBytes = contentEncryptionKey.GetKey(); + AlgorithmIdentifier keyEncryptionAlgorithm = info.AlgorithmID; IWrapper keyWrapper = Helper.CreateWrapper(keyEncryptionAlgorithm.Algorithm.Id); - keyWrapper.Init(true, new ParametersWithRandom(recipientPublicKey, random)); - byte[] encryptedKeyBytes = keyWrapper.Wrap(keyBytes, 0, keyBytes.Length); - - RecipientIdentifier recipId; - if (recipientTbsCert != null) - { - IssuerAndSerialNumber issuerAndSerial = new IssuerAndSerialNumber( - recipientTbsCert.Issuer, recipientTbsCert.SerialNumber.Value); - recipId = new RecipientIdentifier(issuerAndSerial); - } - else - { - recipId = new RecipientIdentifier(subjectKeyIdentifier); - } - - return new RecipientInfo(new KeyTransRecipientInfo(recipId, keyEncryptionAlgorithm, - new DerOctetString(encryptedKeyBytes))); - } - } + keyWrapper.Init(true, new ParametersWithRandom(recipientPublicKey, random)); + return keyWrapper.Wrap(keyBytes, 0, keyBytes.Length); + } + } } diff --git a/crypto/src/crmf/EncryptedValueBuilder.cs b/crypto/src/crmf/EncryptedValueBuilder.cs index 28d5b52b4..b8076c0e9 100644 --- a/crypto/src/crmf/EncryptedValueBuilder.cs +++ b/crypto/src/crmf/EncryptedValueBuilder.cs @@ -110,6 +110,7 @@ namespace Org.BouncyCastle.Crmf { throw new CrmfException("cannot wrap key: " + e.Message, e); } + } private EncryptedValue encryptData(byte[] data) diff --git a/crypto/src/crypto/operators/Asn1CipherBuilder.cs b/crypto/src/crypto/operators/Asn1CipherBuilder.cs new file mode 100644 index 000000000..adb4507a3 --- /dev/null +++ b/crypto/src/crypto/operators/Asn1CipherBuilder.cs @@ -0,0 +1,100 @@ +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; +using Org.BouncyCastle.Crypto.Utilities; + +namespace Org.BouncyCastle.Crypto.Operators +{ + public class Asn1CipherBuilderWithKey:ICipherBuilderWithKey + { + + private readonly KeyParameter encKey; + private AlgorithmIdentifier algorithmIdentifier; + + + public Asn1CipherBuilderWithKey(DerObjectIdentifier encryptionOID, int keySize, SecureRandom random) + { + if (random == null) + { + random= new SecureRandom(); + } + CipherKeyGenerator keyGen = CipherKeyGeneratorFactory.CreateKeyGenerator(encryptionOID, random); + + encKey = new KeyParameter(keyGen.GenerateKey()); + algorithmIdentifier = AlgorithmIdentifierFactory.GenerateEncryptionAlgID(encryptionOID, encKey.GetKey().Length * 8, random); + } + + + 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; } + } + } +} diff --git a/crypto/src/crypto/operators/Asn1KeyWrapper.cs b/crypto/src/crypto/operators/Asn1KeyWrapper.cs new file mode 100644 index 000000000..8cd5cf8fe --- /dev/null +++ b/crypto/src/crypto/operators/Asn1KeyWrapper.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Org.BouncyCastle.X509; + +namespace Org.BouncyCastle.Crypto.Operators +{ + public class Asn1KeyWrapper : IKeyWrapper + { + private X509Certificate cert; + private string algorithm; + + public Asn1KeyWrapper(string algorithm, X509Certificate cert) + { + this.algorithm = algorithm; + this.cert = cert; + } + + public object AlgorithmDetails + { + get + { + throw new NotImplementedException(); + } + } + + public IBlockResult Wrap(byte[] keyData) + { + throw new NotImplementedException(); + } + } + + public class Asn1KeyUnwrapper: IKeyUnwrapper + { + public object AlgorithmDetails + { + get + { + throw new NotImplementedException(); + } + } + + public IBlockResult Unwrap(byte[] cipherText, int offset, int length) + { + throw new NotImplementedException(); + } + } +} diff --git a/crypto/src/crypto/operators/CipherFactory.cs b/crypto/src/crypto/operators/CipherFactory.cs deleted file mode 100644 index 11a9faef9..000000000 --- a/crypto/src/crypto/operators/CipherFactory.cs +++ /dev/null @@ -1,146 +0,0 @@ -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 index f7ddf4db6..da9e32f9e 100644 --- a/crypto/src/crypto/operators/CmsContentEncryptorBuilder.cs +++ b/crypto/src/crypto/operators/CmsContentEncryptorBuilder.cs @@ -9,8 +9,10 @@ using Org.BouncyCastle.Crypto.IO; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Security; using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Operators; -namespace Org.BouncyCastle.Crypto.Operators +namespace Org.BouncyCastle.Operators { public class CmsContentEncryptorBuilder { @@ -55,101 +57,8 @@ namespace Org.BouncyCastle.Crypto.Operators } 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; } + return new Asn1CipherBuilderWithKey(encryptionOID,keySize,random); } } - - 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/operators/CmsKeyTransRecipientInfoGenerator.cs b/crypto/src/crypto/operators/CmsKeyTransRecipientInfoGenerator.cs new file mode 100644 index 000000000..048014f22 --- /dev/null +++ b/crypto/src/crypto/operators/CmsKeyTransRecipientInfoGenerator.cs @@ -0,0 +1,36 @@ +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Cms; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.X509; + +namespace Org.BouncyCastle.Operators +{ + public class CmsKeyTransRecipientInfoGenerator: KeyTransRecipientInfoGenerator + { + private IKeyWrapper keyWrapper; + + public CmsKeyTransRecipientInfoGenerator(X509Certificate recipCert, IKeyWrapper keyWrapper): base(new Asn1.Cms.IssuerAndSerialNumber(recipCert.IssuerDN, new DerInteger(recipCert.SerialNumber))) + { + this.keyWrapper = keyWrapper; + } + + public CmsKeyTransRecipientInfoGenerator(byte[] subjectKeyID, IKeyWrapper keyWrapper) : base(subjectKeyID) + { + this.keyWrapper = keyWrapper; + } + + protected override AlgorithmIdentifier AlgorithmDetails + { + get + { + return (AlgorithmIdentifier)keyWrapper.AlgorithmDetails; + } + } + + protected override byte[] GenerateWrappedKey(Crypto.Parameters.KeyParameter contentKey) + { + return keyWrapper.Wrap(contentKey.GetKey()).Collect(); + } + } +} diff --git a/crypto/src/crypto/util/AlgorithmIdentifierFactory.cs b/crypto/src/crypto/util/AlgorithmIdentifierFactory.cs index 73458f0ea..20eac84ce 100644 --- a/crypto/src/crypto/util/AlgorithmIdentifierFactory.cs +++ b/crypto/src/crypto/util/AlgorithmIdentifierFactory.cs @@ -82,7 +82,7 @@ namespace Org.BouncyCastle.Crypto.Utilities return new AlgorithmIdentifier(encryptionOID, cbcParams); } - else if (encryptionOID.Equals(PkcsObjectIdentifiers.Rc4)) + else if (encryptionOID.Equals(PkcsObjectIdentifiers.rc4)) { return new AlgorithmIdentifier(encryptionOID, DerNull.Instance); } diff --git a/crypto/src/crypto/util/CipherFactory.cs b/crypto/src/crypto/util/CipherFactory.cs new file mode 100644 index 000000000..0a4010b42 --- /dev/null +++ b/crypto/src/crypto/util/CipherFactory.cs @@ -0,0 +1,151 @@ +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.Utilites +{ + public class CipherFactory + { + private 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()); + } + + } +} diff --git a/crypto/src/crypto/util/CipherKeyGeneratorFactory.cs b/crypto/src/crypto/util/CipherKeyGeneratorFactory.cs index 7a24a01a8..f714c40fd 100644 --- a/crypto/src/crypto/util/CipherKeyGeneratorFactory.cs +++ b/crypto/src/crypto/util/CipherKeyGeneratorFactory.cs @@ -12,6 +12,10 @@ namespace Org.BouncyCastle.Crypto.Utilities { public class CipherKeyGeneratorFactory { + private CipherKeyGeneratorFactory() + { + + } /** * Create a key generator for the passed in Object Identifier. @@ -22,7 +26,6 @@ namespace Org.BouncyCastle.Crypto.Utilities * @throws IllegalArgumentException if the algorithm cannot be identified. */ public static CipherKeyGenerator CreateKeyGenerator(DerObjectIdentifier algorithm, SecureRandom random) - { if (NistObjectIdentifiers.IdAes128Cbc.Equals(algorithm)) { @@ -72,7 +75,7 @@ namespace Org.BouncyCastle.Crypto.Utilities return keyGen; } - else if (PkcsObjectIdentifiers.Rc4.Equals(algorithm)) + else if (PkcsObjectIdentifiers.rc4.Equals(algorithm)) { return createCipherKeyGenerator(random, 128); } @@ -86,9 +89,6 @@ namespace Org.BouncyCastle.Crypto.Utilities } } - - - private static CipherKeyGenerator createCipherKeyGenerator(SecureRandom random, int keySize) { CipherKeyGenerator keyGen = new CipherKeyGenerator(); -- cgit 1.4.1