/// <summary> /// Low level RSA Process function for use with private key. /// Should never be used; Because without padding RSA is vulnerable to attacks. Use with caution. /// </summary> /// <param name="plainText">Data to encrypt. Length must be less than Modulus size in octets.</param> /// <param name="usePrivate">True to use Private key, else Public.</param> /// <returns>Encrypted Data</returns> private byte[] RSAProcess(byte[] plainText, bool usePrivate) { if (usePrivate && !rsaParams.HasPrivateInfo) { throw new CryptographicException("RSA Process: Incomplete Private Key Info"); } if (usePrivate == false && !rsaParams.HasPublicInfo) { throw new CryptographicException("RSA Process: Incomplete Public Key Info"); } BigInteger e = usePrivate ? rsaParams.D : rsaParams.E; BigInteger pt = RSAxUtils.OS2IP(plainText, false); BigInteger m = BigInteger.ModPow(pt, e, rsaParams.N); if (m.Sign == -1) { return(RSAxUtils.I2OSP(m + rsaParams.N, rsaParams.OctetsInModulus, false)); } else { return(RSAxUtils.I2OSP(m, rsaParams.OctetsInModulus, false)); } }
/// <summary> /// Low level RSA Decryption function for use with private key. Uses CRT and is Much faster. /// Should never be used; Because without padding RSA is vulnerable to attacks. Use with caution. /// </summary> /// <param name="data">Data to encrypt. Length must be less than Modulus size in octets.</param> /// <returns>Encrypted Data</returns> private byte[] RSADecryptPrivateCRT(byte[] data) { if (rsaParams.HasPrivateInfo && rsaParams.HasCRTInfo) { BigInteger c = RSAxUtils.OS2IP(data, false); BigInteger m1 = BigInteger.ModPow(c, rsaParams.DP, rsaParams.P); BigInteger m2 = BigInteger.ModPow(c, rsaParams.DQ, rsaParams.Q); BigInteger h = (m1 - m2) * rsaParams.InverseQ % rsaParams.P; BigInteger m = m2 + rsaParams.Q * h; if (m.Sign == -1) { return(RSAxUtils.I2OSP(m + rsaParams.N, rsaParams.OctetsInModulus, false)); } else { return(RSAxUtils.I2OSP(m, rsaParams.OctetsInModulus, false)); } } else { throw new CryptographicException("RSA Decrypt CRT: Incomplete Key Info"); } }
/// <summary> /// Mask Generation Function /// </summary> /// <param name="z">Initial pseudorandom Seed.</param> /// <param name="l">Length of output required.</param> /// <returns></returns> private byte[] MGF(byte[] z, int l) { if (l > Math.Pow(2, 32)) { throw new ArgumentException("Mask too long."); } List <byte> result = new List <byte>(); for (int i = 0; i <= l / rsaParams.HLen; i++) { List <byte> data = new List <byte>(); data.AddRange(z); data.AddRange(RSAxUtils.I2OSP(i, 4, false)); result.AddRange(rsaParams.ComputeHash(data.ToArray())); } if (l > result.Count) { throw new ArgumentException("Invalid Mask Length."); } return(result.GetRange(0, l).ToArray()); }