DHAgreement.cs 3.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. #pragma warning disable
  3. using System;
  4. using System.Diagnostics;
  5. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Generators;
  6. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
  7. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Math;
  8. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Security;
  9. namespace Best.HTTP.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(ICipherParameters parameters)
  29. {
  30. AsymmetricKeyParameter kParam;
  31. if (parameters is ParametersWithRandom rParam)
  32. {
  33. this.random = rParam.Random;
  34. kParam = (AsymmetricKeyParameter)rParam.Parameters;
  35. }
  36. else
  37. {
  38. this.random = CryptoServicesRegistrar.GetSecureRandom();
  39. kParam = (AsymmetricKeyParameter)parameters;
  40. }
  41. if (!(kParam is DHPrivateKeyParameters dhPrivateKeyParameters))
  42. throw new ArgumentException("DHEngine expects DHPrivateKeyParameters");
  43. this.key = dhPrivateKeyParameters;
  44. this.dhParams = dhPrivateKeyParameters.Parameters;
  45. }
  46. /**
  47. * calculate our initial message.
  48. */
  49. public BigInteger CalculateMessage()
  50. {
  51. DHKeyPairGenerator dhGen = new DHKeyPairGenerator();
  52. dhGen.Init(new DHKeyGenerationParameters(random, dhParams));
  53. AsymmetricCipherKeyPair dhPair = dhGen.GenerateKeyPair();
  54. this.privateValue = ((DHPrivateKeyParameters)dhPair.Private).X;
  55. return ((DHPublicKeyParameters)dhPair.Public).Y;
  56. }
  57. /**
  58. * given a message from a given party and the corresponding public key
  59. * calculate the next message in the agreement sequence. In this case
  60. * this will represent the shared secret.
  61. */
  62. public BigInteger CalculateAgreement(
  63. DHPublicKeyParameters pub,
  64. BigInteger message)
  65. {
  66. if (pub == null)
  67. throw new ArgumentNullException("pub");
  68. if (message == null)
  69. throw new ArgumentNullException("message");
  70. if (!pub.Parameters.Equals(dhParams))
  71. throw new ArgumentException("Diffie-Hellman public key has wrong parameters.");
  72. BigInteger p = dhParams.P;
  73. BigInteger peerY = pub.Y;
  74. if (peerY == null || peerY.CompareTo(BigInteger.One) <= 0 || peerY.CompareTo(p.Subtract(BigInteger.One)) >= 0)
  75. throw new ArgumentException("Diffie-Hellman public key is weak");
  76. BigInteger result = peerY.ModPow(privateValue, p);
  77. if (result.Equals(BigInteger.One))
  78. throw new InvalidOperationException("Shared key can't be 1");
  79. return message.ModPow(key.X, p).Multiply(result).Mod(p);
  80. }
  81. }
  82. }
  83. #pragma warning restore
  84. #endif