From e6aa0cac548933ea29e4eb8abab505af740a49ea Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Wed, 14 Oct 2015 13:53:25 +0700 Subject: Added "Lenstra" check --- crypto/src/crypto/engines/RSABlindedEngine.cs | 198 +++++++++++++------------- 1 file changed, 101 insertions(+), 97 deletions(-) diff --git a/crypto/src/crypto/engines/RSABlindedEngine.cs b/crypto/src/crypto/engines/RSABlindedEngine.cs index 037abf7e9..f95f145f6 100644 --- a/crypto/src/crypto/engines/RSABlindedEngine.cs +++ b/crypto/src/crypto/engines/RSABlindedEngine.cs @@ -7,118 +7,122 @@ using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Crypto.Engines { - /** - * this does your basic RSA algorithm with blinding - */ - public class RsaBlindedEngine - : IAsymmetricBlockCipher - { - private readonly RsaCoreEngine core = new RsaCoreEngine(); - private RsaKeyParameters key; - private SecureRandom random; + /** + * this does your basic RSA algorithm with blinding + */ + public class RsaBlindedEngine + : IAsymmetricBlockCipher + { + private readonly RsaCoreEngine core = new RsaCoreEngine(); + private RsaKeyParameters key; + private SecureRandom random; public virtual string AlgorithmName - { - get { return "RSA"; } - } + { + get { return "RSA"; } + } - /** - * initialise the RSA engine. - * - * @param forEncryption true if we are encrypting, false otherwise. - * @param param the necessary RSA key parameters. - */ + /** + * initialise the RSA engine. + * + * @param forEncryption true if we are encrypting, false otherwise. + * @param param the necessary RSA key parameters. + */ public virtual void Init( - bool forEncryption, - ICipherParameters param) - { - core.Init(forEncryption, param); + bool forEncryption, + ICipherParameters param) + { + core.Init(forEncryption, param); - if (param is ParametersWithRandom) - { - ParametersWithRandom rParam = (ParametersWithRandom)param; + if (param is ParametersWithRandom) + { + ParametersWithRandom rParam = (ParametersWithRandom)param; - key = (RsaKeyParameters)rParam.Parameters; - random = rParam.Random; - } - else - { - key = (RsaKeyParameters)param; - random = new SecureRandom(); - } - } + key = (RsaKeyParameters)rParam.Parameters; + random = rParam.Random; + } + else + { + key = (RsaKeyParameters)param; + random = new SecureRandom(); + } + } - /** - * Return the maximum size for an input block to this engine. - * For RSA this is always one byte less than the key size on - * encryption, and the same length as the key size on decryption. - * - * @return maximum size for an input block. - */ + /** + * Return the maximum size for an input block to this engine. + * For RSA this is always one byte less than the key size on + * encryption, and the same length as the key size on decryption. + * + * @return maximum size for an input block. + */ public virtual int GetInputBlockSize() - { - return core.GetInputBlockSize(); - } + { + return core.GetInputBlockSize(); + } - /** - * Return the maximum size for an output block to this engine. - * For RSA this is always one byte less than the key size on - * decryption, and the same length as the key size on encryption. - * - * @return maximum size for an output block. - */ + /** + * Return the maximum size for an output block to this engine. + * For RSA this is always one byte less than the key size on + * decryption, and the same length as the key size on encryption. + * + * @return maximum size for an output block. + */ public virtual int GetOutputBlockSize() - { - return core.GetOutputBlockSize(); - } + { + return core.GetOutputBlockSize(); + } - /** - * Process a single block using the basic RSA algorithm. - * - * @param inBuf the input array. - * @param inOff the offset into the input buffer where the data starts. - * @param inLen the length of the data to be processed. - * @return the result of the RSA process. - * @exception DataLengthException the input block is too large. - */ + /** + * Process a single block using the basic RSA algorithm. + * + * @param inBuf the input array. + * @param inOff the offset into the input buffer where the data starts. + * @param inLen the length of the data to be processed. + * @return the result of the RSA process. + * @exception DataLengthException the input block is too large. + */ public virtual byte[] ProcessBlock( - byte[] inBuf, - int inOff, - int inLen) - { - if (key == null) - throw new InvalidOperationException("RSA engine not initialised"); + byte[] inBuf, + int inOff, + int inLen) + { + if (key == null) + throw new InvalidOperationException("RSA engine not initialised"); - BigInteger input = core.ConvertInput(inBuf, inOff, inLen); + BigInteger input = core.ConvertInput(inBuf, inOff, inLen); - BigInteger result; - if (key is RsaPrivateCrtKeyParameters) - { - RsaPrivateCrtKeyParameters k = (RsaPrivateCrtKeyParameters)key; - BigInteger e = k.PublicExponent; - if (e != null) // can't do blinding without a public exponent - { - BigInteger m = k.Modulus; - BigInteger r = BigIntegers.CreateRandomInRange( - BigInteger.One, m.Subtract(BigInteger.One), random); + BigInteger result; + if (key is RsaPrivateCrtKeyParameters) + { + RsaPrivateCrtKeyParameters k = (RsaPrivateCrtKeyParameters)key; + BigInteger e = k.PublicExponent; + if (e != null) // can't do blinding without a public exponent + { + BigInteger m = k.Modulus; + BigInteger r = BigIntegers.CreateRandomInRange( + BigInteger.One, m.Subtract(BigInteger.One), random); - BigInteger blindedInput = r.ModPow(e, m).Multiply(input).Mod(m); - BigInteger blindedResult = core.ProcessBlock(blindedInput); + BigInteger blindedInput = r.ModPow(e, m).Multiply(input).Mod(m); + BigInteger blindedResult = core.ProcessBlock(blindedInput); - BigInteger rInv = r.ModInverse(m); - result = blindedResult.Multiply(rInv).Mod(m); - } - else - { - result = core.ProcessBlock(input); - } - } - else - { - result = core.ProcessBlock(input); - } + BigInteger rInv = r.ModInverse(m); + result = blindedResult.Multiply(rInv).Mod(m); - return core.ConvertOutput(result); - } - } + // defence against Arjen Lenstra’s CRT attack + if (!input.Equals(result.ModPow(e, m))) + throw new InvalidOperationException("RSA engine faulty decryption/signing detected"); + } + else + { + result = core.ProcessBlock(input); + } + } + else + { + result = core.ProcessBlock(input); + } + + return core.ConvertOutput(result); + } + } } -- cgit 1.4.1