DiffieHellman.cs 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. using System;
  2. using System.Diagnostics.Contracts;
  3. using System.Globalization;
  4. using System.Linq;
  5. using System.Numerics;
  6. using System.Security.Cryptography;
  7. namespace FxSsh.Algorithms
  8. {
  9. public class DiffieHellman : AsymmetricAlgorithm
  10. {
  11. // http://tools.ietf.org/html/rfc2412
  12. private const string Okley1024 = "00FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF";
  13. // http://tools.ietf.org/html/rfc3526
  14. private const string Okley2048 = "00FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF";
  15. private static readonly RandomNumberGenerator _rng = RandomNumberGenerator.Create();
  16. private BigInteger _p;
  17. private BigInteger _g;
  18. private BigInteger _x;
  19. public DiffieHellman(int bitlen)
  20. {
  21. Contract.Requires(bitlen == 1024 || bitlen == 2048);
  22. if (bitlen == 1024)
  23. {
  24. _p = BigInteger.Parse(Okley1024, NumberStyles.HexNumber);
  25. _g = new BigInteger(2);
  26. }
  27. else if (bitlen == 2048)
  28. {
  29. _p = BigInteger.Parse(Okley2048, NumberStyles.HexNumber);
  30. _g = new BigInteger(2);
  31. }
  32. else
  33. throw new ArgumentException("bitlen", "bitlen must equal 1024 or 2048");
  34. var bytes = new byte[80]; // 80 * 8 = 640 bits
  35. _rng.GetBytes(bytes);
  36. _x = BigInteger.Abs(new BigInteger(bytes));
  37. }
  38. public byte[] CreateKeyExchange()
  39. {
  40. var y = BigInteger.ModPow(_g, _x, _p);
  41. var bytes = BigintToBytes(y);
  42. return bytes;
  43. }
  44. public byte[] DecryptKeyExchange(byte[] keyEx)
  45. {
  46. Contract.Requires(keyEx != null);
  47. var pvr = BytesToBigint(keyEx);
  48. var z = BigInteger.ModPow(pvr, _x, _p);
  49. var bytes = BigintToBytes(z);
  50. return bytes;
  51. }
  52. private BigInteger BytesToBigint(byte[] bytes)
  53. {
  54. return new BigInteger(bytes.Reverse().Concat(new byte[] { 0 }).ToArray());
  55. }
  56. private byte[] BigintToBytes(BigInteger bigint)
  57. {
  58. var bytes = bigint.ToByteArray();
  59. if (bytes.Length > 1 && bytes[bytes.Length - 1] == 0)
  60. {
  61. return bytes.Reverse().Skip(1).ToArray();
  62. }
  63. return bytes.Reverse().ToArray();
  64. }
  65. }
  66. }