SP800SecureRandomBuilder.cs 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. #pragma warning disable
  3. using System;
  4. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Prng.Drbg;
  5. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Security;
  6. namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Prng
  7. {
  8. /**
  9. * Builder class for making SecureRandom objects based on SP 800-90A Deterministic Random Bit Generators (DRBG).
  10. */
  11. public class SP800SecureRandomBuilder
  12. {
  13. private readonly SecureRandom mRandom;
  14. private readonly IEntropySourceProvider mEntropySourceProvider;
  15. private byte[] mPersonalizationString = null;
  16. private int mSecurityStrength = 256;
  17. private int mEntropyBitsRequired = 256;
  18. /**
  19. * Basic constructor, creates a builder using an EntropySourceProvider based on the default SecureRandom with
  20. * predictionResistant set to false.
  21. * <p>
  22. * Any SecureRandom created from a builder constructed like this will make use of input passed to SecureRandom.setSeed() if
  23. * the default SecureRandom does for its generateSeed() call.
  24. * </p>
  25. */
  26. public SP800SecureRandomBuilder()
  27. : this(CryptoServicesRegistrar.GetSecureRandom(), false)
  28. {
  29. }
  30. /**
  31. * Construct a builder with an EntropySourceProvider based on the passed in SecureRandom and the passed in value
  32. * for prediction resistance.
  33. * <p>
  34. * Any SecureRandom created from a builder constructed like this will make use of input passed to SecureRandom.setSeed() if
  35. * the passed in SecureRandom does for its generateSeed() call.
  36. * </p>
  37. * @param entropySource
  38. * @param predictionResistant
  39. */
  40. public SP800SecureRandomBuilder(SecureRandom entropySource, bool predictionResistant)
  41. {
  42. if (entropySource == null)
  43. throw new ArgumentNullException(nameof(entropySource));
  44. this.mRandom = entropySource;
  45. this.mEntropySourceProvider = new BasicEntropySourceProvider(entropySource, predictionResistant);
  46. }
  47. /**
  48. * Create a builder which makes creates the SecureRandom objects from a specified entropy source provider.
  49. * <p>
  50. * <b>Note:</b> If this constructor is used any calls to setSeed() in the resulting SecureRandom will be ignored.
  51. * </p>
  52. * @param entropySourceProvider a provider of EntropySource objects.
  53. */
  54. public SP800SecureRandomBuilder(IEntropySourceProvider entropySourceProvider)
  55. {
  56. this.mRandom = null;
  57. this.mEntropySourceProvider = entropySourceProvider;
  58. }
  59. /**
  60. * Set the personalization string for DRBG SecureRandoms created by this builder
  61. * @param personalizationString the personalisation string for the underlying DRBG.
  62. * @return the current builder.
  63. */
  64. public SP800SecureRandomBuilder SetPersonalizationString(byte[] personalizationString)
  65. {
  66. this.mPersonalizationString = personalizationString;
  67. return this;
  68. }
  69. /**
  70. * Set the security strength required for DRBGs used in building SecureRandom objects.
  71. *
  72. * @param securityStrength the security strength (in bits)
  73. * @return the current builder.
  74. */
  75. public SP800SecureRandomBuilder SetSecurityStrength(int securityStrength)
  76. {
  77. this.mSecurityStrength = securityStrength;
  78. return this;
  79. }
  80. /**
  81. * Set the amount of entropy bits required for seeding and reseeding DRBGs used in building SecureRandom objects.
  82. *
  83. * @param entropyBitsRequired the number of bits of entropy to be requested from the entropy source on each seed/reseed.
  84. * @return the current builder.
  85. */
  86. public SP800SecureRandomBuilder SetEntropyBitsRequired(int entropyBitsRequired)
  87. {
  88. this.mEntropyBitsRequired = entropyBitsRequired;
  89. return this;
  90. }
  91. /**
  92. * Build a SecureRandom based on a SP 800-90A Hash DRBG.
  93. *
  94. * @param digest digest algorithm to use in the DRBG underneath the SecureRandom.
  95. * @param nonce nonce value to use in DRBG construction.
  96. * @param predictionResistant specify whether the underlying DRBG in the resulting SecureRandom should reseed on each request for bytes.
  97. * @return a SecureRandom supported by a Hash DRBG.
  98. */
  99. public SP800SecureRandom BuildHash(IDigest digest, byte[] nonce, bool predictionResistant)
  100. {
  101. return new SP800SecureRandom(mRandom, mEntropySourceProvider.Get(mEntropyBitsRequired),
  102. new HashDrbgProvider(digest, nonce, mPersonalizationString, mSecurityStrength), predictionResistant);
  103. }
  104. /**
  105. * Build a SecureRandom based on a SP 800-90A CTR DRBG.
  106. *
  107. * @param cipher the block cipher to base the DRBG on.
  108. * @param keySizeInBits key size in bits to be used with the block cipher.
  109. * @param nonce nonce value to use in DRBG construction.
  110. * @param predictionResistant specify whether the underlying DRBG in the resulting SecureRandom should reseed on each request for bytes.
  111. * @return a SecureRandom supported by a CTR DRBG.
  112. */
  113. public SP800SecureRandom BuildCtr(IBlockCipher cipher, int keySizeInBits, byte[] nonce, bool predictionResistant)
  114. {
  115. return new SP800SecureRandom(mRandom, mEntropySourceProvider.Get(mEntropyBitsRequired),
  116. new CtrDrbgProvider(cipher, keySizeInBits, nonce, mPersonalizationString, mSecurityStrength), predictionResistant);
  117. }
  118. /**
  119. * Build a SecureRandom based on a SP 800-90A HMAC DRBG.
  120. *
  121. * @param hMac HMAC algorithm to use in the DRBG underneath the SecureRandom.
  122. * @param nonce nonce value to use in DRBG construction.
  123. * @param predictionResistant specify whether the underlying DRBG in the resulting SecureRandom should reseed on each request for bytes.
  124. * @return a SecureRandom supported by a HMAC DRBG.
  125. */
  126. public SP800SecureRandom BuildHMac(IMac hMac, byte[] nonce, bool predictionResistant)
  127. {
  128. return new SP800SecureRandom(mRandom, mEntropySourceProvider.Get(mEntropyBitsRequired),
  129. new HMacDrbgProvider(hMac, nonce, mPersonalizationString, mSecurityStrength), predictionResistant);
  130. }
  131. private class HashDrbgProvider
  132. : IDrbgProvider
  133. {
  134. private readonly IDigest mDigest;
  135. private readonly byte[] mNonce;
  136. private readonly byte[] mPersonalizationString;
  137. private readonly int mSecurityStrength;
  138. public HashDrbgProvider(IDigest digest, byte[] nonce, byte[] personalizationString, int securityStrength)
  139. {
  140. this.mDigest = digest;
  141. this.mNonce = nonce;
  142. this.mPersonalizationString = personalizationString;
  143. this.mSecurityStrength = securityStrength;
  144. }
  145. public ISP80090Drbg Get(IEntropySource entropySource)
  146. {
  147. return new HashSP800Drbg(mDigest, mSecurityStrength, entropySource, mPersonalizationString, mNonce);
  148. }
  149. }
  150. private class HMacDrbgProvider
  151. : IDrbgProvider
  152. {
  153. private readonly IMac mHMac;
  154. private readonly byte[] mNonce;
  155. private readonly byte[] mPersonalizationString;
  156. private readonly int mSecurityStrength;
  157. public HMacDrbgProvider(IMac hMac, byte[] nonce, byte[] personalizationString, int securityStrength)
  158. {
  159. this.mHMac = hMac;
  160. this.mNonce = nonce;
  161. this.mPersonalizationString = personalizationString;
  162. this.mSecurityStrength = securityStrength;
  163. }
  164. public ISP80090Drbg Get(IEntropySource entropySource)
  165. {
  166. return new HMacSP800Drbg(mHMac, mSecurityStrength, entropySource, mPersonalizationString, mNonce);
  167. }
  168. }
  169. private class CtrDrbgProvider
  170. : IDrbgProvider
  171. {
  172. private readonly IBlockCipher mBlockCipher;
  173. private readonly int mKeySizeInBits;
  174. private readonly byte[] mNonce;
  175. private readonly byte[] mPersonalizationString;
  176. private readonly int mSecurityStrength;
  177. public CtrDrbgProvider(IBlockCipher blockCipher, int keySizeInBits, byte[] nonce, byte[] personalizationString, int securityStrength)
  178. {
  179. this.mBlockCipher = blockCipher;
  180. this.mKeySizeInBits = keySizeInBits;
  181. this.mNonce = nonce;
  182. this.mPersonalizationString = personalizationString;
  183. this.mSecurityStrength = securityStrength;
  184. }
  185. public ISP80090Drbg Get(IEntropySource entropySource)
  186. {
  187. return new CtrSP800Drbg(mBlockCipher, mKeySizeInBits, mSecurityStrength, entropySource, mPersonalizationString, mNonce);
  188. }
  189. }
  190. }
  191. }
  192. #pragma warning restore
  193. #endif