RSACipher.cs 3.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Security.Cryptography;
  6. using Renci.SshNet.Common;
  7. namespace Renci.SshNet.Security.Cryptography
  8. {
  9. /// <summary>
  10. /// RSA algorithm implementation
  11. /// </summary>
  12. public class RSACipher : AsymmetricCipher
  13. {
  14. private static RNGCryptoServiceProvider _randomizer = new System.Security.Cryptography.RNGCryptoServiceProvider();
  15. private RSAPublicKey _key;
  16. /// <summary>
  17. /// Initializes a new instance of the <see cref="RSACipher"/> class.
  18. /// </summary>
  19. /// <param name="hash">The hash.</param>
  20. /// <param name="key">The key.</param>
  21. public RSACipher(HashAlgorithm hash, RSAPublicKey key)
  22. {
  23. this._key = key;
  24. }
  25. /// <summary>
  26. /// Transforms the specified data.
  27. /// </summary>
  28. /// <param name="data">The data.</param>
  29. /// <returns></returns>
  30. public override byte[] Transform(byte[] data)
  31. {
  32. var bytes = new List<byte>(data.Reverse());
  33. bytes.Add(0);
  34. return this.Transform(new BigInteger(bytes.ToArray())).ToByteArray().Reverse().ToArray();
  35. }
  36. /// <summary>
  37. /// Transforms the specified input.
  38. /// </summary>
  39. /// <param name="input">The input.</param>
  40. /// <returns></returns>
  41. public override BigInteger Transform(BigInteger input)
  42. {
  43. var privateKey = this._key as RSAPrivateKey;
  44. if (privateKey != null)
  45. {
  46. BigInteger random = BigInteger.One;
  47. var max = this._key.Modulus - 1;
  48. while (random <= BigInteger.One || random >= max)
  49. {
  50. var bytesArray = new byte[256];
  51. _randomizer.GetBytes(bytesArray);
  52. bytesArray[bytesArray.Length - 1] = (byte)(bytesArray[bytesArray.Length - 1] & 0x7F); // Ensure not a negative value
  53. random = new BigInteger(bytesArray.Reverse().ToArray());
  54. }
  55. BigInteger blindedInput = BigInteger.PositiveMod((BigInteger.ModPow(random, this._key.Exponent, this._key.Modulus) * input), this._key.Modulus);
  56. // mP = ((input Mod p) ^ dP)) Mod p
  57. var mP = BigInteger.ModPow((blindedInput % privateKey.P), privateKey.DP, privateKey.P);
  58. // mQ = ((input Mod q) ^ dQ)) Mod q
  59. var mQ = BigInteger.ModPow((blindedInput % privateKey.Q), privateKey.DQ, privateKey.Q);
  60. var h = BigInteger.PositiveMod(((mP - mQ) * privateKey.InverseQ), privateKey.P);
  61. var m = h * privateKey.Q + mQ;
  62. BigInteger rInv = BigInteger.ModInverse(random, this._key.Modulus);
  63. return BigInteger.PositiveMod((m * rInv), this._key.Modulus);
  64. }
  65. else
  66. {
  67. var value = BigInteger.ModPow(input, this._key.Exponent, this._key.Modulus);
  68. return value;
  69. }
  70. }
  71. }
  72. }