diff options
Diffstat (limited to 'crypto')
23 files changed, 411 insertions, 214 deletions
diff --git a/crypto/NBuild.build b/crypto/NBuild.build index 89c557702..dd63df279 100644 --- a/crypto/NBuild.build +++ b/crypto/NBuild.build @@ -16,7 +16,7 @@ <property name="dist-path" value="./dist"/> <!-- Version --> - <property name="version" value="1.8.2"/> + <property name="version" value="1.8.3"/> <property name="name" value="BouncyCastle.Crypto"/> <property name="OPTIONAL_STRONG_NAME" value="" /> diff --git a/crypto/Readme.html b/crypto/Readme.html index 9f4705f00..72e97516f 100644 --- a/crypto/Readme.html +++ b/crypto/Readme.html @@ -294,7 +294,17 @@ We state, where EC MQV has not otherwise been disabled or removed: <hr style="WIDTH: 100%; HEIGHT: 2px"> <h3><a class="mozTocH3" name="mozTocId3413"></a>Notes:</h3> - <h4><a class="mozTocH4" name="mozTocId85317"></a>Release 1.8.3, TBD</h4> + <h4><a class="mozTocH4" name="mozTocId85317"></a>Release 1.8.3, Saturday August 11, 2018</h4> + + <h5>IMPORTANT</h5> + <ul> + <li> + In this release, the TLS library has moved to a whitelisting approach for client-side validation of server-presented + Diffie-Hellman (DH) parameters. In the default configuration, if a ciphersuite using ephemeral DH is selected by the + server, the client will abort the handshake if the proposed DH group is not one of those specified in RFC 3526 or RFC 7919, + or if the DH prime is < 2048 bits. The client therefore no longer offers DH ciphersuites by default. + </li> + </ul> <h5>Additional Features and Functionality</h5> <ul> diff --git a/crypto/crypto.csproj b/crypto/crypto.csproj index 7cd8de821..b6dfb3963 100644 --- a/crypto/crypto.csproj +++ b/crypto/crypto.csproj @@ -4869,6 +4869,11 @@ BuildAction = "Compile" /> <File + RelPath = "src\crypto\tls\DefaultTlsDHVerifier.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File RelPath = "src\crypto\tls\DefaultTlsEncryptionCredentials.cs" SubType = "Code" BuildAction = "Compile" @@ -5084,11 +5089,6 @@ BuildAction = "Compile" /> <File - RelPath = "src\crypto\tls\ServerDHParams.cs" - SubType = "Code" - BuildAction = "Compile" - /> - <File RelPath = "src\crypto\tls\ServerSrpParams.cs" SubType = "Code" BuildAction = "Compile" @@ -5249,6 +5249,11 @@ BuildAction = "Compile" /> <File + RelPath = "src\crypto\tls\TlsDHVerifier.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File RelPath = "src\crypto\tls\TlsDsaSigner.cs" SubType = "Code" BuildAction = "Compile" diff --git a/crypto/src/asn1/cmp/PollRepContent.cs b/crypto/src/asn1/cmp/PollRepContent.cs index f8bb098a2..ff75d7d6d 100644 --- a/crypto/src/asn1/cmp/PollRepContent.cs +++ b/crypto/src/asn1/cmp/PollRepContent.cs @@ -33,6 +33,25 @@ namespace Org.BouncyCastle.Asn1.Cmp throw new ArgumentException("Invalid object: " + Platform.GetTypeName(obj), "obj"); } + public PollRepContent( + DerInteger certReqId, + DerInteger checkAfter) + { + this.certReqId = certReqId; + this.checkAfter = checkAfter; + this.reason = null; + } + + public PollRepContent( + DerInteger certReqId, + DerInteger checkAfter, + PkiFreeText reason) + { + this.certReqId = certReqId; + this.checkAfter = checkAfter; + this.reason = reason; + } + public virtual DerInteger CertReqID { get { return certReqId; } diff --git a/crypto/src/cms/CMSSignedDataGenerator.cs b/crypto/src/cms/CMSSignedDataGenerator.cs index f63ed874e..5aa5f92ab 100644 --- a/crypto/src/cms/CMSSignedDataGenerator.cs +++ b/crypto/src/cms/CMSSignedDataGenerator.cs @@ -513,15 +513,19 @@ namespace Org.BouncyCastle.Cms if (_certs.Count != 0) { - certificates = CmsUtilities.CreateBerSetFromList(_certs); + certificates = UseDerForCerts + ? CmsUtilities.CreateDerSetFromList(_certs) + : CmsUtilities.CreateBerSetFromList(_certs); } Asn1Set certrevlist = null; if (_crls.Count != 0) { - certrevlist = CmsUtilities.CreateBerSetFromList(_crls); - } + certrevlist = UseDerForCrls + ? CmsUtilities.CreateDerSetFromList(_crls) + : CmsUtilities.CreateBerSetFromList(_crls); + } Asn1OctetString octs = null; if (encapsulate) diff --git a/crypto/src/cms/CMSSignedDataStreamGenerator.cs b/crypto/src/cms/CMSSignedDataStreamGenerator.cs index 55fde90df..1c8fac22b 100644 --- a/crypto/src/cms/CMSSignedDataStreamGenerator.cs +++ b/crypto/src/cms/CMSSignedDataStreamGenerator.cs @@ -836,16 +836,20 @@ namespace Org.BouncyCastle.Cms outer._digests.Clear(); // clear the current preserved digest state - if (outer._certs.Count > 0) - { - Asn1Set certs = CmsUtilities.CreateBerSetFromList(outer._certs); + if (outer._certs.Count > 0) + { + Asn1Set certs = outer.UseDerForCerts + ? CmsUtilities.CreateDerSetFromList(outer._certs) + : CmsUtilities.CreateBerSetFromList(outer._certs); WriteToGenerator(_sigGen, new BerTaggedObject(false, 0, certs)); } - if (outer._crls.Count > 0) - { - Asn1Set crls = CmsUtilities.CreateBerSetFromList(outer._crls); + if (outer._crls.Count > 0) + { + Asn1Set crls = outer.UseDerForCrls + ? CmsUtilities.CreateDerSetFromList(outer._crls) + : CmsUtilities.CreateBerSetFromList(outer._crls); WriteToGenerator(_sigGen, new BerTaggedObject(false, 1, crls)); } diff --git a/crypto/src/cms/CMSSignedGenerator.cs b/crypto/src/cms/CMSSignedGenerator.cs index eec2e875b..249d70499 100644 --- a/crypto/src/cms/CMSSignedGenerator.cs +++ b/crypto/src/cms/CMSSignedGenerator.cs @@ -147,6 +147,8 @@ namespace Org.BouncyCastle.Cms internal IList _crls = Platform.CreateArrayList(); internal IList _signers = Platform.CreateArrayList(); internal IDictionary _digests = Platform.CreateHashtable(); + internal bool _useDerForCerts = false; + internal bool _useDerForCrls = false; protected readonly SecureRandom rand; @@ -251,6 +253,18 @@ namespace Org.BouncyCastle.Cms return Platform.CreateHashtable(_digests); } + public bool UseDerForCerts + { + get { return _useDerForCerts; } + set { this._useDerForCerts = value; } + } + + public bool UseDerForCrls + { + get { return _useDerForCrls; } + set { this._useDerForCrls = value; } + } + internal virtual void AddSignerCallback( SignerInformation si) { diff --git a/crypto/src/crypto/encodings/OaepEncoding.cs b/crypto/src/crypto/encodings/OaepEncoding.cs index 287876f12..92001589c 100644 --- a/crypto/src/crypto/encodings/OaepEncoding.cs +++ b/crypto/src/crypto/encodings/OaepEncoding.cs @@ -212,10 +212,17 @@ namespace Org.BouncyCastle.Crypto.Encodings // on encryption, we need to make sure our decrypted block comes back // the same size. // + bool wrongData = (block.Length < (2 * defHash.Length) + 1); - Array.Copy(data, 0, block, block.Length - data.Length, data.Length); - - bool shortData = (block.Length < (2 * defHash.Length) + 1); + if (data.Length <= block.Length) + { + Array.Copy(data, 0, block, block.Length - data.Length, data.Length); + } + else + { + Array.Copy(data, 0, block, 0, block.Length); + wrongData = true; + } // // unmask the seed. @@ -269,7 +276,7 @@ namespace Org.BouncyCastle.Crypto.Encodings start++; - if (defHashWrong | shortData | dataStartWrong) + if (defHashWrong | wrongData | dataStartWrong) { Arrays.Fill(block, 0); throw new InvalidCipherTextException("data wrong"); diff --git a/crypto/src/crypto/operators/Asn1Signature.cs b/crypto/src/crypto/operators/Asn1Signature.cs index e023c1d18..373ba0cee 100644 --- a/crypto/src/crypto/operators/Asn1Signature.cs +++ b/crypto/src/crypto/operators/Asn1Signature.cs @@ -325,7 +325,8 @@ namespace Org.BouncyCastle.Crypto.Operators /// Calculator factory class for signature generation in ASN.1 based profiles that use an AlgorithmIdentifier to preserve /// signature algorithm details. /// </summary> - public class Asn1SignatureFactory: ISignatureFactory + public class Asn1SignatureFactory + : ISignatureFactory { private readonly AlgorithmIdentifier algID; private readonly string algorithm; @@ -337,7 +338,8 @@ namespace Org.BouncyCastle.Crypto.Operators /// </summary> /// <param name="algorithm">The name of the signature algorithm to use.</param> /// <param name="privateKey">The private key to be used in the signing operation.</param> - public Asn1SignatureFactory (string algorithm, AsymmetricKeyParameter privateKey): this(algorithm, privateKey, null) + public Asn1SignatureFactory (string algorithm, AsymmetricKeyParameter privateKey) + : this(algorithm, privateKey, null) { } @@ -347,14 +349,21 @@ namespace Org.BouncyCastle.Crypto.Operators /// <param name="algorithm">The name of the signature algorithm to use.</param> /// <param name="privateKey">The private key to be used in the signing operation.</param> /// <param name="random">The source of randomness to be used in signature calculation.</param> - public Asn1SignatureFactory (string algorithm, AsymmetricKeyParameter privateKey, SecureRandom random) + public Asn1SignatureFactory(string algorithm, AsymmetricKeyParameter privateKey, SecureRandom random) { - DerObjectIdentifier sigOid = X509Utilities.GetAlgorithmOid (algorithm); + if (algorithm == null) + throw new ArgumentNullException("algorithm"); + if (privateKey == null) + throw new ArgumentNullException("privateKey"); + if (!privateKey.IsPrivate) + throw new ArgumentException("Key for signing must be private", "privateKey"); + + DerObjectIdentifier sigOid = X509Utilities.GetAlgorithmOid(algorithm); this.algorithm = algorithm; this.privateKey = privateKey; this.random = random; - this.algID = X509Utilities.GetSigAlgID (sigOid, algorithm); + this.algID = X509Utilities.GetSigAlgID(sigOid, algorithm); } public Object AlgorithmDetails @@ -365,16 +374,12 @@ namespace Org.BouncyCastle.Crypto.Operators public IStreamCalculator CreateCalculator() { ISigner sig = SignerUtilities.GetSigner(algorithm); - + ICipherParameters cp = privateKey; if (random != null) { - sig.Init(true, new ParametersWithRandom(privateKey, random)); + cp = new ParametersWithRandom(cp, random); } - else - { - sig.Init(true, privateKey); - } - + sig.Init(true, cp); return new SigCalculator(sig); } @@ -437,7 +442,8 @@ namespace Org.BouncyCastle.Crypto.Operators /// Verifier class for signature verification in ASN.1 based profiles that use an AlgorithmIdentifier to preserve /// signature algorithm details. /// </summary> - public class Asn1VerifierFactory: IVerifierFactory + public class Asn1VerifierFactory + : IVerifierFactory { private readonly AlgorithmIdentifier algID; private readonly AsymmetricKeyParameter publicKey; @@ -447,15 +453,22 @@ namespace Org.BouncyCastle.Crypto.Operators /// </summary> /// <param name="algorithm">The name of the signature algorithm to use.</param> /// <param name="publicKey">The public key to be used in the verification operation.</param> - public Asn1VerifierFactory (String algorithm, AsymmetricKeyParameter publicKey) + public Asn1VerifierFactory(string algorithm, AsymmetricKeyParameter publicKey) { - DerObjectIdentifier sigOid = X509Utilities.GetAlgorithmOid (algorithm); + if (algorithm == null) + throw new ArgumentNullException("algorithm"); + if (publicKey == null) + throw new ArgumentNullException("publicKey"); + if (publicKey.IsPrivate) + throw new ArgumentException("Key for verifying must be public", "publicKey"); + + DerObjectIdentifier sigOid = X509Utilities.GetAlgorithmOid(algorithm); this.publicKey = publicKey; - this.algID = X509Utilities.GetSigAlgID (sigOid, algorithm); + this.algID = X509Utilities.GetSigAlgID(sigOid, algorithm); } - public Asn1VerifierFactory (AlgorithmIdentifier algorithm, AsymmetricKeyParameter publicKey) + public Asn1VerifierFactory(AlgorithmIdentifier algorithm, AsymmetricKeyParameter publicKey) { this.publicKey = publicKey; this.algID = algorithm; @@ -540,7 +553,7 @@ namespace Org.BouncyCastle.Crypto.Operators public IVerifierFactory CreateVerifierFactory(Object algorithmDetails) { - return new Asn1VerifierFactory ((AlgorithmIdentifier)algorithmDetails, publicKey); + return new Asn1VerifierFactory((AlgorithmIdentifier)algorithmDetails, publicKey); } /// <summary> diff --git a/crypto/src/crypto/tls/DefaultTlsClient.cs b/crypto/src/crypto/tls/DefaultTlsClient.cs index 32a86e503..64d29863b 100644 --- a/crypto/src/crypto/tls/DefaultTlsClient.cs +++ b/crypto/src/crypto/tls/DefaultTlsClient.cs @@ -14,14 +14,22 @@ namespace Org.BouncyCastle.Crypto.Tls public abstract class DefaultTlsClient : AbstractTlsClient { + protected TlsDHVerifier mDHVerifier; + public DefaultTlsClient() - : base() + : this(new DefaultTlsCipherFactory()) { } public DefaultTlsClient(TlsCipherFactory cipherFactory) - : base(cipherFactory) + : this(cipherFactory, new DefaultTlsDHVerifier()) + { + } + + public DefaultTlsClient(TlsCipherFactory cipherFactory, TlsDHVerifier dhVerifier) + : base(cipherFactory) { + this.mDHVerifier = dhVerifier; } public override int[] GetCipherSuites() @@ -34,12 +42,6 @@ namespace Org.BouncyCastle.Crypto.Tls CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, - CipherSuite.TLS_DHE_DSS_WITH_AES_128_GCM_SHA256, - CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, - CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA, - CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, - CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, - CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256, CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256, CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, @@ -85,12 +87,12 @@ namespace Org.BouncyCastle.Crypto.Tls protected virtual TlsKeyExchange CreateDHKeyExchange(int keyExchange) { - return new TlsDHKeyExchange(keyExchange, mSupportedSignatureAlgorithms, null); + return new TlsDHKeyExchange(keyExchange, mSupportedSignatureAlgorithms, mDHVerifier, null); } protected virtual TlsKeyExchange CreateDheKeyExchange(int keyExchange) { - return new TlsDheKeyExchange(keyExchange, mSupportedSignatureAlgorithms, null); + return new TlsDheKeyExchange(keyExchange, mSupportedSignatureAlgorithms, mDHVerifier, null); } protected virtual TlsKeyExchange CreateECDHKeyExchange(int keyExchange) diff --git a/crypto/src/crypto/tls/DefaultTlsDHVerifier.cs b/crypto/src/crypto/tls/DefaultTlsDHVerifier.cs new file mode 100644 index 000000000..ae26d04c3 --- /dev/null +++ b/crypto/src/crypto/tls/DefaultTlsDHVerifier.cs @@ -0,0 +1,101 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Crypto.Agreement; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Tls +{ + public class DefaultTlsDHVerifier + : TlsDHVerifier + { + public static readonly int DefaultMinimumPrimeBits = 2048; + + protected static readonly IList DefaultGroups = Platform.CreateArrayList(); + + private static void AddDefaultGroup(DHParameters dhParameters) + { + DefaultGroups.Add(dhParameters); + } + + static DefaultTlsDHVerifier() + { + AddDefaultGroup(DHStandardGroups.rfc7919_ffdhe2048); + AddDefaultGroup(DHStandardGroups.rfc7919_ffdhe3072); + AddDefaultGroup(DHStandardGroups.rfc7919_ffdhe4096); + AddDefaultGroup(DHStandardGroups.rfc7919_ffdhe6144); + AddDefaultGroup(DHStandardGroups.rfc7919_ffdhe8192); + + AddDefaultGroup(DHStandardGroups.rfc3526_1536); + AddDefaultGroup(DHStandardGroups.rfc3526_2048); + AddDefaultGroup(DHStandardGroups.rfc3526_3072); + AddDefaultGroup(DHStandardGroups.rfc3526_4096); + AddDefaultGroup(DHStandardGroups.rfc3526_6144); + AddDefaultGroup(DHStandardGroups.rfc3526_8192); + } + + // IList is (DHParameters) + protected readonly IList mGroups; + protected readonly int mMinimumPrimeBits; + + /// <summary>Accept various standard DH groups with 'P' at least <c>DefaultMinimumPrimeBits</c> bits.</summary> + public DefaultTlsDHVerifier() + : this(DefaultMinimumPrimeBits) + { + } + + /// <summary>Accept various standard DH groups with 'P' at least the specified number of bits.</summary> + public DefaultTlsDHVerifier(int minimumPrimeBits) + : this(DefaultGroups, minimumPrimeBits) + { + } + + /// <summary>Accept a custom set of group parameters, subject to a minimum bitlength for 'P'.</summary> + /// <param name="groups">An <c>IList</c> of acceptable <c>DHParameters</c>.</param> + /// <param name="minimumPrimeBits">The minimum acceptable bitlength of the 'P' parameter.</param> + public DefaultTlsDHVerifier(IList groups, int minimumPrimeBits) + { + this.mGroups = groups; + this.mMinimumPrimeBits = minimumPrimeBits; + } + + public virtual bool Accept(DHParameters dhParameters) + { + return CheckMinimumPrimeBits(dhParameters) && CheckGroup(dhParameters); + } + + public virtual int MinimumPrimeBits + { + get { return mMinimumPrimeBits; } + } + + protected virtual bool AreGroupsEqual(DHParameters a, DHParameters b) + { + return a == b || (AreParametersEqual(a.P, b.P) && AreParametersEqual(a.G, b.G)); + } + + protected virtual bool AreParametersEqual(BigInteger a, BigInteger b) + { + return a == b || a.Equals(b); + } + + protected virtual bool CheckGroup(DHParameters dhParameters) + { + foreach (DHParameters group in mGroups) + { + if (AreGroupsEqual(dhParameters, group)) + { + return true; + } + } + return false; + } + + protected virtual bool CheckMinimumPrimeBits(DHParameters dhParameters) + { + return dhParameters.P.BitLength >= MinimumPrimeBits; + } + } +} diff --git a/crypto/src/crypto/tls/DefaultTlsServer.cs b/crypto/src/crypto/tls/DefaultTlsServer.cs index 97eaa079d..90f357687 100644 --- a/crypto/src/crypto/tls/DefaultTlsServer.cs +++ b/crypto/src/crypto/tls/DefaultTlsServer.cs @@ -138,12 +138,12 @@ namespace Org.BouncyCastle.Crypto.Tls protected virtual TlsKeyExchange CreateDHKeyExchange(int keyExchange) { - return new TlsDHKeyExchange(keyExchange, mSupportedSignatureAlgorithms, GetDHParameters()); + return new TlsDHKeyExchange(keyExchange, mSupportedSignatureAlgorithms, null, GetDHParameters()); } protected virtual TlsKeyExchange CreateDheKeyExchange(int keyExchange) { - return new TlsDheKeyExchange(keyExchange, mSupportedSignatureAlgorithms, GetDHParameters()); + return new TlsDheKeyExchange(keyExchange, mSupportedSignatureAlgorithms, null, GetDHParameters()); } protected virtual TlsKeyExchange CreateECDHKeyExchange(int keyExchange) diff --git a/crypto/src/crypto/tls/PskTlsClient.cs b/crypto/src/crypto/tls/PskTlsClient.cs index 2ef80dcfd..d5fa43543 100644 --- a/crypto/src/crypto/tls/PskTlsClient.cs +++ b/crypto/src/crypto/tls/PskTlsClient.cs @@ -6,16 +6,23 @@ namespace Org.BouncyCastle.Crypto.Tls public class PskTlsClient : AbstractTlsClient { + protected TlsDHVerifier mDHVerifier; protected TlsPskIdentity mPskIdentity; public PskTlsClient(TlsPskIdentity pskIdentity) - : this(new DefaultTlsCipherFactory(), pskIdentity) + : this(new DefaultTlsCipherFactory(), pskIdentity) { } public PskTlsClient(TlsCipherFactory cipherFactory, TlsPskIdentity pskIdentity) - : base(cipherFactory) + : this(cipherFactory, new DefaultTlsDHVerifier(), pskIdentity) { + } + + public PskTlsClient(TlsCipherFactory cipherFactory, TlsDHVerifier dhVerifier, TlsPskIdentity pskIdentity) + : base(cipherFactory) + { + this.mDHVerifier = dhVerifier; this.mPskIdentity = pskIdentity; } @@ -25,8 +32,6 @@ namespace Org.BouncyCastle.Crypto.Tls { CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA, - CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA256, - CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA }; } @@ -63,8 +68,8 @@ namespace Org.BouncyCastle.Crypto.Tls protected virtual TlsKeyExchange CreatePskKeyExchange(int keyExchange) { - return new TlsPskKeyExchange(keyExchange, mSupportedSignatureAlgorithms, mPskIdentity, null, null, mNamedCurves, - mClientECPointFormats, mServerECPointFormats); + return new TlsPskKeyExchange(keyExchange, mSupportedSignatureAlgorithms, mPskIdentity, null, mDHVerifier, null, + mNamedCurves, mClientECPointFormats, mServerECPointFormats); } } } diff --git a/crypto/src/crypto/tls/PskTlsServer.cs b/crypto/src/crypto/tls/PskTlsServer.cs index b0fb67c04..a3778420d 100644 --- a/crypto/src/crypto/tls/PskTlsServer.cs +++ b/crypto/src/crypto/tls/PskTlsServer.cs @@ -87,7 +87,7 @@ namespace Org.BouncyCastle.Crypto.Tls protected virtual TlsKeyExchange CreatePskKeyExchange(int keyExchange) { return new TlsPskKeyExchange(keyExchange, mSupportedSignatureAlgorithms, null, mPskIdentityManager, - GetDHParameters(), mNamedCurves, mClientECPointFormats, mServerECPointFormats); + null, GetDHParameters(), mNamedCurves, mClientECPointFormats, mServerECPointFormats); } } } diff --git a/crypto/src/crypto/tls/ServerDHParams.cs b/crypto/src/crypto/tls/ServerDHParams.cs deleted file mode 100644 index b09262771..000000000 --- a/crypto/src/crypto/tls/ServerDHParams.cs +++ /dev/null @@ -1,61 +0,0 @@ -using System; -using System.IO; - -using Org.BouncyCastle.Crypto.Parameters; -using Org.BouncyCastle.Math; - -namespace Org.BouncyCastle.Crypto.Tls -{ - public class ServerDHParams - { - protected readonly DHPublicKeyParameters mPublicKey; - - public ServerDHParams(DHPublicKeyParameters publicKey) - { - if (publicKey == null) - throw new ArgumentNullException("publicKey"); - - this.mPublicKey = publicKey; - } - - public virtual DHPublicKeyParameters PublicKey - { - get { return mPublicKey; } - } - - /** - * Encode this {@link ServerDHParams} to a {@link Stream}. - * - * @param output - * the {@link Stream} to encode to. - * @throws IOException - */ - public virtual void Encode(Stream output) - { - DHParameters dhParameters = mPublicKey.Parameters; - BigInteger Ys = mPublicKey.Y; - - TlsDHUtilities.WriteDHParameter(dhParameters.P, output); - TlsDHUtilities.WriteDHParameter(dhParameters.G, output); - TlsDHUtilities.WriteDHParameter(Ys, output); - } - - /** - * Parse a {@link ServerDHParams} from a {@link Stream}. - * - * @param input - * the {@link Stream} to parse from. - * @return a {@link ServerDHParams} object. - * @throws IOException - */ - public static ServerDHParams Parse(Stream input) - { - BigInteger p = TlsDHUtilities.ReadDHParameter(input); - BigInteger g = TlsDHUtilities.ReadDHParameter(input); - BigInteger Ys = TlsDHUtilities.ReadDHParameter(input); - - return new ServerDHParams( - TlsDHUtilities.ValidateDHPublicKey(new DHPublicKeyParameters(Ys, new DHParameters(p, g)))); - } - } -} diff --git a/crypto/src/crypto/tls/TlsDHKeyExchange.cs b/crypto/src/crypto/tls/TlsDHKeyExchange.cs index d179068bb..59d52265b 100644 --- a/crypto/src/crypto/tls/TlsDHKeyExchange.cs +++ b/crypto/src/crypto/tls/TlsDHKeyExchange.cs @@ -4,7 +4,6 @@ using System.IO; using Org.BouncyCastle.Asn1.X509; using Org.BouncyCastle.Crypto.Parameters; -using Org.BouncyCastle.Math; using Org.BouncyCastle.Security; namespace Org.BouncyCastle.Crypto.Tls @@ -14,6 +13,7 @@ namespace Org.BouncyCastle.Crypto.Tls : AbstractTlsKeyExchange { protected TlsSigner mTlsSigner; + protected TlsDHVerifier mDHVerifier; protected DHParameters mDHParameters; protected AsymmetricKeyParameter mServerPublicKey; @@ -22,7 +22,7 @@ namespace Org.BouncyCastle.Crypto.Tls protected DHPrivateKeyParameters mDHAgreePrivateKey; protected DHPublicKeyParameters mDHAgreePublicKey; - public TlsDHKeyExchange(int keyExchange, IList supportedSignatureAlgorithms, DHParameters dhParameters) + public TlsDHKeyExchange(int keyExchange, IList supportedSignatureAlgorithms, TlsDHVerifier dhVerifier, DHParameters dhParameters) : base(keyExchange, supportedSignatureAlgorithms) { switch (keyExchange) @@ -42,6 +42,7 @@ namespace Org.BouncyCastle.Crypto.Tls throw new InvalidOperationException("unsupported key exchange algorithm"); } + this.mDHVerifier = dhVerifier; this.mDHParameters = dhParameters; } @@ -84,8 +85,8 @@ namespace Org.BouncyCastle.Crypto.Tls { try { - this.mDHAgreePublicKey = TlsDHUtilities.ValidateDHPublicKey((DHPublicKeyParameters)this.mServerPublicKey); - this.mDHParameters = ValidateDHParameters(mDHAgreePublicKey.Parameters); + this.mDHAgreePublicKey = (DHPublicKeyParameters)this.mServerPublicKey; + this.mDHParameters = mDHAgreePublicKey.Parameters; } catch (InvalidCastException e) { @@ -143,10 +144,8 @@ namespace Org.BouncyCastle.Crypto.Tls // DH_anon is handled here, DHE_* in a subclass - ServerDHParams dhParams = ServerDHParams.Parse(input); - - this.mDHAgreePublicKey = TlsDHUtilities.ValidateDHPublicKey(dhParams.PublicKey); - this.mDHParameters = ValidateDHParameters(mDHAgreePublicKey.Parameters); + this.mDHParameters = TlsDHUtilities.ReceiveDHParameters(mDHVerifier, input); + this.mDHAgreePublicKey = new DHPublicKeyParameters(TlsDHUtilities.ReadDHParameter(input), mDHParameters); } public override void ValidateCertificateRequest(CertificateRequest certificateRequest) @@ -223,9 +222,7 @@ namespace Org.BouncyCastle.Crypto.Tls return; } - BigInteger Yc = TlsDHUtilities.ReadDHParameter(input); - - this.mDHAgreePublicKey = TlsDHUtilities.ValidateDHPublicKey(new DHPublicKeyParameters(Yc, mDHParameters)); + this.mDHAgreePublicKey = new DHPublicKeyParameters(TlsDHUtilities.ReadDHParameter(input), mDHParameters); } public override byte[] GeneratePremasterSecret() @@ -242,18 +239,5 @@ namespace Org.BouncyCastle.Crypto.Tls throw new TlsFatalAlert(AlertDescription.internal_error); } - - protected virtual int MinimumPrimeBits - { - get { return 1024; } - } - - protected virtual DHParameters ValidateDHParameters(DHParameters parameters) - { - if (parameters.P.BitLength < MinimumPrimeBits) - throw new TlsFatalAlert(AlertDescription.insufficient_security); - - return TlsDHUtilities.ValidateDHParameters(parameters); - } } } diff --git a/crypto/src/crypto/tls/TlsDHUtilities.cs b/crypto/src/crypto/tls/TlsDHUtilities.cs index 6df61cbed..9567ee062 100644 --- a/crypto/src/crypto/tls/TlsDHUtilities.cs +++ b/crypto/src/crypto/tls/TlsDHUtilities.cs @@ -417,46 +417,43 @@ namespace Org.BouncyCastle.Crypto.Tls AsymmetricCipherKeyPair kp = GenerateDHKeyPair(random, dhParams); DHPublicKeyParameters dhPublic = (DHPublicKeyParameters)kp.Public; - new ServerDHParams(dhPublic).Encode(output); + WriteDHParameters(dhParams, output); + WriteDHParameter(dhPublic.Y, output); return (DHPrivateKeyParameters)kp.Private; } - public static DHParameters ValidateDHParameters(DHParameters parameters) + public static BigInteger ReadDHParameter(Stream input) { - BigInteger p = parameters.P; - BigInteger g = parameters.G; - - if (!p.IsProbablePrime(2)) - throw new TlsFatalAlert(AlertDescription.illegal_parameter); - if (g.CompareTo(Two) < 0 || g.CompareTo(p.Subtract(Two)) > 0) - throw new TlsFatalAlert(AlertDescription.illegal_parameter); - - - return parameters; + return new BigInteger(1, TlsUtilities.ReadOpaque16(input)); } - public static DHPublicKeyParameters ValidateDHPublicKey(DHPublicKeyParameters key) + public static DHParameters ReadDHParameters(Stream input) { - DHParameters parameters = ValidateDHParameters(key.Parameters); - - BigInteger Y = key.Y; - if (Y.CompareTo(Two) < 0 || Y.CompareTo(parameters.P.Subtract(Two)) > 0) - throw new TlsFatalAlert(AlertDescription.illegal_parameter); + BigInteger p = ReadDHParameter(input); + BigInteger g = ReadDHParameter(input); - // TODO See RFC 2631 for more discussion of Diffie-Hellman validation - - return key; + return new DHParameters(p, g); } - public static BigInteger ReadDHParameter(Stream input) + public static DHParameters ReceiveDHParameters(TlsDHVerifier dhVerifier, Stream input) { - return new BigInteger(1, TlsUtilities.ReadOpaque16(input)); + DHParameters dhParameters = ReadDHParameters(input); + if (!dhVerifier.Accept(dhParameters)) + throw new TlsFatalAlert(AlertDescription.insufficient_security); + + return dhParameters; } public static void WriteDHParameter(BigInteger x, Stream output) { TlsUtilities.WriteOpaque16(BigIntegers.AsUnsignedByteArray(x), output); } + + public static void WriteDHParameters(DHParameters dhParameters, Stream output) + { + WriteDHParameter(dhParameters.P, output); + WriteDHParameter(dhParameters.G, output); + } } } diff --git a/crypto/src/crypto/tls/TlsDHVerifier.cs b/crypto/src/crypto/tls/TlsDHVerifier.cs new file mode 100644 index 000000000..867403c3c --- /dev/null +++ b/crypto/src/crypto/tls/TlsDHVerifier.cs @@ -0,0 +1,15 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; + +namespace Org.BouncyCastle.Crypto.Tls +{ + /// <summary>An interface for verifying that Diffie-Hellman parameters are acceptable.</summary> + public interface TlsDHVerifier + { + /// <summary>Verify that the given <c>DHParameters</c> are acceptable.</summary> + /// <param name="dhParameters">The <c>DHParameters</c> to verify.</param> + /// <returns>true if (and only if) the specified parameters are acceptable.</returns> + bool Accept(DHParameters dhParameters); + } +} diff --git a/crypto/src/crypto/tls/TlsDheKeyExchange.cs b/crypto/src/crypto/tls/TlsDheKeyExchange.cs index cdd629247..402c74720 100644 --- a/crypto/src/crypto/tls/TlsDheKeyExchange.cs +++ b/crypto/src/crypto/tls/TlsDheKeyExchange.cs @@ -3,7 +3,6 @@ using System.Collections; using System.IO; using Org.BouncyCastle.Crypto.Parameters; -using Org.BouncyCastle.Math; using Org.BouncyCastle.Security; using Org.BouncyCastle.Utilities.IO; @@ -14,8 +13,8 @@ namespace Org.BouncyCastle.Crypto.Tls { protected TlsSignerCredentials mServerCredentials = null; - public TlsDheKeyExchange(int keyExchange, IList supportedSignatureAlgorithms, DHParameters dhParameters) - : base(keyExchange, supportedSignatureAlgorithms, dhParameters) + public TlsDheKeyExchange(int keyExchange, IList supportedSignatureAlgorithms, TlsDHVerifier dhVerifier, DHParameters dhParameters) + : base(keyExchange, supportedSignatureAlgorithms, dhVerifier, dhParameters) { } @@ -69,7 +68,8 @@ namespace Org.BouncyCastle.Crypto.Tls SignerInputBuffer buf = new SignerInputBuffer(); Stream teeIn = new TeeInputStream(input, buf); - ServerDHParams dhParams = ServerDHParams.Parse(teeIn); + this.mDHParameters = TlsDHUtilities.ReceiveDHParameters(mDHVerifier, teeIn); + this.mDHAgreePublicKey = new DHPublicKeyParameters(TlsDHUtilities.ReadDHParameter(teeIn), mDHParameters); DigitallySigned signed_params = ParseSignature(input); @@ -77,9 +77,6 @@ namespace Org.BouncyCastle.Crypto.Tls buf.UpdateSigner(signer); if (!signer.VerifySignature(signed_params.Signature)) throw new TlsFatalAlert(AlertDescription.decrypt_error); - - this.mDHAgreePublicKey = TlsDHUtilities.ValidateDHPublicKey(dhParams.PublicKey); - this.mDHParameters = ValidateDHParameters(mDHAgreePublicKey.Parameters); } protected virtual ISigner InitVerifyer(TlsSigner tlsSigner, SignatureAndHashAlgorithm algorithm, diff --git a/crypto/src/crypto/tls/TlsPskKeyExchange.cs b/crypto/src/crypto/tls/TlsPskKeyExchange.cs index 0af7f7a69..36ef09e85 100644 --- a/crypto/src/crypto/tls/TlsPskKeyExchange.cs +++ b/crypto/src/crypto/tls/TlsPskKeyExchange.cs @@ -4,7 +4,6 @@ using System.IO; using Org.BouncyCastle.Asn1.X509; using Org.BouncyCastle.Crypto.Parameters; -using Org.BouncyCastle.Math; using Org.BouncyCastle.Security; using Org.BouncyCastle.Utilities; using Org.BouncyCastle.Utilities.IO; @@ -18,6 +17,7 @@ namespace Org.BouncyCastle.Crypto.Tls protected TlsPskIdentity mPskIdentity; protected TlsPskIdentityManager mPskIdentityManager; + protected TlsDHVerifier mDHVerifier; protected DHParameters mDHParameters; protected int[] mNamedCurves; protected byte[] mClientECPointFormats, mServerECPointFormats; @@ -37,7 +37,7 @@ namespace Org.BouncyCastle.Crypto.Tls protected byte[] mPremasterSecret; public TlsPskKeyExchange(int keyExchange, IList supportedSignatureAlgorithms, TlsPskIdentity pskIdentity, - TlsPskIdentityManager pskIdentityManager, DHParameters dhParameters, int[] namedCurves, + TlsPskIdentityManager pskIdentityManager, TlsDHVerifier dhVerifier, DHParameters dhParameters, int[] namedCurves, byte[] clientECPointFormats, byte[] serverECPointFormats) : base(keyExchange, supportedSignatureAlgorithms) { @@ -54,6 +54,7 @@ namespace Org.BouncyCastle.Crypto.Tls this.mPskIdentity = pskIdentity; this.mPskIdentityManager = pskIdentityManager; + this.mDHVerifier = dhVerifier; this.mDHParameters = dhParameters; this.mNamedCurves = namedCurves; this.mClientECPointFormats = clientECPointFormats; @@ -162,10 +163,8 @@ namespace Org.BouncyCastle.Crypto.Tls if (this.mKeyExchange == KeyExchangeAlgorithm.DHE_PSK) { - ServerDHParams serverDHParams = ServerDHParams.Parse(input); - - this.mDHAgreePublicKey = TlsDHUtilities.ValidateDHPublicKey(serverDHParams.PublicKey); - this.mDHParameters = mDHAgreePublicKey.Parameters; + this.mDHParameters = TlsDHUtilities.ReceiveDHParameters(mDHVerifier, input); + this.mDHAgreePublicKey = new DHPublicKeyParameters(TlsDHUtilities.ReadDHParameter(input), mDHParameters); } else if (this.mKeyExchange == KeyExchangeAlgorithm.ECDHE_PSK) { @@ -240,9 +239,7 @@ namespace Org.BouncyCastle.Crypto.Tls if (this.mKeyExchange == KeyExchangeAlgorithm.DHE_PSK) { - BigInteger Yc = TlsDHUtilities.ReadDHParameter(input); - - this.mDHAgreePublicKey = TlsDHUtilities.ValidateDHPublicKey(new DHPublicKeyParameters(Yc, mDHParameters)); + this.mDHAgreePublicKey = new DHPublicKeyParameters(TlsDHUtilities.ReadDHParameter(input), mDHParameters); } else if (this.mKeyExchange == KeyExchangeAlgorithm.ECDHE_PSK) { diff --git a/crypto/src/pkcs/Pkcs10CertificationRequest.cs b/crypto/src/pkcs/Pkcs10CertificationRequest.cs index 24dc9b1cc..34bda3815 100644 --- a/crypto/src/pkcs/Pkcs10CertificationRequest.cs +++ b/crypto/src/pkcs/Pkcs10CertificationRequest.cs @@ -210,71 +210,73 @@ namespace Org.BouncyCastle.Pkcs /// <param name="publicKey">Public Key to be included in cert reqest.</param> /// <param name="attributes">ASN1Set of Attributes.</param> /// <param name="signingKey">Matching Private key for nominated (above) public key to be used to sign the request.</param> - [Obsolete("Use constructor with an ISignatureFactory")] public Pkcs10CertificationRequest( string signatureAlgorithm, X509Name subject, AsymmetricKeyParameter publicKey, Asn1Set attributes, AsymmetricKeyParameter signingKey) + : this(new Asn1SignatureFactory(signatureAlgorithm, signingKey), subject, publicKey, attributes) { - if (signatureAlgorithm == null) - throw new ArgumentNullException("signatureAlgorithm"); - if (subject == null) - throw new ArgumentNullException("subject"); - if (publicKey == null) - throw new ArgumentNullException("publicKey"); - if (publicKey.IsPrivate) - throw new ArgumentException("expected public key", "publicKey"); - if (!signingKey.IsPrivate) - throw new ArgumentException("key for signing must be private", "signingKey"); - - init(new Asn1SignatureFactory(signatureAlgorithm, signingKey), subject, publicKey, attributes, signingKey); } /// <summary> /// Instantiate a Pkcs10CertificationRequest object with the necessary credentials. /// </summary> - ///<param name="signatureCalculatorFactory">The factory for signature calculators to sign the PKCS#10 request with.</param> + ///<param name="signatureFactory">The factory for signature calculators to sign the PKCS#10 request with.</param> /// <param name="subject">X509Name of subject eg OU="My unit." O="My Organisatioin" C="au" </param> /// <param name="publicKey">Public Key to be included in cert reqest.</param> /// <param name="attributes">ASN1Set of Attributes.</param> - /// <param name="signingKey">Matching Private key for nominated (above) public key to be used to sign the request.</param> + /// <param name="signingKey">Ignored.</param> + [Obsolete("Use constructor without 'signingKey' parameter (ignored here)")] public Pkcs10CertificationRequest( - ISignatureFactory signatureCalculatorFactory, + ISignatureFactory signatureFactory, X509Name subject, AsymmetricKeyParameter publicKey, Asn1Set attributes, AsymmetricKeyParameter signingKey) + : this(signatureFactory, subject, publicKey, attributes) { - if (signatureCalculatorFactory == null) - throw new ArgumentNullException("signatureCalculator"); + } + + /// <summary> + /// Instantiate a Pkcs10CertificationRequest object with the necessary credentials. + /// </summary> + ///<param name="signatureFactory">The factory for signature calculators to sign the PKCS#10 request with.</param> + /// <param name="subject">X509Name of subject eg OU="My unit." O="My Organisatioin" C="au" </param> + /// <param name="publicKey">Public Key to be included in cert reqest.</param> + /// <param name="attributes">ASN1Set of Attributes.</param> + public Pkcs10CertificationRequest( + ISignatureFactory signatureFactory, + X509Name subject, + AsymmetricKeyParameter publicKey, + Asn1Set attributes) + { + if (signatureFactory == null) + throw new ArgumentNullException("signatureFactory"); if (subject == null) throw new ArgumentNullException("subject"); if (publicKey == null) throw new ArgumentNullException("publicKey"); if (publicKey.IsPrivate) throw new ArgumentException("expected public key", "publicKey"); - if (!signingKey.IsPrivate) - throw new ArgumentException("key for signing must be private", "signingKey"); - init(signatureCalculatorFactory, subject, publicKey, attributes, signingKey); + Init(signatureFactory, subject, publicKey, attributes); } - private void init( - ISignatureFactory signatureCalculator, + private void Init( + ISignatureFactory signatureFactory, X509Name subject, AsymmetricKeyParameter publicKey, - Asn1Set attributes, - AsymmetricKeyParameter signingKey) + Asn1Set attributes) { - this.sigAlgId = (AlgorithmIdentifier)signatureCalculator.AlgorithmDetails; + this.sigAlgId = (AlgorithmIdentifier)signatureFactory.AlgorithmDetails; SubjectPublicKeyInfo pubInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(publicKey); this.reqInfo = new CertificationRequestInfo(subject, pubInfo, attributes); - IStreamCalculator streamCalculator = signatureCalculator.CreateCalculator(); + IStreamCalculator streamCalculator = signatureFactory.CreateCalculator(); byte[] reqInfoData = reqInfo.GetDerEncoded(); diff --git a/crypto/src/x509/store/X509CertStoreSelector.cs b/crypto/src/x509/store/X509CertStoreSelector.cs index 3874edf1d..f92a4ac03 100644 --- a/crypto/src/x509/store/X509CertStoreSelector.cs +++ b/crypto/src/x509/store/X509CertStoreSelector.cs @@ -21,6 +21,7 @@ namespace Org.BouncyCastle.X509.Store private X509Certificate certificate; private DateTimeObject certificateValid; private ISet extendedKeyUsage; + private bool ignoreX509NameOrdering; private X509Name issuer; private bool[] keyUsage; private ISet policy; @@ -43,6 +44,7 @@ namespace Org.BouncyCastle.X509.Store this.certificate = o.Certificate; this.certificateValid = o.CertificateValid; this.extendedKeyUsage = o.ExtendedKeyUsage; + this.ignoreX509NameOrdering = o.IgnoreX509NameOrdering; this.issuer = o.Issuer; this.keyUsage = o.KeyUsage; this.policy = o.Policy; @@ -95,6 +97,12 @@ namespace Org.BouncyCastle.X509.Store set { extendedKeyUsage = CopySet(value); } } + public bool IgnoreX509NameOrdering + { + get { return ignoreX509NameOrdering; } + set { this.ignoreX509NameOrdering = value; } + } + public X509Name Issuer { get { return issuer; } @@ -140,7 +148,8 @@ namespace Org.BouncyCastle.X509.Store set { subject = value; } } - public string SubjectAsString + [Obsolete("Avoid working with X509Name objects in string form")] + public string SubjectAsString { get { return subject != null ? subject.ToString() : null; } } @@ -212,7 +221,7 @@ namespace Org.BouncyCastle.X509.Store } } - if (issuer != null && !issuer.Equivalent(c.IssuerDN, true)) + if (issuer != null && !issuer.Equivalent(c.IssuerDN, !ignoreX509NameOrdering)) return false; if (keyUsage != null) @@ -277,7 +286,7 @@ namespace Org.BouncyCastle.X509.Store if (serialNumber != null && !serialNumber.Equals(c.SerialNumber)) return false; - if (subject != null && !subject.Equivalent(c.SubjectDN, true)) + if (subject != null && !subject.Equivalent(c.SubjectDN, !ignoreX509NameOrdering)) return false; if (!MatchExtension(subjectKeyIdentifier, c, X509Extensions.SubjectKeyIdentifier)) diff --git a/crypto/test/src/crypto/test/OAEPTest.cs b/crypto/test/src/crypto/test/OAEPTest.cs index 39af21137..781e92ba5 100644 --- a/crypto/test/src/crypto/test/OAEPTest.cs +++ b/crypto/test/src/crypto/test/OAEPTest.cs @@ -8,6 +8,7 @@ using Org.BouncyCastle.Asn1.X509; using Org.BouncyCastle.Crypto.Digests; using Org.BouncyCastle.Crypto.Encodings; using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Generators; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Math; using Org.BouncyCastle.Security; @@ -780,8 +781,10 @@ namespace Org.BouncyCastle.Crypto.Tests OaepVecTest(1027, 5, pubParam, privParam, seed_1027_5, input_1027_5, output_1027_5); OaepVecTest(1027, 6, pubParam, privParam, seed_1027_6, input_1027_6, output_1027_6); + TestForHighByteError("invalidCiphertextOaepTest 1024", 1024); + // - // OAEP - public encrypt, private decrypt differring hashes + // OAEP - public encrypt, private decrypt, differing hashes // IAsymmetricBlockCipher cipher = new OaepEncoding(new RsaEngine(), new Sha256Digest(), new Sha1Digest(), new byte[10]); @@ -822,8 +825,78 @@ namespace Org.BouncyCastle.Crypto.Tests } } - public static void MainOld( - string[] args) + private void TestForHighByteError(string label, int keySizeBits) + { + // draw a key of the size asked + BigInteger e = BigInteger.One.ShiftLeft(16).Add(BigInteger.One); + + IAsymmetricCipherKeyPairGenerator kpGen = new RsaKeyPairGenerator(); + + kpGen.Init(new RsaKeyGenerationParameters(e, new SecureRandom(), keySizeBits, 100)); + + AsymmetricCipherKeyPair kp = kpGen.GenerateKeyPair(); + + IAsymmetricBlockCipher cipher = new OaepEncoding(new RsaEngine()); + + // obtain a known good ciphertext + cipher.Init(true, new ParametersWithRandom(kp.Public, new VecRand(seed))); + byte[] m = { 42 }; + byte[] c = cipher.ProcessBlock(m, 0, m.Length); + int keySizeBytes = (keySizeBits + 7) / 8; + if (c.Length != keySizeBytes) + { + Fail(label + " failed ciphertext size"); + } + + BigInteger n = ((RsaPrivateCrtKeyParameters)kp.Private).Modulus; + + // decipher + cipher.Init(false, kp.Private); + byte[] r = cipher.ProcessBlock(c, 0, keySizeBytes); + if (r.Length != 1 || r[0] != 42) + { + Fail(label + " failed first decryption of test message"); + } + + // decipher again + r = cipher.ProcessBlock(c, 0, keySizeBytes); + if (r.Length != 1 || r[0] != 42) + { + Fail(label + " failed second decryption of test message"); + } + + // check hapazard incorrect ciphertexts + for (int i = keySizeBytes * 8; --i >= 0; ) + { + c[i / 8] ^= (byte)(1 << (i & 7)); + bool ko = true; + try + { + BigInteger cV = new BigInteger(1, c); + + // don't pass in c if it will be rejected trivially + if (cV.CompareTo(n) < 0) + { + r = cipher.ProcessBlock(c, 0, keySizeBytes); + } + else + { + ko = false; // size errors are picked up at start + } + } + catch (InvalidCipherTextException) + { + ko = false; + } + if (ko) + { + Fail(label + " invalid ciphertext caused no exception"); + } + c[i / 8] ^= (byte)(1 << (i & 7)); + } + } + + public static void MainOld(string[] args) { RunTest(new OaepTest()); } |