DHAgreement.cs 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. #pragma warning disable
  3. using System;
  4. using System.Diagnostics;
  5. using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Generators;
  6. using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
  7. using BestHTTP.SecureProtocol.Org.BouncyCastle.Math;
  8. using BestHTTP.SecureProtocol.Org.BouncyCastle.Security;
  9. namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Agreement
  10. {
  11. /**
  12. * a Diffie-Hellman key exchange engine.
  13. * <p>
  14. * note: This uses MTI/A0 key agreement in order to make the key agreement
  15. * secure against passive attacks. If you're doing Diffie-Hellman and both
  16. * parties have long term public keys you should look at using this. For
  17. * further information have a look at RFC 2631.</p>
  18. * <p>
  19. * It's possible to extend this to more than two parties as well, for the moment
  20. * that is left as an exercise for the reader.</p>
  21. */
  22. public class DHAgreement
  23. {
  24. private DHPrivateKeyParameters key;
  25. private DHParameters dhParams;
  26. private BigInteger privateValue;
  27. private SecureRandom random;
  28. public void Init(
  29. ICipherParameters parameters)
  30. {
  31. AsymmetricKeyParameter kParam;
  32. if (parameters is ParametersWithRandom)
  33. {
  34. ParametersWithRandom rParam = (ParametersWithRandom)parameters;
  35. this.random = rParam.Random;
  36. kParam = (AsymmetricKeyParameter)rParam.Parameters;
  37. }
  38. else
  39. {
  40. this.random = new SecureRandom();
  41. kParam = (AsymmetricKeyParameter)parameters;
  42. }
  43. if (!(kParam is DHPrivateKeyParameters))
  44. {
  45. throw new ArgumentException("DHEngine expects DHPrivateKeyParameters");
  46. }
  47. this.key = (DHPrivateKeyParameters)kParam;
  48. this.dhParams = key.Parameters;
  49. }
  50. /**
  51. * calculate our initial message.
  52. */
  53. public BigInteger CalculateMessage()
  54. {
  55. DHKeyPairGenerator dhGen = new DHKeyPairGenerator();
  56. dhGen.Init(new DHKeyGenerationParameters(random, dhParams));
  57. AsymmetricCipherKeyPair dhPair = dhGen.GenerateKeyPair();
  58. this.privateValue = ((DHPrivateKeyParameters)dhPair.Private).X;
  59. return ((DHPublicKeyParameters)dhPair.Public).Y;
  60. }
  61. /**
  62. * given a message from a given party and the corresponding public key
  63. * calculate the next message in the agreement sequence. In this case
  64. * this will represent the shared secret.
  65. */
  66. public BigInteger CalculateAgreement(
  67. DHPublicKeyParameters pub,
  68. BigInteger message)
  69. {
  70. if (pub == null)
  71. throw new ArgumentNullException("pub");
  72. if (message == null)
  73. throw new ArgumentNullException("message");
  74. if (!pub.Parameters.Equals(dhParams))
  75. throw new ArgumentException("Diffie-Hellman public key has wrong parameters.");
  76. BigInteger p = dhParams.P;
  77. BigInteger peerY = pub.Y;
  78. if (peerY == null || peerY.CompareTo(BigInteger.One) <= 0 || peerY.CompareTo(p.Subtract(BigInteger.One)) >= 0)
  79. throw new ArgumentException("Diffie-Hellman public key is weak");
  80. BigInteger result = peerY.ModPow(privateValue, p);
  81. if (result.Equals(BigInteger.One))
  82. throw new InvalidOperationException("Shared key can't be 1");
  83. return message.ModPow(key.X, p).Multiply(result).Mod(p);
  84. }
  85. }
  86. }
  87. #pragma warning restore
  88. #endif