diff options
author | David Hook <dgh@bouncycastle.org> | 2021-05-24 13:06:31 +1000 |
---|---|---|
committer | David Hook <dgh@bouncycastle.org> | 2021-05-24 13:06:31 +1000 |
commit | 01238566c1d4b2a606e4859a75ad05ca79db4ffb (patch) | |
tree | ee7d1057d41cd25c3f0383b5d1ca2e213a976feb | |
parent | github#54 test for mixed mode definition (diff) | |
download | BouncyCastle.NET-ed25519-01238566c1d4b2a606e4859a75ad05ca79db4ffb.tar.xz |
github #222 addressed OAEP parameter setting, refactored KeyTransRecipientInfoGenerator to allow deprecation of sub class
-rw-r--r-- | crypto/src/asn1/pkcs/RSAESOAEPparams.cs | 11 | ||||
-rw-r--r-- | crypto/src/cms/CMSEnvelopedGenerator.cs | 15 | ||||
-rw-r--r-- | crypto/src/cms/KeyTransRecipientInfoGenerator.cs | 65 | ||||
-rw-r--r-- | crypto/src/cms/KeyTransRecipientInformation.cs | 27 | ||||
-rw-r--r-- | crypto/src/crypto/encodings/OaepEncoding.cs | 30 | ||||
-rw-r--r-- | crypto/src/crypto/operators/Asn1KeyWrapper.cs | 203 | ||||
-rw-r--r-- | crypto/src/crypto/operators/CmsKeyTransRecipientInfoGenerator.cs | 21 | ||||
-rw-r--r-- | crypto/src/crypto/signers/PssSigner.cs | 24 | ||||
-rw-r--r-- | crypto/src/security/WrapperUtilities.cs | 1 | ||||
-rw-r--r-- | crypto/test/src/cms/test/EnvelopedDataTest.cs | 135 | ||||
-rw-r--r-- | crypto/test/src/crmf/test/CrmfTest.cs | 2 |
11 files changed, 434 insertions, 100 deletions
diff --git a/crypto/src/asn1/pkcs/RSAESOAEPparams.cs b/crypto/src/asn1/pkcs/RSAESOAEPparams.cs index 0cf22f860..6434f0935 100644 --- a/crypto/src/asn1/pkcs/RSAESOAEPparams.cs +++ b/crypto/src/asn1/pkcs/RSAESOAEPparams.cs @@ -36,10 +36,15 @@ namespace Org.BouncyCastle.Asn1.Pkcs * The default version */ public RsaesOaepParameters() + : this(DefaultHashAlgorithm, DefaultMaskGenFunction, DefaultPSourceAlgorithm) + { + } + + public RsaesOaepParameters( + AlgorithmIdentifier hashAlgorithm, + AlgorithmIdentifier maskGenAlgorithm) + : this(DefaultHashAlgorithm, DefaultMaskGenFunction, DefaultPSourceAlgorithm) { - hashAlgorithm = DefaultHashAlgorithm; - maskGenAlgorithm = DefaultMaskGenFunction; - pSourceAlgorithm = DefaultPSourceAlgorithm; } public RsaesOaepParameters( diff --git a/crypto/src/cms/CMSEnvelopedGenerator.cs b/crypto/src/cms/CMSEnvelopedGenerator.cs index ed7e1edee..d7d3e4bbf 100644 --- a/crypto/src/cms/CMSEnvelopedGenerator.cs +++ b/crypto/src/cms/CMSEnvelopedGenerator.cs @@ -10,6 +10,7 @@ using Org.BouncyCastle.Asn1.Pkcs; using Org.BouncyCastle.Asn1.X509; using Org.BouncyCastle.Asn1.X9; using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Operators; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Security; using Org.BouncyCastle.Utilities; @@ -132,10 +133,9 @@ namespace Org.BouncyCastle.Cms public void AddKeyTransRecipient( X509Certificate cert) { - KeyTransRecipientInfoGenerator ktrig = new KeyTransRecipientInfoGenerator(); - ktrig.RecipientCert = cert; - - recipientInfoGenerators.Add(ktrig); + TbsCertificateStructure recipientTbsCert = CmsUtilities.GetTbsCertificateStructure(cert); + SubjectPublicKeyInfo info = recipientTbsCert.SubjectPublicKeyInfo; + this.AddRecipientInfoGenerator(new KeyTransRecipientInfoGenerator(cert, new Asn1KeyWrapper(info.AlgorithmID.Algorithm, info.AlgorithmID.Parameters, cert))); } /** @@ -149,11 +149,8 @@ namespace Org.BouncyCastle.Cms AsymmetricKeyParameter pubKey, byte[] subKeyId) { - KeyTransRecipientInfoGenerator ktrig = new KeyTransRecipientInfoGenerator(); - ktrig.RecipientPublicKey = pubKey; - ktrig.SubjectKeyIdentifier = new DerOctetString(subKeyId); - - recipientInfoGenerators.Add(ktrig); + SubjectPublicKeyInfo info = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(pubKey); + this.AddRecipientInfoGenerator(new KeyTransRecipientInfoGenerator(subKeyId, new Asn1KeyWrapper(info.AlgorithmID.Algorithm, info.AlgorithmID.Parameters, pubKey))); } /** diff --git a/crypto/src/cms/KeyTransRecipientInfoGenerator.cs b/crypto/src/cms/KeyTransRecipientInfoGenerator.cs index 23b06d3b3..60020be1f 100644 --- a/crypto/src/cms/KeyTransRecipientInfoGenerator.cs +++ b/crypto/src/cms/KeyTransRecipientInfoGenerator.cs @@ -15,60 +15,30 @@ namespace Org.BouncyCastle.Cms { private static readonly CmsEnvelopedHelper Helper = CmsEnvelopedHelper.Instance; - private TbsCertificateStructure recipientTbsCert; - private AsymmetricKeyParameter recipientPublicKey; private Asn1OctetString subjectKeyIdentifier; + private IKeyWrapper keyWrapper; // Derived fields private SubjectPublicKeyInfo info; private IssuerAndSerialNumber issuerAndSerialNumber; private SecureRandom random; + - internal KeyTransRecipientInfoGenerator() + public KeyTransRecipientInfoGenerator(X509Certificate recipCert, IKeyWrapper keyWrapper) + : this(new Asn1.Cms.IssuerAndSerialNumber(recipCert.IssuerDN, new DerInteger(recipCert.SerialNumber)), keyWrapper) { } - protected KeyTransRecipientInfoGenerator(IssuerAndSerialNumber issuerAndSerialNumber) + public KeyTransRecipientInfoGenerator(IssuerAndSerialNumber issuerAndSerial, IKeyWrapper keyWrapper) { - this.issuerAndSerialNumber = issuerAndSerialNumber; + this.issuerAndSerialNumber = issuerAndSerial; + this.keyWrapper = keyWrapper; } - protected KeyTransRecipientInfoGenerator(byte[] subjectKeyIdentifier) + public KeyTransRecipientInfoGenerator(byte[] subjectKeyID, IKeyWrapper keyWrapper) { 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; } + this.keyWrapper = keyWrapper; } public RecipientInfo Generate(KeyParameter contentEncryptionKey, SecureRandom random) @@ -80,11 +50,9 @@ namespace Org.BouncyCastle.Cms byte[] encryptedKeyBytes = GenerateWrappedKey(contentEncryptionKey); RecipientIdentifier recipId; - if (recipientTbsCert != null) + if (issuerAndSerialNumber != null) { - IssuerAndSerialNumber issuerAndSerial = new IssuerAndSerialNumber( - recipientTbsCert.Issuer, recipientTbsCert.SerialNumber.Value); - recipId = new RecipientIdentifier(issuerAndSerial); + recipId = new RecipientIdentifier(issuerAndSerialNumber); } else { @@ -99,18 +67,17 @@ namespace Org.BouncyCastle.Cms { get { + if (this.keyWrapper != null) + { + return (AlgorithmIdentifier)keyWrapper.AlgorithmDetails; + } 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)); - return keyWrapper.Wrap(keyBytes, 0, keyBytes.Length); + return keyWrapper.Wrap(contentEncryptionKey.GetKey()).Collect(); } } } diff --git a/crypto/src/cms/KeyTransRecipientInformation.cs b/crypto/src/cms/KeyTransRecipientInformation.cs index 7d2f072b5..2a40fed06 100644 --- a/crypto/src/cms/KeyTransRecipientInformation.cs +++ b/crypto/src/cms/KeyTransRecipientInformation.cs @@ -9,6 +9,8 @@ using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Security; using Org.BouncyCastle.X509; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Crypto.Operators; namespace Org.BouncyCastle.Cms { @@ -42,7 +44,7 @@ namespace Org.BouncyCastle.Cms } else { - IssuerAndSerialNumber iAnds = IssuerAndSerialNumber.GetInstance(r.ID); + Asn1.Cms.IssuerAndSerialNumber iAnds = Asn1.Cms.IssuerAndSerialNumber.GetInstance(r.ID); rid.Issuer = iAnds.Name; rid.SerialNumber = iAnds.SerialNumber.Value; @@ -74,16 +76,27 @@ namespace Org.BouncyCastle.Cms internal KeyParameter UnwrapKey(ICipherParameters key) { byte[] encryptedKey = info.EncryptedKey.GetOctets(); - string keyExchangeAlgorithm = GetExchangeEncryptionAlgorithmName(keyEncAlg); + try { - IWrapper keyWrapper = WrapperUtilities.GetWrapper(keyExchangeAlgorithm); - keyWrapper.Init(false, key); + if (keyEncAlg.Algorithm.Equals(PkcsObjectIdentifiers.IdRsaesOaep)) + { + IKeyUnwrapper keyWrapper = new Asn1KeyUnwrapper(keyEncAlg.Algorithm, keyEncAlg.Parameters, key); - // FIXME Support for MAC algorithm parameters similar to cipher parameters - return ParameterUtilities.CreateKeyParameter( - GetContentAlgorithmName(), keyWrapper.Unwrap(encryptedKey, 0, encryptedKey.Length)); + return ParameterUtilities.CreateKeyParameter( + GetContentAlgorithmName(), keyWrapper.Unwrap(encryptedKey, 0, encryptedKey.Length).Collect()); + } + else + { + string keyExchangeAlgorithm = GetExchangeEncryptionAlgorithmName(keyEncAlg); + IWrapper keyWrapper = WrapperUtilities.GetWrapper(keyExchangeAlgorithm); + keyWrapper.Init(false, key); + + // FIXME Support for MAC algorithm parameters similar to cipher parameters + return ParameterUtilities.CreateKeyParameter( + GetContentAlgorithmName(), keyWrapper.Unwrap(encryptedKey, 0, encryptedKey.Length)); + } } catch (SecurityUtilityException e) { diff --git a/crypto/src/crypto/encodings/OaepEncoding.cs b/crypto/src/crypto/encodings/OaepEncoding.cs index 690be116d..b01af6eed 100644 --- a/crypto/src/crypto/encodings/OaepEncoding.cs +++ b/crypto/src/crypto/encodings/OaepEncoding.cs @@ -169,7 +169,7 @@ namespace Org.BouncyCastle.Crypto.Encodings // // mask the message block. // - byte[] mask = maskGeneratorFunction1(seed, 0, seed.Length, block.Length - defHash.Length); + byte[] mask = MaskGeneratorFunction(seed, 0, seed.Length, block.Length - defHash.Length); for (int i = defHash.Length; i != block.Length; i++) { @@ -184,7 +184,7 @@ namespace Org.BouncyCastle.Crypto.Encodings // // mask the seed. // - mask = maskGeneratorFunction1( + mask = MaskGeneratorFunction( block, defHash.Length, block.Length - defHash.Length, defHash.Length); for (int i = 0; i != defHash.Length; i++) @@ -227,7 +227,7 @@ namespace Org.BouncyCastle.Crypto.Encodings // // unmask the seed. // - byte[] mask = maskGeneratorFunction1( + byte[] mask = MaskGeneratorFunction( block, defHash.Length, block.Length - defHash.Length, defHash.Length); for (int i = 0; i != defHash.Length; i++) @@ -238,7 +238,7 @@ namespace Org.BouncyCastle.Crypto.Encodings // // unmask the message block. // - mask = maskGeneratorFunction1(block, 0, defHash.Length, block.Length - defHash.Length); + mask = MaskGeneratorFunction(block, 0, defHash.Length, block.Length - defHash.Length); for (int i = defHash.Length; i != block.Length; i++) { @@ -306,10 +306,30 @@ namespace Org.BouncyCastle.Crypto.Encodings sp[3] = (byte)((uint)i >> 0); } + private byte[] MaskGeneratorFunction( + byte[] Z, + int zOff, + int zLen, + int length) + { + if (mgf1Hash is IXof) + { + byte[] mask = new byte[length]; + mgf1Hash.BlockUpdate(Z, zOff, zLen); + ((IXof)mgf1Hash).DoFinal(mask, 0, mask.Length); + + return mask; + } + else + { + return MaskGeneratorFunction1(Z, zOff, zLen, length); + } + } + /** * mask generator function, as described in PKCS1v2. */ - private byte[] maskGeneratorFunction1( + private byte[] MaskGeneratorFunction1( byte[] Z, int zOff, int zLen, diff --git a/crypto/src/crypto/operators/Asn1KeyWrapper.cs b/crypto/src/crypto/operators/Asn1KeyWrapper.cs index e2b2f8a37..a34d93d54 100644 --- a/crypto/src/crypto/operators/Asn1KeyWrapper.cs +++ b/crypto/src/crypto/operators/Asn1KeyWrapper.cs @@ -26,6 +26,50 @@ namespace Org.BouncyCastle.Crypto.Operators wrapper = KeyWrapperUtil.WrapperForName(algorithm, cert.GetPublicKey()); } + public Asn1KeyWrapper(DerObjectIdentifier algorithm, X509Certificate cert) + : this(algorithm, cert.GetPublicKey()) + { + } + + public Asn1KeyWrapper(DerObjectIdentifier algorithm, ICipherParameters key) + : this(algorithm, null, key) + { + } + + public Asn1KeyWrapper(DerObjectIdentifier algorithm, Asn1Encodable parameters, X509Certificate cert) + :this(algorithm, parameters, cert.GetPublicKey()) + { + } + + public Asn1KeyWrapper(DerObjectIdentifier algorithm, Asn1Encodable parameters, ICipherParameters key) + { + this.algorithm = algorithm.Id; + if (algorithm.Equals(PkcsObjectIdentifiers.IdRsaesOaep)) + { + RsaesOaepParameters oaepParams = RsaesOaepParameters.GetInstance(parameters); + WrapperProvider provider; + if (oaepParams.MaskGenAlgorithm.Algorithm.Equals(PkcsObjectIdentifiers.IdMgf1)) + { + AlgorithmIdentifier digAlg = AlgorithmIdentifier.GetInstance(oaepParams.MaskGenAlgorithm.Parameters); + + provider = new RsaOaepWrapperProvider(oaepParams.HashAlgorithm.Algorithm, digAlg.Algorithm); + } + else + { + provider = new RsaOaepWrapperProvider(oaepParams.HashAlgorithm.Algorithm, oaepParams.MaskGenAlgorithm.Algorithm); + } + wrapper = (IKeyWrapper)provider.CreateWrapper(true, key); + } + else if (algorithm.Equals(PkcsObjectIdentifiers.RsaEncryption)) + { + wrapper = (IKeyWrapper)new RsaPkcs1Wrapper(true, key); + } + else + { + throw new ArgumentException("unknown algorithm: " + algorithm.Id); + } + } + public object AlgorithmDetails { get { return wrapper.AlgorithmDetails; } @@ -37,6 +81,75 @@ namespace Org.BouncyCastle.Crypto.Operators } } + public class Asn1KeyUnwrapper + : IKeyUnwrapper + { + private string algorithm; + private IKeyUnwrapper wrapper; + + public Asn1KeyUnwrapper(string algorithm, ICipherParameters key) + { + this.algorithm = algorithm; + wrapper = KeyWrapperUtil.UnwrapperForName(algorithm, key); + } + + public Asn1KeyUnwrapper(DerObjectIdentifier algorithm, ICipherParameters key) + : this(algorithm, null, key) + { + } + + public Asn1KeyUnwrapper(DerObjectIdentifier algorithm, Asn1Encodable parameters, ICipherParameters key) + { + this.algorithm = algorithm.Id; + if (algorithm.Equals(PkcsObjectIdentifiers.IdRsaesOaep)) + { + RsaesOaepParameters oaepParams = RsaesOaepParameters.GetInstance(parameters); + WrapperProvider provider; + if (oaepParams.MaskGenAlgorithm.Algorithm.Equals(PkcsObjectIdentifiers.IdMgf1)) + { + AlgorithmIdentifier digAlg = AlgorithmIdentifier.GetInstance(oaepParams.MaskGenAlgorithm.Parameters); + + provider = new RsaOaepWrapperProvider(oaepParams.HashAlgorithm.Algorithm, digAlg.Algorithm); + } + else + { + provider = new RsaOaepWrapperProvider(oaepParams.HashAlgorithm.Algorithm, oaepParams.MaskGenAlgorithm.Algorithm); + } + wrapper = (IKeyUnwrapper)provider.CreateWrapper(false, key); + } + else if (algorithm.Equals(PkcsObjectIdentifiers.RsaEncryption)) + { + RsaesOaepParameters oaepParams = RsaesOaepParameters.GetInstance(parameters); + WrapperProvider provider; + if (oaepParams.MaskGenAlgorithm.Algorithm.Equals(PkcsObjectIdentifiers.IdMgf1)) + { + AlgorithmIdentifier digAlg = AlgorithmIdentifier.GetInstance(oaepParams.MaskGenAlgorithm.Parameters); + + provider = new RsaOaepWrapperProvider(oaepParams.HashAlgorithm.Algorithm, digAlg.Algorithm); + } + else + { + provider = new RsaOaepWrapperProvider(oaepParams.HashAlgorithm.Algorithm, oaepParams.MaskGenAlgorithm.Algorithm); + } + wrapper = (IKeyUnwrapper)new RsaPkcs1Wrapper(false, key); + } + else + { + throw new ArgumentException("unknown algorithm: " + algorithm.Id); + } + } + + public object AlgorithmDetails + { + get { return wrapper.AlgorithmDetails; } + } + + public IBlockResult Unwrap(byte[] keyData, int offSet, int length) + { + return wrapper.Unwrap(keyData, offSet, length); + } + } + internal class KeyWrapperUtil { // @@ -45,12 +158,16 @@ namespace Org.BouncyCastle.Crypto.Operators private static readonly IDictionary providerMap = Platform.CreateHashtable(); static KeyWrapperUtil() + { + providerMap.Add("RSA/ECB/PKCS1PADDING", new RsaOaepWrapperProvider(OiwObjectIdentifiers.IdSha1)); + providerMap.Add("RSA/NONE/PKCS1PADDING", new RsaOaepWrapperProvider(OiwObjectIdentifiers.IdSha1)); providerMap.Add("RSA/NONE/OAEPWITHSHA1ANDMGF1PADDING", new RsaOaepWrapperProvider(OiwObjectIdentifiers.IdSha1)); providerMap.Add("RSA/NONE/OAEPWITHSHA224ANDMGF1PADDING", new RsaOaepWrapperProvider(NistObjectIdentifiers.IdSha224)); providerMap.Add("RSA/NONE/OAEPWITHSHA256ANDMGF1PADDING", new RsaOaepWrapperProvider(NistObjectIdentifiers.IdSha256)); providerMap.Add("RSA/NONE/OAEPWITHSHA384ANDMGF1PADDING", new RsaOaepWrapperProvider(NistObjectIdentifiers.IdSha384)); providerMap.Add("RSA/NONE/OAEPWITHSHA512ANDMGF1PADDING", new RsaOaepWrapperProvider(NistObjectIdentifiers.IdSha512)); + providerMap.Add("RSA/NONE/OAEPWITHSHA256ANDMGF1WITHSHA1PADDING", new RsaOaepWrapperProvider(NistObjectIdentifiers.IdSha256, OiwObjectIdentifiers.IdSha1)); } public static IKeyWrapper WrapperForName(string algorithm, ICipherParameters parameters) @@ -78,22 +195,84 @@ namespace Org.BouncyCastle.Crypto.Operators object CreateWrapper(bool forWrapping, ICipherParameters parameters); } + internal class RsaPkcs1Wrapper : IKeyWrapper, IKeyUnwrapper + { + private readonly AlgorithmIdentifier algId; + private readonly IAsymmetricBlockCipher engine; + + public RsaPkcs1Wrapper(bool forWrapping, ICipherParameters parameters) + { + this.algId = new AlgorithmIdentifier( + PkcsObjectIdentifiers.RsaEncryption, + DerNull.Instance); + + this.engine = new Pkcs1Encoding(new RsaBlindedEngine()); + this.engine.Init(forWrapping, parameters); + } + + public object AlgorithmDetails + { + get { return algId; } + } + + public IBlockResult Unwrap(byte[] cipherText, int offset, int length) + { + return new SimpleBlockResult(engine.ProcessBlock(cipherText, offset, length)); + } + + public IBlockResult Wrap(byte[] keyData) + { + return new SimpleBlockResult(engine.ProcessBlock(keyData, 0, keyData.Length)); + } + } + + internal class RsaPkcs1WrapperProvider + : WrapperProvider + { + internal RsaPkcs1WrapperProvider() + { + } + + object WrapperProvider.CreateWrapper(bool forWrapping, ICipherParameters parameters) + { + return new RsaPkcs1Wrapper(forWrapping, parameters); + } + } + internal class RsaOaepWrapper : IKeyWrapper, IKeyUnwrapper { private readonly AlgorithmIdentifier algId; private readonly IAsymmetricBlockCipher engine; public RsaOaepWrapper(bool forWrapping, ICipherParameters parameters, DerObjectIdentifier digestOid) + : this(forWrapping, parameters, digestOid, digestOid) + { + } + + public RsaOaepWrapper(bool forWrapping, ICipherParameters parameters, DerObjectIdentifier digestOid, DerObjectIdentifier mgfOid) { AlgorithmIdentifier digestAlgId = new AlgorithmIdentifier(digestOid, DerNull.Instance); - this.algId = new AlgorithmIdentifier( - PkcsObjectIdentifiers.IdRsaesOaep, - new RsaesOaepParameters( - digestAlgId, - new AlgorithmIdentifier(PkcsObjectIdentifiers.IdMgf1, digestAlgId), - RsaesOaepParameters.DefaultPSourceAlgorithm)); - this.engine = new OaepEncoding(new RsaBlindedEngine(), DigestUtilities.GetDigest(digestOid) ); + if (mgfOid.Equals(NistObjectIdentifiers.IdShake128) || mgfOid.Equals(NistObjectIdentifiers.IdShake256)) + { + this.algId = new AlgorithmIdentifier( + PkcsObjectIdentifiers.IdRsaesOaep, + new RsaesOaepParameters( + digestAlgId, + new AlgorithmIdentifier(mgfOid), + RsaesOaepParameters.DefaultPSourceAlgorithm)); + } + else + { + this.algId = new AlgorithmIdentifier( + PkcsObjectIdentifiers.IdRsaesOaep, + new RsaesOaepParameters( + digestAlgId, + new AlgorithmIdentifier(PkcsObjectIdentifiers.IdMgf1, new AlgorithmIdentifier(mgfOid, DerNull.Instance)), + RsaesOaepParameters.DefaultPSourceAlgorithm)); + } + + this.engine = new OaepEncoding(new RsaBlindedEngine(), DigestUtilities.GetDigest(digestOid), DigestUtilities.GetDigest(mgfOid), null); this.engine.Init(forWrapping, parameters); } @@ -117,15 +296,23 @@ namespace Org.BouncyCastle.Crypto.Operators : WrapperProvider { private readonly DerObjectIdentifier digestOid; + private readonly DerObjectIdentifier mgfOid; internal RsaOaepWrapperProvider(DerObjectIdentifier digestOid) { this.digestOid = digestOid; + this.mgfOid = digestOid; + } + + internal RsaOaepWrapperProvider(DerObjectIdentifier digestOid, DerObjectIdentifier mgfOid) + { + this.digestOid = digestOid; + this.mgfOid = mgfOid; } object WrapperProvider.CreateWrapper(bool forWrapping, ICipherParameters parameters) { - return new RsaOaepWrapper(forWrapping, parameters, digestOid); + return new RsaOaepWrapper(forWrapping, parameters, digestOid, mgfOid); } } } diff --git a/crypto/src/crypto/operators/CmsKeyTransRecipientInfoGenerator.cs b/crypto/src/crypto/operators/CmsKeyTransRecipientInfoGenerator.cs index b73c41dbd..0165f6af0 100644 --- a/crypto/src/crypto/operators/CmsKeyTransRecipientInfoGenerator.cs +++ b/crypto/src/crypto/operators/CmsKeyTransRecipientInfoGenerator.cs @@ -1,6 +1,7 @@ using System; using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Cms; using Org.BouncyCastle.Asn1.X509; using Org.BouncyCastle.Cms; using Org.BouncyCastle.Crypto; @@ -8,32 +9,22 @@ using Org.BouncyCastle.X509; namespace Org.BouncyCastle.Operators { + /// <deprecated>Use KeyTransRecipientInfoGenerator</deprecated> public class CmsKeyTransRecipientInfoGenerator : KeyTransRecipientInfoGenerator { - private readonly IKeyWrapper keyWrapper; - public CmsKeyTransRecipientInfoGenerator(X509Certificate recipCert, IKeyWrapper keyWrapper) - : base(new Asn1.Cms.IssuerAndSerialNumber(recipCert.IssuerDN, new DerInteger(recipCert.SerialNumber))) - { - this.keyWrapper = keyWrapper; - this.RecipientCert = recipCert; - this.RecipientPublicKey = recipCert.GetPublicKey(); - } - - public CmsKeyTransRecipientInfoGenerator(byte[] subjectKeyID, IKeyWrapper keyWrapper) : base(subjectKeyID) + : base(new Asn1.Cms.IssuerAndSerialNumber(recipCert.IssuerDN, new DerInteger(recipCert.SerialNumber)), keyWrapper) { - this.keyWrapper = keyWrapper; } - protected override AlgorithmIdentifier AlgorithmDetails + public CmsKeyTransRecipientInfoGenerator(IssuerAndSerialNumber issuerAndSerial, IKeyWrapper keyWrapper) + : base(issuerAndSerial, keyWrapper) { - get { return (AlgorithmIdentifier)keyWrapper.AlgorithmDetails; } } - protected override byte[] GenerateWrappedKey(Crypto.Parameters.KeyParameter contentKey) + public CmsKeyTransRecipientInfoGenerator(byte[] subjectKeyID, IKeyWrapper keyWrapper) : base(subjectKeyID, keyWrapper) { - return keyWrapper.Wrap(contentKey.GetKey()).Collect(); } } } diff --git a/crypto/src/crypto/signers/PssSigner.cs b/crypto/src/crypto/signers/PssSigner.cs index b31384783..66efa51b8 100644 --- a/crypto/src/crypto/signers/PssSigner.cs +++ b/crypto/src/crypto/signers/PssSigner.cs @@ -245,7 +245,7 @@ namespace Org.BouncyCastle.Crypto.Signers block[block.Length - sLen - 1 - hLen - 1] = (byte) (0x01); salt.CopyTo(block, block.Length - sLen - hLen - 1); - byte[] dbMask = MaskGeneratorFunction1(h, 0, h.Length, block.Length - hLen - 1); + byte[] dbMask = MaskGeneratorFunction(h, 0, h.Length, block.Length - hLen - 1); for (int i = 0; i != dbMask.Length; i++) { block[i] ^= dbMask[i]; @@ -286,7 +286,7 @@ namespace Org.BouncyCastle.Crypto.Signers return false; } - byte[] dbMask = MaskGeneratorFunction1(block, block.Length - hLen - 1, hLen, block.Length - hLen - 1); + byte[] dbMask = MaskGeneratorFunction(block, block.Length - hLen - 1, hLen, block.Length - hLen - 1); for (int i = 0; i != dbMask.Length; i++) { @@ -349,6 +349,26 @@ namespace Org.BouncyCastle.Crypto.Signers sp[3] = (byte)((uint) i >> 0); } + private byte[] MaskGeneratorFunction( + byte[] Z, + int zOff, + int zLen, + int length) + { + if (mgfDigest is IXof) + { + byte[] mask = new byte[length]; + mgfDigest.BlockUpdate(Z, zOff, zLen); + ((IXof)mgfDigest).DoFinal(mask, 0, mask.Length); + + return mask; + } + else + { + return MaskGeneratorFunction1(Z, zOff, zLen, length); + } + } + /// <summary> mask generator function, as described in Pkcs1v2.</summary> private byte[] MaskGeneratorFunction1( byte[] Z, diff --git a/crypto/src/security/WrapperUtilities.cs b/crypto/src/security/WrapperUtilities.cs index c57632081..e0c677e42 100644 --- a/crypto/src/security/WrapperUtilities.cs +++ b/crypto/src/security/WrapperUtilities.cs @@ -6,6 +6,7 @@ using Org.BouncyCastle.Asn1.Kisa; using Org.BouncyCastle.Asn1.Nist; using Org.BouncyCastle.Asn1.Ntt; using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Asn1.X509; using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto.Engines; using Org.BouncyCastle.Utilities; diff --git a/crypto/test/src/cms/test/EnvelopedDataTest.cs b/crypto/test/src/cms/test/EnvelopedDataTest.cs index be588ef42..04e75f623 100644 --- a/crypto/test/src/cms/test/EnvelopedDataTest.cs +++ b/crypto/test/src/cms/test/EnvelopedDataTest.cs @@ -9,9 +9,12 @@ 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.Cms; using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Operators; using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Operators; using Org.BouncyCastle.Security; using Org.BouncyCastle.Utilities; using Org.BouncyCastle.Utilities.Encoders; @@ -241,7 +244,8 @@ namespace Org.BouncyCastle.Cms.Tests CmsEnvelopedDataGenerator edGen = new CmsEnvelopedDataGenerator(); - edGen.AddKeyTransRecipient(ReciCert); + edGen.AddRecipientInfoGenerator(new KeyTransRecipientInfoGenerator(ReciCert, + new Asn1KeyWrapper("RSA/ECB/PKCS1Padding", ReciCert))); CmsEnvelopedData ed = edGen.Generate( new CmsProcessableByteArray(data), @@ -322,6 +326,135 @@ namespace Org.BouncyCastle.Cms.Tests } [Test] + public void TestKeyTransSmallAesUsingAoep() + { + byte[] data = new byte[] { 0, 1, 2, 3 }; + + CmsEnvelopedDataGenerator edGen = new CmsEnvelopedDataGenerator(); + + edGen.AddRecipientInfoGenerator(new KeyTransRecipientInfoGenerator(ReciCert, + new Asn1KeyWrapper("RSA/None/OAEPwithSHA256andMGF1withSHA1Padding", ReciCert))); + + CmsEnvelopedData ed = edGen.Generate( + new CmsProcessableByteArray(data), + CmsEnvelopedDataGenerator.Aes128Cbc); + + RecipientInformationStore recipients = ed.GetRecipientInfos(); + + Assert.AreEqual(ed.EncryptionAlgOid, + CmsEnvelopedDataGenerator.Aes128Cbc); + + ICollection c = recipients.GetRecipients(); + + Assert.AreEqual(1, c.Count); + + foreach (RecipientInformation recipient in c) + { + byte[] recData = recipient.GetContent(ReciKP.Private); + Assert.IsTrue(Arrays.AreEqual(data, recData)); + } + } + + [Test] + public void TestKeyTransSmallAesUsingAoepMixed() + { + byte[] data = new byte[] { 0, 1, 2, 3 }; + + CmsEnvelopedDataGenerator edGen = new CmsEnvelopedDataGenerator(); + + edGen.AddRecipientInfoGenerator(new KeyTransRecipientInfoGenerator(ReciCert, new Asn1KeyWrapper("RSA/None/OAEPwithSHA256andMGF1withSHA1Padding", ReciCert))); + + CmsEnvelopedData ed = edGen.Generate( + new CmsProcessableByteArray(data), + CmsEnvelopedDataGenerator.Aes128Cbc); + + RecipientInformationStore recipients = ed.GetRecipientInfos(); + + Assert.AreEqual(ed.EncryptionAlgOid, + CmsEnvelopedDataGenerator.Aes128Cbc); + + ICollection c = recipients.GetRecipients(); + + Assert.AreEqual(1, c.Count); + + foreach (RecipientInformation recipient in c) + { + byte[] recData = recipient.GetContent(ReciKP.Private); + Assert.IsTrue(Arrays.AreEqual(data, recData)); + } + } + + [Test] + public void TestKeyTransSmallAesUsingAoepMixedParams() + { + byte[] data = new byte[] { 0, 1, 2, 3 }; + + CmsEnvelopedDataGenerator edGen = new CmsEnvelopedDataGenerator(); + + edGen.AddRecipientInfoGenerator( + new KeyTransRecipientInfoGenerator( + ReciCert, + new Asn1KeyWrapper( + PkcsObjectIdentifiers.IdRsaesOaep, + new RsaesOaepParameters( + new AlgorithmIdentifier(NistObjectIdentifiers.IdSha256, DerNull.Instance), + new AlgorithmIdentifier(PkcsObjectIdentifiers.IdMgf1, new AlgorithmIdentifier(NistObjectIdentifiers.IdSha224, DerNull.Instance))), + ReciCert))); + + CmsEnvelopedData ed = edGen.Generate( + new CmsProcessableByteArray(data), + CmsEnvelopedDataGenerator.Aes128Cbc); + + RecipientInformationStore recipients = ed.GetRecipientInfos(); + + Assert.AreEqual(ed.EncryptionAlgOid, + CmsEnvelopedDataGenerator.Aes128Cbc); + + ICollection c = recipients.GetRecipients(); + + Assert.AreEqual(1, c.Count); + + foreach (RecipientInformation recipient in c) + { + byte[] recData = recipient.GetContent(ReciKP.Private); + Assert.IsTrue(Arrays.AreEqual(data, recData)); + } + } + + [Test] + public void TestKeyTransSmallAesUsingPkcs1() + { + byte[] data = new byte[] { 0, 1, 2, 3 }; + + CmsEnvelopedDataGenerator edGen = new CmsEnvelopedDataGenerator(); + + edGen.AddRecipientInfoGenerator( + new KeyTransRecipientInfoGenerator( + ReciCert, + new Asn1KeyWrapper( + PkcsObjectIdentifiers.RsaEncryption, ReciCert))); + + CmsEnvelopedData ed = edGen.Generate( + new CmsProcessableByteArray(data), + CmsEnvelopedDataGenerator.Aes128Cbc); + + RecipientInformationStore recipients = ed.GetRecipientInfos(); + + Assert.AreEqual(ed.EncryptionAlgOid, + CmsEnvelopedDataGenerator.Aes128Cbc); + + ICollection c = recipients.GetRecipients(); + + Assert.AreEqual(1, c.Count); + + foreach (RecipientInformation recipient in c) + { + byte[] recData = recipient.GetContent(ReciKP.Private); + Assert.IsTrue(Arrays.AreEqual(data, recData)); + } + } + + [Test] public void TestKeyTransCast5() { TryKeyTrans(CmsEnvelopedDataGenerator.Cast5Cbc, diff --git a/crypto/test/src/crmf/test/CrmfTest.cs b/crypto/test/src/crmf/test/CrmfTest.cs index 8211fe1c4..3e5251d18 100644 --- a/crypto/test/src/crmf/test/CrmfTest.cs +++ b/crypto/test/src/crmf/test/CrmfTest.cs @@ -110,7 +110,7 @@ namespace Org.BouncyCastle.Crmf.Tests certificateRequestMessageBuilder.AddControl( new PkiArchiveControlBuilder(privateInfo, new GeneralName(new X509Name("CN=Test"))) - .AddRecipientGenerator(new CmsKeyTransRecipientInfoGenerator(cert, new Asn1KeyWrapper("RSA/None/OAEPwithSHA256andMGF1Padding", cert))) + .AddRecipientGenerator(new KeyTransRecipientInfoGenerator(cert, new Asn1KeyWrapper("RSA/None/OAEPwithSHA256andMGF1Padding", cert))) .Build(new CmsContentEncryptorBuilder(NistObjectIdentifiers.IdAes128Cbc).Build()) ); |