<PackageReference Include="BouncyCastle.Cryptography" Version="2.5.0" />

RsaBlindedEngine

using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Math; using Org.BouncyCastle.Security; using Org.BouncyCastle.Utilities; using System; namespace Org.BouncyCastle.Crypto.Engines { public class RsaBlindedEngine : IAsymmetricBlockCipher { private readonly IRsa core; private RsaKeyParameters key; private SecureRandom random; public virtual string AlgorithmName => "RSA"; public RsaBlindedEngine() : this(new RsaCoreEngine()) { } public RsaBlindedEngine(IRsa rsa) { core = rsa; } public virtual void Init(bool forEncryption, ICipherParameters param) { SecureRandom provided = null; ParametersWithRandom parametersWithRandom = param as ParametersWithRandom; if (parametersWithRandom != null) { provided = parametersWithRandom.Random; param = parametersWithRandom.Parameters; } core.Init(forEncryption, param); key = (RsaKeyParameters)param; random = InitSecureRandom(key is RsaPrivateCrtKeyParameters, provided); } public virtual int GetInputBlockSize() { return core.GetInputBlockSize(); } public virtual int GetOutputBlockSize() { return core.GetOutputBlockSize(); } public virtual byte[] ProcessBlock(byte[] inBuf, int inOff, int inLen) { if (key == null) throw new InvalidOperationException("RSA engine not initialised"); BigInteger input = core.ConvertInput(inBuf, inOff, inLen); BigInteger result = ProcessInput(input); return core.ConvertOutput(result); } protected virtual SecureRandom InitSecureRandom(bool needed, SecureRandom provided) { if (!needed) return null; return CryptoServicesRegistrar.GetSecureRandom(provided); } private BigInteger ProcessInput(BigInteger input) { RsaPrivateCrtKeyParameters rsaPrivateCrtKeyParameters = key as RsaPrivateCrtKeyParameters; if (rsaPrivateCrtKeyParameters == null) return core.ProcessBlock(input); BigInteger publicExponent = rsaPrivateCrtKeyParameters.PublicExponent; BigInteger modulus = rsaPrivateCrtKeyParameters.Modulus; BigInteger bigInteger = BigIntegers.CreateRandomInRange(BigInteger.One, modulus.Subtract(BigInteger.One), random); BigInteger bigInteger2 = bigInteger.ModPow(publicExponent, modulus); BigInteger bigInteger3 = BigIntegers.ModOddInverse(modulus, bigInteger); BigInteger input2 = bigInteger2.Multiply(input).Mod(modulus); BigInteger val = core.ProcessBlock(input2); return bigInteger3.Multiply(val).Mod(modulus); } } }