add all
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Security;
|
||||
|
||||
namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Prng
|
||||
{
|
||||
/**
|
||||
* An EntropySourceProvider where entropy generation is based on a SecureRandom output using SecureRandom.generateSeed().
|
||||
*/
|
||||
public class BasicEntropySourceProvider
|
||||
: IEntropySourceProvider
|
||||
{
|
||||
private readonly SecureRandom mSecureRandom;
|
||||
private readonly bool mPredictionResistant;
|
||||
|
||||
/**
|
||||
* Create a entropy source provider based on the passed in SecureRandom.
|
||||
*
|
||||
* @param secureRandom the SecureRandom to base EntropySource construction on.
|
||||
* @param isPredictionResistant boolean indicating if the SecureRandom is based on prediction resistant entropy or not (true if it is).
|
||||
*/
|
||||
public BasicEntropySourceProvider(SecureRandom secureRandom, bool isPredictionResistant)
|
||||
{
|
||||
if (secureRandom == null)
|
||||
throw new ArgumentNullException(nameof(secureRandom));
|
||||
|
||||
mSecureRandom = secureRandom;
|
||||
mPredictionResistant = isPredictionResistant;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an entropy source that will create bitsRequired bits of entropy on
|
||||
* each invocation of getEntropy().
|
||||
*
|
||||
* @param bitsRequired size (in bits) of entropy to be created by the provided source.
|
||||
* @return an EntropySource that generates bitsRequired bits of entropy on each call to its getEntropy() method.
|
||||
*/
|
||||
public IEntropySource Get(int bitsRequired)
|
||||
{
|
||||
return new BasicEntropySource(mSecureRandom, mPredictionResistant, bitsRequired);
|
||||
}
|
||||
|
||||
private class BasicEntropySource
|
||||
: IEntropySource
|
||||
{
|
||||
private readonly SecureRandom mSecureRandom;
|
||||
private readonly bool mPredictionResistant;
|
||||
private readonly int mEntropySize;
|
||||
|
||||
internal BasicEntropySource(SecureRandom secureRandom, bool predictionResistant, int entropySize)
|
||||
{
|
||||
if (secureRandom == null)
|
||||
throw new ArgumentNullException(nameof(secureRandom));
|
||||
|
||||
this.mSecureRandom = secureRandom;
|
||||
this.mPredictionResistant = predictionResistant;
|
||||
this.mEntropySize = entropySize;
|
||||
}
|
||||
|
||||
bool IEntropySource.IsPredictionResistant
|
||||
{
|
||||
get { return mPredictionResistant; }
|
||||
}
|
||||
|
||||
byte[] IEntropySource.GetEntropy()
|
||||
{
|
||||
// TODO[FIPS] Not all SecureRandom implementations are considered valid entropy sources
|
||||
return SecureRandom.GetNextBytes(mSecureRandom, (mEntropySize + 7) / 8);
|
||||
}
|
||||
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
int IEntropySource.GetEntropy(Span<byte> output)
|
||||
{
|
||||
int length = (mEntropySize + 7) / 8;
|
||||
mSecureRandom.NextBytes(output[..length]);
|
||||
return length;
|
||||
}
|
||||
#endif
|
||||
|
||||
int IEntropySource.EntropySize
|
||||
{
|
||||
get { return mEntropySize; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cb455ad34ed0d474d845cc23f0a2fbf0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,80 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Prng
|
||||
{
|
||||
public class CryptoApiEntropySourceProvider
|
||||
: IEntropySourceProvider
|
||||
{
|
||||
private readonly RandomNumberGenerator mRng;
|
||||
private readonly bool mPredictionResistant;
|
||||
|
||||
public CryptoApiEntropySourceProvider()
|
||||
: this(RandomNumberGenerator.Create(), true)
|
||||
{
|
||||
}
|
||||
|
||||
public CryptoApiEntropySourceProvider(RandomNumberGenerator rng, bool isPredictionResistant)
|
||||
{
|
||||
if (rng == null)
|
||||
throw new ArgumentNullException("rng");
|
||||
|
||||
mRng = rng;
|
||||
mPredictionResistant = isPredictionResistant;
|
||||
}
|
||||
|
||||
public IEntropySource Get(int bitsRequired)
|
||||
{
|
||||
return new CryptoApiEntropySource(mRng, mPredictionResistant, bitsRequired);
|
||||
}
|
||||
|
||||
private class CryptoApiEntropySource
|
||||
: IEntropySource
|
||||
{
|
||||
private readonly RandomNumberGenerator mRng;
|
||||
private readonly bool mPredictionResistant;
|
||||
private readonly int mEntropySize;
|
||||
|
||||
internal CryptoApiEntropySource(RandomNumberGenerator rng, bool predictionResistant, int entropySize)
|
||||
{
|
||||
this.mRng = rng;
|
||||
this.mPredictionResistant = predictionResistant;
|
||||
this.mEntropySize = entropySize;
|
||||
}
|
||||
|
||||
#region IEntropySource Members
|
||||
|
||||
bool IEntropySource.IsPredictionResistant
|
||||
{
|
||||
get { return mPredictionResistant; }
|
||||
}
|
||||
|
||||
byte[] IEntropySource.GetEntropy()
|
||||
{
|
||||
byte[] result = new byte[(mEntropySize + 7) / 8];
|
||||
mRng.GetBytes(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
int IEntropySource.GetEntropy(Span<byte> output)
|
||||
{
|
||||
int length = (mEntropySize + 7) / 8;
|
||||
mRng.GetBytes(output[..length]);
|
||||
return length;
|
||||
}
|
||||
#endif
|
||||
|
||||
int IEntropySource.EntropySize
|
||||
{
|
||||
get { return mEntropySize; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 98f1d87eb3d920a43b46bc92a02aa02e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,94 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Prng
|
||||
{
|
||||
/// <summary>
|
||||
/// Uses RandomNumberGenerator.Create() to get randomness generator
|
||||
/// </summary>
|
||||
public sealed class CryptoApiRandomGenerator
|
||||
: IRandomGenerator, IDisposable
|
||||
{
|
||||
private readonly RandomNumberGenerator m_randomNumberGenerator;
|
||||
|
||||
public CryptoApiRandomGenerator()
|
||||
: this(RandomNumberGenerator.Create())
|
||||
{
|
||||
}
|
||||
|
||||
public CryptoApiRandomGenerator(RandomNumberGenerator randomNumberGenerator)
|
||||
{
|
||||
m_randomNumberGenerator = randomNumberGenerator ??
|
||||
throw new ArgumentNullException(nameof(randomNumberGenerator));
|
||||
}
|
||||
|
||||
#region IRandomGenerator Members
|
||||
|
||||
public void AddSeedMaterial(byte[] seed)
|
||||
{
|
||||
// We don't care about the seed
|
||||
}
|
||||
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
public void AddSeedMaterial(ReadOnlySpan<byte> inSeed)
|
||||
{
|
||||
// We don't care about the seed
|
||||
}
|
||||
#endif
|
||||
|
||||
public void AddSeedMaterial(long seed)
|
||||
{
|
||||
// We don't care about the seed
|
||||
}
|
||||
|
||||
public void NextBytes(byte[] bytes)
|
||||
{
|
||||
m_randomNumberGenerator.GetBytes(bytes);
|
||||
}
|
||||
|
||||
public void NextBytes(byte[] bytes, int start, int len)
|
||||
{
|
||||
#if NETCOREAPP2_0_OR_GREATER || NETSTANDARD2_0_OR_GREATER
|
||||
m_randomNumberGenerator.GetBytes(bytes, start, len);
|
||||
#else
|
||||
if (start < 0)
|
||||
throw new ArgumentException("Start offset cannot be negative", "start");
|
||||
if (bytes.Length < (start + len))
|
||||
throw new ArgumentException("Byte array too small for requested offset and length");
|
||||
|
||||
if (bytes.Length == len && start == 0)
|
||||
{
|
||||
NextBytes(bytes);
|
||||
}
|
||||
else
|
||||
{
|
||||
byte[] tmpBuf = new byte[len];
|
||||
NextBytes(tmpBuf);
|
||||
Array.Copy(tmpBuf, 0, bytes, start, len);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
public void NextBytes(Span<byte> bytes)
|
||||
{
|
||||
m_randomNumberGenerator.GetBytes(bytes);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endregion
|
||||
|
||||
#region IDisposable Members
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
m_randomNumberGenerator.Dispose();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f3caaf979811f624b974ab1d665a661e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
187
Packages/com.tivadar.best.http/Runtime/3rdParty/BouncyCastle/crypto/prng/DigestRandomGenerator.cs
vendored
Normal file
187
Packages/com.tivadar.best.http/Runtime/3rdParty/BouncyCastle/crypto/prng/DigestRandomGenerator.cs
vendored
Normal file
@@ -0,0 +1,187 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Utilities;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Utilities;
|
||||
|
||||
namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Prng
|
||||
{
|
||||
/**
|
||||
* Random generation based on the digest with counter. Calling AddSeedMaterial will
|
||||
* always increase the entropy of the hash.
|
||||
* <p>
|
||||
* Internal access to the digest is synchronized so a single one of these can be shared.
|
||||
* </p>
|
||||
*/
|
||||
public sealed class DigestRandomGenerator
|
||||
: IRandomGenerator
|
||||
{
|
||||
private const long CYCLE_COUNT = 10;
|
||||
|
||||
private long stateCounter;
|
||||
private long seedCounter;
|
||||
private IDigest digest;
|
||||
private byte[] state;
|
||||
private byte[] seed;
|
||||
|
||||
public DigestRandomGenerator(IDigest digest)
|
||||
{
|
||||
this.digest = digest;
|
||||
|
||||
this.seed = new byte[digest.GetDigestSize()];
|
||||
this.seedCounter = 1;
|
||||
|
||||
this.state = new byte[digest.GetDigestSize()];
|
||||
this.stateCounter = 1;
|
||||
}
|
||||
|
||||
public void AddSeedMaterial(byte[] inSeed)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
if (!Arrays.IsNullOrEmpty(inSeed))
|
||||
{
|
||||
DigestUpdate(inSeed);
|
||||
}
|
||||
DigestUpdate(seed);
|
||||
DigestDoFinal(seed);
|
||||
}
|
||||
}
|
||||
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
public void AddSeedMaterial(ReadOnlySpan<byte> inSeed)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
if (!inSeed.IsEmpty)
|
||||
{
|
||||
DigestUpdate(inSeed);
|
||||
}
|
||||
DigestUpdate(seed);
|
||||
DigestDoFinal(seed);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
public void AddSeedMaterial(long rSeed)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
DigestAddCounter(rSeed);
|
||||
DigestUpdate(seed);
|
||||
DigestDoFinal(seed);
|
||||
}
|
||||
}
|
||||
|
||||
public void NextBytes(byte[] bytes)
|
||||
{
|
||||
NextBytes(bytes, 0, bytes.Length);
|
||||
}
|
||||
|
||||
public void NextBytes(byte[] bytes, int start, int len)
|
||||
{
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
NextBytes(bytes.AsSpan(start, len));
|
||||
#else
|
||||
lock (this)
|
||||
{
|
||||
int stateOff = 0;
|
||||
|
||||
GenerateState();
|
||||
|
||||
int end = start + len;
|
||||
for (int i = start; i < end; ++i)
|
||||
{
|
||||
if (stateOff == state.Length)
|
||||
{
|
||||
GenerateState();
|
||||
stateOff = 0;
|
||||
}
|
||||
bytes[i] = state[stateOff++];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
public void NextBytes(Span<byte> bytes)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
int stateOff = 0;
|
||||
|
||||
GenerateState();
|
||||
|
||||
for (int i = 0; i < bytes.Length; ++i)
|
||||
{
|
||||
if (stateOff == state.Length)
|
||||
{
|
||||
GenerateState();
|
||||
stateOff = 0;
|
||||
}
|
||||
bytes[i] = state[stateOff++];
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
private void CycleSeed()
|
||||
{
|
||||
DigestUpdate(seed);
|
||||
DigestAddCounter(seedCounter++);
|
||||
DigestDoFinal(seed);
|
||||
}
|
||||
|
||||
private void GenerateState()
|
||||
{
|
||||
DigestAddCounter(stateCounter++);
|
||||
DigestUpdate(state);
|
||||
DigestUpdate(seed);
|
||||
DigestDoFinal(state);
|
||||
|
||||
if ((stateCounter % CYCLE_COUNT) == 0)
|
||||
{
|
||||
CycleSeed();
|
||||
}
|
||||
}
|
||||
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
private void DigestAddCounter(long seedVal)
|
||||
{
|
||||
Span<byte> bytes = stackalloc byte[8];
|
||||
Pack.UInt64_To_LE((ulong)seedVal, bytes);
|
||||
digest.BlockUpdate(bytes);
|
||||
}
|
||||
|
||||
private void DigestUpdate(ReadOnlySpan<byte> inSeed)
|
||||
{
|
||||
digest.BlockUpdate(inSeed);
|
||||
}
|
||||
|
||||
private void DigestDoFinal(Span<byte> result)
|
||||
{
|
||||
digest.DoFinal(result);
|
||||
}
|
||||
#else
|
||||
private void DigestAddCounter(long seedVal)
|
||||
{
|
||||
byte[] bytes = new byte[8];
|
||||
Pack.UInt64_To_LE((ulong)seedVal, bytes);
|
||||
digest.BlockUpdate(bytes, 0, bytes.Length);
|
||||
}
|
||||
|
||||
private void DigestUpdate(byte[] inSeed)
|
||||
{
|
||||
digest.BlockUpdate(inSeed, 0, inSeed.Length);
|
||||
}
|
||||
|
||||
private void DigestDoFinal(byte[] result)
|
||||
{
|
||||
digest.DoFinal(result, 0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7816f1b03e8a4154085c3dd6c3ee115f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
34
Packages/com.tivadar.best.http/Runtime/3rdParty/BouncyCastle/crypto/prng/EntropyUtilities.cs
vendored
Normal file
34
Packages/com.tivadar.best.http/Runtime/3rdParty/BouncyCastle/crypto/prng/EntropyUtilities.cs
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Security;
|
||||
|
||||
namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Prng
|
||||
{
|
||||
public abstract class EntropyUtilities
|
||||
{
|
||||
/**
|
||||
* Generate numBytes worth of entropy from the passed in entropy source.
|
||||
*
|
||||
* @param entropySource the entropy source to request the data from.
|
||||
* @param numBytes the number of bytes of entropy requested.
|
||||
* @return a byte array populated with the random data.
|
||||
*/
|
||||
public static byte[] GenerateSeed(IEntropySource entropySource, int numBytes)
|
||||
{
|
||||
byte[] bytes = new byte[numBytes];
|
||||
int count = 0;
|
||||
while (count < numBytes)
|
||||
{
|
||||
byte[] entropy = entropySource.GetEntropy();
|
||||
int toCopy = System.Math.Min(bytes.Length, numBytes - count);
|
||||
Array.Copy(entropy, 0, bytes, count, toCopy);
|
||||
count += toCopy;
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b9987c57d8739434c94cec3a72c2e62f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
15
Packages/com.tivadar.best.http/Runtime/3rdParty/BouncyCastle/crypto/prng/IDrbgProvider.cs
vendored
Normal file
15
Packages/com.tivadar.best.http/Runtime/3rdParty/BouncyCastle/crypto/prng/IDrbgProvider.cs
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Prng.Drbg;
|
||||
|
||||
namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Prng
|
||||
{
|
||||
internal interface IDrbgProvider
|
||||
{
|
||||
ISP80090Drbg Get(IEntropySource entropySource);
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
11
Packages/com.tivadar.best.http/Runtime/3rdParty/BouncyCastle/crypto/prng/IDrbgProvider.cs.meta
vendored
Normal file
11
Packages/com.tivadar.best.http/Runtime/3rdParty/BouncyCastle/crypto/prng/IDrbgProvider.cs.meta
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e23783c6ef2676c468b3c5ae42a5f29e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
38
Packages/com.tivadar.best.http/Runtime/3rdParty/BouncyCastle/crypto/prng/IRandomGenerator.cs
vendored
Normal file
38
Packages/com.tivadar.best.http/Runtime/3rdParty/BouncyCastle/crypto/prng/IRandomGenerator.cs
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
|
||||
namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Prng
|
||||
{
|
||||
/// <remarks>Generic interface for objects generating random bytes.</remarks>
|
||||
public interface IRandomGenerator
|
||||
{
|
||||
/// <summary>Add more seed material to the generator.</summary>
|
||||
/// <param name="seed">A byte array to be mixed into the generator's state.</param>
|
||||
void AddSeedMaterial(byte[] seed);
|
||||
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
void AddSeedMaterial(ReadOnlySpan<byte> seed);
|
||||
#endif
|
||||
|
||||
/// <summary>Add more seed material to the generator.</summary>
|
||||
/// <param name="seed">A long value to be mixed into the generator's state.</param>
|
||||
void AddSeedMaterial(long seed);
|
||||
|
||||
/// <summary>Fill byte array with random values.</summary>
|
||||
/// <param name="bytes">Array to be filled.</param>
|
||||
void NextBytes(byte[] bytes);
|
||||
|
||||
/// <summary>Fill byte array with random values.</summary>
|
||||
/// <param name="bytes">Array to receive bytes.</param>
|
||||
/// <param name="start">Index to start filling at.</param>
|
||||
/// <param name="len">Length of segment to fill.</param>
|
||||
void NextBytes(byte[] bytes, int start, int len);
|
||||
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
void NextBytes(Span<byte> bytes);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1501d9a297438c547ac3f782a85f3796
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,2 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7ff89dbb06ce62b4f94d8f8556629e2b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
135
Packages/com.tivadar.best.http/Runtime/3rdParty/BouncyCastle/crypto/prng/SP800SecureRandom.cs
vendored
Normal file
135
Packages/com.tivadar.best.http/Runtime/3rdParty/BouncyCastle/crypto/prng/SP800SecureRandom.cs
vendored
Normal file
@@ -0,0 +1,135 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Prng.Drbg;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Security;
|
||||
|
||||
namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Prng
|
||||
{
|
||||
public class SP800SecureRandom
|
||||
: SecureRandom
|
||||
{
|
||||
private readonly IDrbgProvider mDrbgProvider;
|
||||
private readonly bool mPredictionResistant;
|
||||
private readonly SecureRandom mRandomSource;
|
||||
private readonly IEntropySource mEntropySource;
|
||||
|
||||
private ISP80090Drbg mDrbg;
|
||||
|
||||
internal SP800SecureRandom(SecureRandom randomSource, IEntropySource entropySource, IDrbgProvider drbgProvider,
|
||||
bool predictionResistant)
|
||||
: base(null)
|
||||
{
|
||||
this.mRandomSource = randomSource;
|
||||
this.mEntropySource = entropySource;
|
||||
this.mDrbgProvider = drbgProvider;
|
||||
this.mPredictionResistant = predictionResistant;
|
||||
}
|
||||
|
||||
public override void SetSeed(byte[] seed)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
if (mRandomSource != null)
|
||||
{
|
||||
this.mRandomSource.SetSeed(seed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
public override void SetSeed(Span<byte> seed)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
if (mRandomSource != null)
|
||||
{
|
||||
this.mRandomSource.SetSeed(seed);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
public override void SetSeed(long seed)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
// this will happen when SecureRandom() is created
|
||||
if (mRandomSource != null)
|
||||
{
|
||||
this.mRandomSource.SetSeed(seed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void NextBytes(byte[] bytes)
|
||||
{
|
||||
NextBytes(bytes, 0, bytes.Length);
|
||||
}
|
||||
|
||||
public override void NextBytes(byte[] buf, int off, int len)
|
||||
{
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
NextBytes(buf.AsSpan(off, len));
|
||||
#else
|
||||
lock (this)
|
||||
{
|
||||
if (mDrbg == null)
|
||||
{
|
||||
mDrbg = mDrbgProvider.Get(mEntropySource);
|
||||
}
|
||||
|
||||
// check if a reseed is required...
|
||||
if (mDrbg.Generate(buf, off, len, null, mPredictionResistant) < 0)
|
||||
{
|
||||
mDrbg.Reseed(null);
|
||||
mDrbg.Generate(buf, off, len, null, mPredictionResistant);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
public override void NextBytes(Span<byte> buffer)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
if (mDrbg == null)
|
||||
{
|
||||
mDrbg = mDrbgProvider.Get(mEntropySource);
|
||||
}
|
||||
|
||||
// check if a reseed is required...
|
||||
if (mDrbg.Generate(buffer, mPredictionResistant) < 0)
|
||||
{
|
||||
mDrbg.Reseed(ReadOnlySpan<byte>.Empty);
|
||||
mDrbg.Generate(buffer, mPredictionResistant);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
public override byte[] GenerateSeed(int numBytes)
|
||||
{
|
||||
return EntropyUtilities.GenerateSeed(mEntropySource, numBytes);
|
||||
}
|
||||
|
||||
/// <summary>Force a reseed of the DRBG.</summary>
|
||||
/// <param name="additionalInput">optional additional input</param>
|
||||
public virtual void Reseed(byte[] additionalInput)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
if (mDrbg == null)
|
||||
{
|
||||
mDrbg = mDrbgProvider.Get(mEntropySource);
|
||||
}
|
||||
|
||||
mDrbg.Reseed(additionalInput);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2af845dab91a6114b94dcf61aafb387c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
215
Packages/com.tivadar.best.http/Runtime/3rdParty/BouncyCastle/crypto/prng/SP800SecureRandomBuilder.cs
vendored
Normal file
215
Packages/com.tivadar.best.http/Runtime/3rdParty/BouncyCastle/crypto/prng/SP800SecureRandomBuilder.cs
vendored
Normal file
@@ -0,0 +1,215 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Prng.Drbg;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Security;
|
||||
|
||||
namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Prng
|
||||
{
|
||||
/**
|
||||
* Builder class for making SecureRandom objects based on SP 800-90A Deterministic Random Bit Generators (DRBG).
|
||||
*/
|
||||
public class SP800SecureRandomBuilder
|
||||
{
|
||||
private readonly SecureRandom mRandom;
|
||||
private readonly IEntropySourceProvider mEntropySourceProvider;
|
||||
|
||||
private byte[] mPersonalizationString = null;
|
||||
private int mSecurityStrength = 256;
|
||||
private int mEntropyBitsRequired = 256;
|
||||
|
||||
/**
|
||||
* Basic constructor, creates a builder using an EntropySourceProvider based on the default SecureRandom with
|
||||
* predictionResistant set to false.
|
||||
* <p>
|
||||
* Any SecureRandom created from a builder constructed like this will make use of input passed to SecureRandom.setSeed() if
|
||||
* the default SecureRandom does for its generateSeed() call.
|
||||
* </p>
|
||||
*/
|
||||
public SP800SecureRandomBuilder()
|
||||
: this(CryptoServicesRegistrar.GetSecureRandom(), false)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a builder with an EntropySourceProvider based on the passed in SecureRandom and the passed in value
|
||||
* for prediction resistance.
|
||||
* <p>
|
||||
* Any SecureRandom created from a builder constructed like this will make use of input passed to SecureRandom.setSeed() if
|
||||
* the passed in SecureRandom does for its generateSeed() call.
|
||||
* </p>
|
||||
* @param entropySource
|
||||
* @param predictionResistant
|
||||
*/
|
||||
public SP800SecureRandomBuilder(SecureRandom entropySource, bool predictionResistant)
|
||||
{
|
||||
if (entropySource == null)
|
||||
throw new ArgumentNullException(nameof(entropySource));
|
||||
|
||||
this.mRandom = entropySource;
|
||||
this.mEntropySourceProvider = new BasicEntropySourceProvider(entropySource, predictionResistant);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a builder which makes creates the SecureRandom objects from a specified entropy source provider.
|
||||
* <p>
|
||||
* <b>Note:</b> If this constructor is used any calls to setSeed() in the resulting SecureRandom will be ignored.
|
||||
* </p>
|
||||
* @param entropySourceProvider a provider of EntropySource objects.
|
||||
*/
|
||||
public SP800SecureRandomBuilder(IEntropySourceProvider entropySourceProvider)
|
||||
{
|
||||
this.mRandom = null;
|
||||
this.mEntropySourceProvider = entropySourceProvider;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the personalization string for DRBG SecureRandoms created by this builder
|
||||
* @param personalizationString the personalisation string for the underlying DRBG.
|
||||
* @return the current builder.
|
||||
*/
|
||||
public SP800SecureRandomBuilder SetPersonalizationString(byte[] personalizationString)
|
||||
{
|
||||
this.mPersonalizationString = personalizationString;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the security strength required for DRBGs used in building SecureRandom objects.
|
||||
*
|
||||
* @param securityStrength the security strength (in bits)
|
||||
* @return the current builder.
|
||||
*/
|
||||
public SP800SecureRandomBuilder SetSecurityStrength(int securityStrength)
|
||||
{
|
||||
this.mSecurityStrength = securityStrength;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the amount of entropy bits required for seeding and reseeding DRBGs used in building SecureRandom objects.
|
||||
*
|
||||
* @param entropyBitsRequired the number of bits of entropy to be requested from the entropy source on each seed/reseed.
|
||||
* @return the current builder.
|
||||
*/
|
||||
public SP800SecureRandomBuilder SetEntropyBitsRequired(int entropyBitsRequired)
|
||||
{
|
||||
this.mEntropyBitsRequired = entropyBitsRequired;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a SecureRandom based on a SP 800-90A Hash DRBG.
|
||||
*
|
||||
* @param digest digest algorithm to use in the DRBG underneath the SecureRandom.
|
||||
* @param nonce nonce value to use in DRBG construction.
|
||||
* @param predictionResistant specify whether the underlying DRBG in the resulting SecureRandom should reseed on each request for bytes.
|
||||
* @return a SecureRandom supported by a Hash DRBG.
|
||||
*/
|
||||
public SP800SecureRandom BuildHash(IDigest digest, byte[] nonce, bool predictionResistant)
|
||||
{
|
||||
return new SP800SecureRandom(mRandom, mEntropySourceProvider.Get(mEntropyBitsRequired),
|
||||
new HashDrbgProvider(digest, nonce, mPersonalizationString, mSecurityStrength), predictionResistant);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a SecureRandom based on a SP 800-90A CTR DRBG.
|
||||
*
|
||||
* @param cipher the block cipher to base the DRBG on.
|
||||
* @param keySizeInBits key size in bits to be used with the block cipher.
|
||||
* @param nonce nonce value to use in DRBG construction.
|
||||
* @param predictionResistant specify whether the underlying DRBG in the resulting SecureRandom should reseed on each request for bytes.
|
||||
* @return a SecureRandom supported by a CTR DRBG.
|
||||
*/
|
||||
public SP800SecureRandom BuildCtr(IBlockCipher cipher, int keySizeInBits, byte[] nonce, bool predictionResistant)
|
||||
{
|
||||
return new SP800SecureRandom(mRandom, mEntropySourceProvider.Get(mEntropyBitsRequired),
|
||||
new CtrDrbgProvider(cipher, keySizeInBits, nonce, mPersonalizationString, mSecurityStrength), predictionResistant);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a SecureRandom based on a SP 800-90A HMAC DRBG.
|
||||
*
|
||||
* @param hMac HMAC algorithm to use in the DRBG underneath the SecureRandom.
|
||||
* @param nonce nonce value to use in DRBG construction.
|
||||
* @param predictionResistant specify whether the underlying DRBG in the resulting SecureRandom should reseed on each request for bytes.
|
||||
* @return a SecureRandom supported by a HMAC DRBG.
|
||||
*/
|
||||
public SP800SecureRandom BuildHMac(IMac hMac, byte[] nonce, bool predictionResistant)
|
||||
{
|
||||
return new SP800SecureRandom(mRandom, mEntropySourceProvider.Get(mEntropyBitsRequired),
|
||||
new HMacDrbgProvider(hMac, nonce, mPersonalizationString, mSecurityStrength), predictionResistant);
|
||||
}
|
||||
|
||||
private class HashDrbgProvider
|
||||
: IDrbgProvider
|
||||
{
|
||||
private readonly IDigest mDigest;
|
||||
private readonly byte[] mNonce;
|
||||
private readonly byte[] mPersonalizationString;
|
||||
private readonly int mSecurityStrength;
|
||||
|
||||
public HashDrbgProvider(IDigest digest, byte[] nonce, byte[] personalizationString, int securityStrength)
|
||||
{
|
||||
this.mDigest = digest;
|
||||
this.mNonce = nonce;
|
||||
this.mPersonalizationString = personalizationString;
|
||||
this.mSecurityStrength = securityStrength;
|
||||
}
|
||||
|
||||
public ISP80090Drbg Get(IEntropySource entropySource)
|
||||
{
|
||||
return new HashSP800Drbg(mDigest, mSecurityStrength, entropySource, mPersonalizationString, mNonce);
|
||||
}
|
||||
}
|
||||
|
||||
private class HMacDrbgProvider
|
||||
: IDrbgProvider
|
||||
{
|
||||
private readonly IMac mHMac;
|
||||
private readonly byte[] mNonce;
|
||||
private readonly byte[] mPersonalizationString;
|
||||
private readonly int mSecurityStrength;
|
||||
|
||||
public HMacDrbgProvider(IMac hMac, byte[] nonce, byte[] personalizationString, int securityStrength)
|
||||
{
|
||||
this.mHMac = hMac;
|
||||
this.mNonce = nonce;
|
||||
this.mPersonalizationString = personalizationString;
|
||||
this.mSecurityStrength = securityStrength;
|
||||
}
|
||||
|
||||
public ISP80090Drbg Get(IEntropySource entropySource)
|
||||
{
|
||||
return new HMacSP800Drbg(mHMac, mSecurityStrength, entropySource, mPersonalizationString, mNonce);
|
||||
}
|
||||
}
|
||||
|
||||
private class CtrDrbgProvider
|
||||
: IDrbgProvider
|
||||
{
|
||||
private readonly IBlockCipher mBlockCipher;
|
||||
private readonly int mKeySizeInBits;
|
||||
private readonly byte[] mNonce;
|
||||
private readonly byte[] mPersonalizationString;
|
||||
private readonly int mSecurityStrength;
|
||||
|
||||
public CtrDrbgProvider(IBlockCipher blockCipher, int keySizeInBits, byte[] nonce, byte[] personalizationString, int securityStrength)
|
||||
{
|
||||
this.mBlockCipher = blockCipher;
|
||||
this.mKeySizeInBits = keySizeInBits;
|
||||
this.mNonce = nonce;
|
||||
this.mPersonalizationString = personalizationString;
|
||||
this.mSecurityStrength = securityStrength;
|
||||
}
|
||||
|
||||
public ISP80090Drbg Get(IEntropySource entropySource)
|
||||
{
|
||||
return new CtrSP800Drbg(mBlockCipher, mKeySizeInBits, mSecurityStrength, entropySource, mPersonalizationString, mNonce);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c68208041500178428c38d37e6d6b3e4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
144
Packages/com.tivadar.best.http/Runtime/3rdParty/BouncyCastle/crypto/prng/VMPCRandomGenerator.cs
vendored
Normal file
144
Packages/com.tivadar.best.http/Runtime/3rdParty/BouncyCastle/crypto/prng/VMPCRandomGenerator.cs
vendored
Normal file
@@ -0,0 +1,144 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Utilities;
|
||||
|
||||
namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Prng
|
||||
{
|
||||
public sealed class VmpcRandomGenerator
|
||||
: IRandomGenerator
|
||||
{
|
||||
/// <remarks>
|
||||
/// Permutation generated by code:
|
||||
/// <code>
|
||||
/// // First 1850 fractional digit of Pi number.
|
||||
/// byte[] key = new BigInteger("14159265358979323846...5068006422512520511").ToByteArray();
|
||||
/// s = 0;
|
||||
/// P = new byte[256];
|
||||
/// for (int i = 0; i < 256; i++)
|
||||
/// {
|
||||
/// P[i] = (byte) i;
|
||||
/// }
|
||||
/// for (int m = 0; m < 768; m++)
|
||||
/// {
|
||||
/// s = P[(s + P[m & 0xff] + key[m % key.length]) & 0xff];
|
||||
/// byte temp = P[m & 0xff];
|
||||
/// P[m & 0xff] = P[s & 0xff];
|
||||
/// P[s & 0xff] = temp;
|
||||
/// } </code>
|
||||
/// </remarks>
|
||||
private readonly byte[] P =
|
||||
{
|
||||
0xbb, 0x2c, 0x62, 0x7f, 0xb5, 0xaa, 0xd4, 0x0d, 0x81, 0xfe, 0xb2, 0x82, 0xcb, 0xa0, 0xa1, 0x08,
|
||||
0x18, 0x71, 0x56, 0xe8, 0x49, 0x02, 0x10, 0xc4, 0xde, 0x35, 0xa5, 0xec, 0x80, 0x12, 0xb8, 0x69,
|
||||
0xda, 0x2f, 0x75, 0xcc, 0xa2, 0x09, 0x36, 0x03, 0x61, 0x2d, 0xfd, 0xe0, 0xdd, 0x05, 0x43, 0x90,
|
||||
0xad, 0xc8, 0xe1, 0xaf, 0x57, 0x9b, 0x4c, 0xd8, 0x51, 0xae, 0x50, 0x85, 0x3c, 0x0a, 0xe4, 0xf3,
|
||||
0x9c, 0x26, 0x23, 0x53, 0xc9, 0x83, 0x97, 0x46, 0xb1, 0x99, 0x64, 0x31, 0x77, 0xd5, 0x1d, 0xd6,
|
||||
0x78, 0xbd, 0x5e, 0xb0, 0x8a, 0x22, 0x38, 0xf8, 0x68, 0x2b, 0x2a, 0xc5, 0xd3, 0xf7, 0xbc, 0x6f,
|
||||
0xdf, 0x04, 0xe5, 0x95, 0x3e, 0x25, 0x86, 0xa6, 0x0b, 0x8f, 0xf1, 0x24, 0x0e, 0xd7, 0x40, 0xb3,
|
||||
0xcf, 0x7e, 0x06, 0x15, 0x9a, 0x4d, 0x1c, 0xa3, 0xdb, 0x32, 0x92, 0x58, 0x11, 0x27, 0xf4, 0x59,
|
||||
0xd0, 0x4e, 0x6a, 0x17, 0x5b, 0xac, 0xff, 0x07, 0xc0, 0x65, 0x79, 0xfc, 0xc7, 0xcd, 0x76, 0x42,
|
||||
0x5d, 0xe7, 0x3a, 0x34, 0x7a, 0x30, 0x28, 0x0f, 0x73, 0x01, 0xf9, 0xd1, 0xd2, 0x19, 0xe9, 0x91,
|
||||
0xb9, 0x5a, 0xed, 0x41, 0x6d, 0xb4, 0xc3, 0x9e, 0xbf, 0x63, 0xfa, 0x1f, 0x33, 0x60, 0x47, 0x89,
|
||||
0xf0, 0x96, 0x1a, 0x5f, 0x93, 0x3d, 0x37, 0x4b, 0xd9, 0xa8, 0xc1, 0x1b, 0xf6, 0x39, 0x8b, 0xb7,
|
||||
0x0c, 0x20, 0xce, 0x88, 0x6e, 0xb6, 0x74, 0x8e, 0x8d, 0x16, 0x29, 0xf2, 0x87, 0xf5, 0xeb, 0x70,
|
||||
0xe3, 0xfb, 0x55, 0x9f, 0xc6, 0x44, 0x4a, 0x45, 0x7d, 0xe2, 0x6b, 0x5c, 0x6c, 0x66, 0xa9, 0x8c,
|
||||
0xee, 0x84, 0x13, 0xa7, 0x1e, 0x9d, 0xdc, 0x67, 0x48, 0xba, 0x2e, 0xe6, 0xa4, 0xab, 0x7c, 0x94,
|
||||
0x00, 0x21, 0xef, 0xea, 0xbe, 0xca, 0x72, 0x4f, 0x52, 0x98, 0x3f, 0xc2, 0x14, 0x7b, 0x3b, 0x54,
|
||||
};
|
||||
|
||||
/// <remarks>Value generated in the same way as <c>P</c>.</remarks>
|
||||
private byte s = 0xbe;
|
||||
private byte n = 0;
|
||||
|
||||
public VmpcRandomGenerator()
|
||||
{
|
||||
}
|
||||
|
||||
public void AddSeedMaterial(byte[] seed)
|
||||
{
|
||||
for (int m = 0; m < seed.Length; m++)
|
||||
{
|
||||
byte pn = P[n];
|
||||
s = P[(s + pn + seed[m]) & 0xff];
|
||||
P[n] = P[s];
|
||||
P[s] = pn;
|
||||
n = (byte)(n + 1);
|
||||
}
|
||||
}
|
||||
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
public void AddSeedMaterial(ReadOnlySpan<byte> seed)
|
||||
{
|
||||
for (int m = 0; m < seed.Length; m++)
|
||||
{
|
||||
byte pn = P[n];
|
||||
s = P[(s + pn + seed[m]) & 0xff];
|
||||
P[n] = P[s];
|
||||
P[s] = pn;
|
||||
n = (byte)(n + 1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
public void AddSeedMaterial(long seed)
|
||||
{
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
Span<byte> bytes = stackalloc byte[8];
|
||||
Pack.UInt64_To_BE((ulong)seed, bytes);
|
||||
AddSeedMaterial(bytes);
|
||||
#else
|
||||
AddSeedMaterial(Pack.UInt64_To_BE((ulong)seed));
|
||||
#endif
|
||||
}
|
||||
|
||||
public void NextBytes(byte[] bytes)
|
||||
{
|
||||
NextBytes(bytes, 0, bytes.Length);
|
||||
}
|
||||
|
||||
public void NextBytes(byte[] bytes, int start, int len)
|
||||
{
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
NextBytes(bytes.AsSpan(start, len));
|
||||
#else
|
||||
lock (P)
|
||||
{
|
||||
int end = start + len;
|
||||
for (int i = start; i != end; i++)
|
||||
{
|
||||
byte pn = P[n];
|
||||
s = P[(s + pn) & 0xFF];
|
||||
byte ps = P[s];
|
||||
bytes[i] = P[(P[ps] + 1) & 0xFF];
|
||||
P[s] = pn;
|
||||
P[n] = ps;
|
||||
n = (byte)(n + 1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
public void NextBytes(Span<byte> bytes)
|
||||
{
|
||||
lock (P)
|
||||
{
|
||||
for (int i = 0; i < bytes.Length; ++i)
|
||||
{
|
||||
byte pn = P[n];
|
||||
s = P[(s + pn) & 0xFF];
|
||||
byte ps = P[s];
|
||||
bytes[i] = P[(P[ps] + 1) & 0xFF];
|
||||
P[s] = pn;
|
||||
P[n] = ps;
|
||||
n = (byte)(n + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f0a086195f427d344a93a2bb16650895
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
206
Packages/com.tivadar.best.http/Runtime/3rdParty/BouncyCastle/crypto/prng/X931Rng.cs
vendored
Normal file
206
Packages/com.tivadar.best.http/Runtime/3rdParty/BouncyCastle/crypto/prng/X931Rng.cs
vendored
Normal file
@@ -0,0 +1,206 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
|
||||
namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Prng
|
||||
{
|
||||
internal class X931Rng
|
||||
{
|
||||
private const long BLOCK64_RESEED_MAX = 1L << (16 - 1);
|
||||
private const long BLOCK128_RESEED_MAX = 1L << (24 - 1);
|
||||
private const int BLOCK64_MAX_BITS_REQUEST = 1 << (13 - 1);
|
||||
private const int BLOCK128_MAX_BITS_REQUEST = 1 << (19 - 1);
|
||||
|
||||
private readonly IBlockCipher mEngine;
|
||||
private readonly IEntropySource mEntropySource;
|
||||
|
||||
private readonly byte[] mDT;
|
||||
private readonly byte[] mI;
|
||||
private readonly byte[] mR;
|
||||
|
||||
private byte[] mV;
|
||||
|
||||
private long mReseedCounter = 1;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param engine
|
||||
* @param entropySource
|
||||
*/
|
||||
internal X931Rng(IBlockCipher engine, byte[] dateTimeVector, IEntropySource entropySource)
|
||||
{
|
||||
this.mEngine = engine;
|
||||
this.mEntropySource = entropySource;
|
||||
|
||||
this.mDT = new byte[engine.GetBlockSize()];
|
||||
|
||||
Array.Copy(dateTimeVector, 0, mDT, 0, mDT.Length);
|
||||
|
||||
this.mI = new byte[engine.GetBlockSize()];
|
||||
this.mR = new byte[engine.GetBlockSize()];
|
||||
}
|
||||
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
internal int Generate(Span<byte> output, bool predictionResistant)
|
||||
{
|
||||
int outputLen = output.Length;
|
||||
|
||||
if (mR.Length == 8) // 64 bit block size
|
||||
{
|
||||
if (mReseedCounter > BLOCK64_RESEED_MAX)
|
||||
return -1;
|
||||
|
||||
if (outputLen > BLOCK64_MAX_BITS_REQUEST / 8)
|
||||
throw new ArgumentException("Number of bits per request limited to " + BLOCK64_MAX_BITS_REQUEST, "output");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mReseedCounter > BLOCK128_RESEED_MAX)
|
||||
return -1;
|
||||
|
||||
if (outputLen > BLOCK128_MAX_BITS_REQUEST / 8)
|
||||
throw new ArgumentException("Number of bits per request limited to " + BLOCK128_MAX_BITS_REQUEST, "output");
|
||||
}
|
||||
|
||||
if (predictionResistant || mV == null)
|
||||
{
|
||||
mV = mEntropySource.GetEntropy();
|
||||
if (mV.Length != mEngine.GetBlockSize())
|
||||
throw new InvalidOperationException("Insufficient entropy returned");
|
||||
}
|
||||
|
||||
int m = outputLen / mR.Length;
|
||||
|
||||
for (int i = 0; i < m; i++)
|
||||
{
|
||||
mEngine.ProcessBlock(mDT, mI);
|
||||
Process(mR, mI, mV);
|
||||
Process(mV, mR, mI);
|
||||
|
||||
mR.CopyTo(output[(i * mR.Length)..]);
|
||||
|
||||
Increment(mDT);
|
||||
}
|
||||
|
||||
int bytesToCopy = outputLen - m * mR.Length;
|
||||
|
||||
if (bytesToCopy > 0)
|
||||
{
|
||||
mEngine.ProcessBlock(mDT, mI);
|
||||
Process(mR, mI, mV);
|
||||
Process(mV, mR, mI);
|
||||
|
||||
mR.AsSpan(0, bytesToCopy).CopyTo(output[(m * mR.Length)..]);
|
||||
|
||||
Increment(mDT);
|
||||
}
|
||||
|
||||
mReseedCounter++;
|
||||
|
||||
return outputLen * 8;
|
||||
}
|
||||
#else
|
||||
/**
|
||||
* Populate a passed in array with random data.
|
||||
*
|
||||
* @param output output array for generated bits.
|
||||
* @param predictionResistant true if a reseed should be forced, false otherwise.
|
||||
*
|
||||
* @return number of bits generated, -1 if a reseed required.
|
||||
*/
|
||||
internal int Generate(byte[] output, int outputOff, int outputLen, bool predictionResistant)
|
||||
{
|
||||
if (mR.Length == 8) // 64 bit block size
|
||||
{
|
||||
if (mReseedCounter > BLOCK64_RESEED_MAX)
|
||||
return -1;
|
||||
|
||||
if (outputLen > BLOCK64_MAX_BITS_REQUEST / 8)
|
||||
throw new ArgumentException("Number of bits per request limited to " + BLOCK64_MAX_BITS_REQUEST, "output");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mReseedCounter > BLOCK128_RESEED_MAX)
|
||||
return -1;
|
||||
|
||||
if (outputLen > BLOCK128_MAX_BITS_REQUEST / 8)
|
||||
throw new ArgumentException("Number of bits per request limited to " + BLOCK128_MAX_BITS_REQUEST, "output");
|
||||
}
|
||||
|
||||
if (predictionResistant || mV == null)
|
||||
{
|
||||
mV = mEntropySource.GetEntropy();
|
||||
if (mV.Length != mEngine.GetBlockSize())
|
||||
throw new InvalidOperationException("Insufficient entropy returned");
|
||||
}
|
||||
|
||||
int m = outputLen / mR.Length;
|
||||
|
||||
for (int i = 0; i < m; i++)
|
||||
{
|
||||
mEngine.ProcessBlock(mDT, 0, mI, 0);
|
||||
Process(mR, mI, mV);
|
||||
Process(mV, mR, mI);
|
||||
|
||||
Array.Copy(mR, 0, output, outputOff + i * mR.Length, mR.Length);
|
||||
|
||||
Increment(mDT);
|
||||
}
|
||||
|
||||
int bytesToCopy = outputLen - m * mR.Length;
|
||||
|
||||
if (bytesToCopy > 0)
|
||||
{
|
||||
mEngine.ProcessBlock(mDT, 0, mI, 0);
|
||||
Process(mR, mI, mV);
|
||||
Process(mV, mR, mI);
|
||||
|
||||
Array.Copy(mR, 0, output, outputOff + m * mR.Length, bytesToCopy);
|
||||
|
||||
Increment(mDT);
|
||||
}
|
||||
|
||||
mReseedCounter++;
|
||||
|
||||
return outputLen * 8;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Reseed the RNG.
|
||||
*/
|
||||
internal void Reseed()
|
||||
{
|
||||
mV = mEntropySource.GetEntropy();
|
||||
if (mV.Length != mEngine.GetBlockSize())
|
||||
throw new InvalidOperationException("Insufficient entropy returned");
|
||||
mReseedCounter = 1;
|
||||
}
|
||||
|
||||
internal IEntropySource EntropySource
|
||||
{
|
||||
get { return mEntropySource; }
|
||||
}
|
||||
|
||||
private void Process(byte[] res, byte[] a, byte[] b)
|
||||
{
|
||||
for (int i = 0; i != res.Length; i++)
|
||||
{
|
||||
res[i] = (byte)(a[i] ^ b[i]);
|
||||
}
|
||||
|
||||
mEngine.ProcessBlock(res, 0, res, 0);
|
||||
}
|
||||
|
||||
private void Increment(byte[] val)
|
||||
{
|
||||
for (int i = val.Length - 1; i >= 0; i--)
|
||||
{
|
||||
if (++val[i] != 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
11
Packages/com.tivadar.best.http/Runtime/3rdParty/BouncyCastle/crypto/prng/X931Rng.cs.meta
vendored
Normal file
11
Packages/com.tivadar.best.http/Runtime/3rdParty/BouncyCastle/crypto/prng/X931Rng.cs.meta
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0b5c39730f073604498d1d749ac3d680
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
104
Packages/com.tivadar.best.http/Runtime/3rdParty/BouncyCastle/crypto/prng/X931SecureRandom.cs
vendored
Normal file
104
Packages/com.tivadar.best.http/Runtime/3rdParty/BouncyCastle/crypto/prng/X931SecureRandom.cs
vendored
Normal file
@@ -0,0 +1,104 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Security;
|
||||
|
||||
namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Prng
|
||||
{
|
||||
public class X931SecureRandom
|
||||
: SecureRandom
|
||||
{
|
||||
private readonly bool mPredictionResistant;
|
||||
private readonly SecureRandom mRandomSource;
|
||||
private readonly X931Rng mDrbg;
|
||||
|
||||
internal X931SecureRandom(SecureRandom randomSource, X931Rng drbg, bool predictionResistant)
|
||||
: base(null)
|
||||
{
|
||||
this.mRandomSource = randomSource;
|
||||
this.mDrbg = drbg;
|
||||
this.mPredictionResistant = predictionResistant;
|
||||
}
|
||||
|
||||
public override void SetSeed(byte[] seed)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
if (mRandomSource != null)
|
||||
{
|
||||
this.mRandomSource.SetSeed(seed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
public override void SetSeed(Span<byte> seed)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
if (mRandomSource != null)
|
||||
{
|
||||
this.mRandomSource.SetSeed(seed);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
public override void SetSeed(long seed)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
// this will happen when SecureRandom() is created
|
||||
if (mRandomSource != null)
|
||||
{
|
||||
this.mRandomSource.SetSeed(seed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void NextBytes(byte[] bytes)
|
||||
{
|
||||
NextBytes(bytes, 0, bytes.Length);
|
||||
}
|
||||
|
||||
public override void NextBytes(byte[] buf, int off, int len)
|
||||
{
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
NextBytes(buf.AsSpan(off, len));
|
||||
#else
|
||||
lock (this)
|
||||
{
|
||||
// check if a reseed is required...
|
||||
if (mDrbg.Generate(buf, off, len, mPredictionResistant) < 0)
|
||||
{
|
||||
mDrbg.Reseed();
|
||||
mDrbg.Generate(buf, off, len, mPredictionResistant);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
public override void NextBytes(Span<byte> buffer)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
// check if a reseed is required...
|
||||
if (mDrbg.Generate(buffer, mPredictionResistant) < 0)
|
||||
{
|
||||
mDrbg.Reseed();
|
||||
mDrbg.Generate(buffer, mPredictionResistant);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
public override byte[] GenerateSeed(int numBytes)
|
||||
{
|
||||
return EntropyUtilities.GenerateSeed(mDrbg.EntropySource, numBytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 80ec4ccddf3d5ca47a23f1689dca826b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,94 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Utilities;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Security;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Utilities.Date;
|
||||
|
||||
namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Prng
|
||||
{
|
||||
public class X931SecureRandomBuilder
|
||||
{
|
||||
private readonly SecureRandom mRandom; // JDK 1.1 complains on final.
|
||||
|
||||
private IEntropySourceProvider mEntropySourceProvider;
|
||||
private byte[] mDateTimeVector;
|
||||
|
||||
/**
|
||||
* Basic constructor, creates a builder using an EntropySourceProvider based on the default SecureRandom with
|
||||
* predictionResistant set to false.
|
||||
* <p>
|
||||
* Any SecureRandom created from a builder constructed like this will make use of input passed to SecureRandom.setSeed() if
|
||||
* the default SecureRandom does for its generateSeed() call.
|
||||
* </p>
|
||||
*/
|
||||
public X931SecureRandomBuilder()
|
||||
: this(CryptoServicesRegistrar.GetSecureRandom(), false)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a builder with an EntropySourceProvider based on the passed in SecureRandom and the passed in value
|
||||
* for prediction resistance.
|
||||
* <p>
|
||||
* Any SecureRandom created from a builder constructed like this will make use of input passed to SecureRandom.setSeed() if
|
||||
* the passed in SecureRandom does for its generateSeed() call.
|
||||
* </p>
|
||||
* @param entropySource
|
||||
* @param predictionResistant
|
||||
*/
|
||||
public X931SecureRandomBuilder(SecureRandom entropySource, bool predictionResistant)
|
||||
{
|
||||
if (entropySource == null)
|
||||
throw new ArgumentNullException(nameof(entropySource));
|
||||
|
||||
this.mRandom = entropySource;
|
||||
this.mEntropySourceProvider = new BasicEntropySourceProvider(mRandom, predictionResistant);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a builder which makes creates the SecureRandom objects from a specified entropy source provider.
|
||||
* <p>
|
||||
* <b>Note:</b> If this constructor is used any calls to setSeed() in the resulting SecureRandom will be ignored.
|
||||
* </p>
|
||||
* @param entropySourceProvider a provider of EntropySource objects.
|
||||
*/
|
||||
public X931SecureRandomBuilder(IEntropySourceProvider entropySourceProvider)
|
||||
{
|
||||
this.mRandom = null;
|
||||
this.mEntropySourceProvider = entropySourceProvider;
|
||||
}
|
||||
|
||||
public X931SecureRandomBuilder SetDateTimeVector(byte[] dateTimeVector)
|
||||
{
|
||||
this.mDateTimeVector = dateTimeVector;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a X9.31 secure random generator using the passed in engine and key. If predictionResistant is true the
|
||||
* generator will be reseeded on each request.
|
||||
*
|
||||
* @param engine a block cipher to use as the operator.
|
||||
* @param key the block cipher key to initialise engine with.
|
||||
* @param predictionResistant true if engine to be reseeded on each use, false otherwise.
|
||||
* @return a SecureRandom.
|
||||
*/
|
||||
public X931SecureRandom Build(IBlockCipher engine, KeyParameter key, bool predictionResistant)
|
||||
{
|
||||
if (mDateTimeVector == null)
|
||||
{
|
||||
mDateTimeVector = new byte[engine.GetBlockSize()];
|
||||
Pack.UInt64_To_BE((ulong)DateTimeUtilities.CurrentUnixMs(), mDateTimeVector, 0);
|
||||
}
|
||||
|
||||
engine.Init(true, key);
|
||||
|
||||
return new X931SecureRandom(mRandom, new X931Rng(engine, mDateTimeVector, mEntropySourceProvider.Get(engine.GetBlockSize() * 8)), predictionResistant);
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4989e991238339740be31b78063f178a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Packages/com.tivadar.best.http/Runtime/3rdParty/BouncyCastle/crypto/prng/drbg.meta
vendored
Normal file
8
Packages/com.tivadar.best.http/Runtime/3rdParty/BouncyCastle/crypto/prng/drbg.meta
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 43e04952d1da85f438aed0991c0b3edd
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
775
Packages/com.tivadar.best.http/Runtime/3rdParty/BouncyCastle/crypto/prng/drbg/CtrSP800Drbg.cs
vendored
Normal file
775
Packages/com.tivadar.best.http/Runtime/3rdParty/BouncyCastle/crypto/prng/drbg/CtrSP800Drbg.cs
vendored
Normal file
@@ -0,0 +1,775 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Utilities;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Utilities;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Utilities.Encoders;
|
||||
|
||||
namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Prng.Drbg
|
||||
{
|
||||
/**
|
||||
* A SP800-90A CTR DRBG.
|
||||
*/
|
||||
public sealed class CtrSP800Drbg
|
||||
: ISP80090Drbg
|
||||
{
|
||||
private static readonly long TDEA_RESEED_MAX = 1L << (32 - 1);
|
||||
private static readonly long AES_RESEED_MAX = 1L << (48 - 1);
|
||||
private static readonly int TDEA_MAX_BITS_REQUEST = 1 << (13 - 1);
|
||||
private static readonly int AES_MAX_BITS_REQUEST = 1 << (19 - 1);
|
||||
|
||||
private readonly IEntropySource mEntropySource;
|
||||
private readonly IBlockCipher mEngine;
|
||||
private readonly int mKeySizeInBits;
|
||||
private readonly int mSeedLength;
|
||||
private readonly int mSecurityStrength;
|
||||
|
||||
// internal state
|
||||
private byte[] mKey;
|
||||
private byte[] mV;
|
||||
private long mReseedCounter = 0;
|
||||
private bool mIsTdea = false;
|
||||
|
||||
/**
|
||||
* Construct a SP800-90A CTR DRBG.
|
||||
* <p>
|
||||
* Minimum entropy requirement is the security strength requested.
|
||||
* </p>
|
||||
* @param engine underlying block cipher to use to support DRBG
|
||||
* @param keySizeInBits size of the key to use with the block cipher.
|
||||
* @param securityStrength security strength required (in bits)
|
||||
* @param entropySource source of entropy to use for seeding/reseeding.
|
||||
* @param personalizationString personalization string to distinguish this DRBG (may be null).
|
||||
* @param nonce nonce to further distinguish this DRBG (may be null).
|
||||
*/
|
||||
public CtrSP800Drbg(IBlockCipher engine, int keySizeInBits, int securityStrength, IEntropySource entropySource,
|
||||
byte[] personalizationString, byte[] nonce)
|
||||
{
|
||||
if (securityStrength > 256)
|
||||
throw new ArgumentException("Requested security strength is not supported by the derivation function");
|
||||
if (GetMaxSecurityStrength(engine, keySizeInBits) < securityStrength)
|
||||
throw new ArgumentException("Requested security strength is not supported by block cipher and key size");
|
||||
if (entropySource.EntropySize < securityStrength)
|
||||
throw new ArgumentException("Not enough entropy for security strength required");
|
||||
|
||||
mEntropySource = entropySource;
|
||||
mEngine = engine;
|
||||
|
||||
mKeySizeInBits = keySizeInBits;
|
||||
mSecurityStrength = securityStrength;
|
||||
mSeedLength = keySizeInBits + engine.GetBlockSize() * 8;
|
||||
mIsTdea = IsTdea(engine);
|
||||
|
||||
CTR_DRBG_Instantiate_algorithm(nonce, personalizationString);
|
||||
}
|
||||
|
||||
private void CTR_DRBG_Instantiate_algorithm(byte[] nonce, byte[] personalisationString)
|
||||
{
|
||||
byte[] entropy = GetEntropy(); // Get_entropy_input
|
||||
byte[] seedMaterial = Arrays.ConcatenateAll(entropy, nonce, personalisationString);
|
||||
byte[] seed = BlockCipherDF(seedMaterial, mSeedLength / 8);
|
||||
|
||||
int blockSize = mEngine.GetBlockSize();
|
||||
|
||||
mKey = new byte[(mKeySizeInBits + 7) / 8];
|
||||
mV = new byte[blockSize];
|
||||
|
||||
// mKey & mV are modified by this call
|
||||
CTR_DRBG_Update(seed, mKey, mV);
|
||||
|
||||
mReseedCounter = 1;
|
||||
}
|
||||
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
private void CTR_DRBG_Update(ReadOnlySpan<byte> seed, Span<byte> key, Span<byte> v)
|
||||
{
|
||||
int seedLength = seed.Length;
|
||||
Span<byte> temp = seedLength <= 256
|
||||
? stackalloc byte[seedLength]
|
||||
: new byte[seedLength];
|
||||
|
||||
int blockSize = mEngine.GetBlockSize();
|
||||
Span<byte> block = blockSize <= 64
|
||||
? stackalloc byte[blockSize]
|
||||
: new byte[blockSize];
|
||||
|
||||
mEngine.Init(true, ExpandToKeyParameter(key));
|
||||
for (int i = 0; i * blockSize < seed.Length; ++i)
|
||||
{
|
||||
AddOneTo(v);
|
||||
mEngine.ProcessBlock(v, block);
|
||||
|
||||
int bytesToCopy = System.Math.Min(blockSize, temp.Length - i * blockSize);
|
||||
block[..bytesToCopy].CopyTo(temp[(i * blockSize)..]);
|
||||
}
|
||||
|
||||
XorWith(seed, temp);
|
||||
|
||||
key.CopyFrom(temp);
|
||||
v.CopyFrom(temp[key.Length..]);
|
||||
}
|
||||
#else
|
||||
private void CTR_DRBG_Update(byte[] seed, byte[] key, byte[] v)
|
||||
{
|
||||
byte[] temp = new byte[seed.Length];
|
||||
byte[] outputBlock = new byte[mEngine.GetBlockSize()];
|
||||
|
||||
int i = 0;
|
||||
int outLen = mEngine.GetBlockSize();
|
||||
|
||||
mEngine.Init(true, ExpandToKeyParameter(key));
|
||||
while (i * outLen < seed.Length)
|
||||
{
|
||||
AddOneTo(v);
|
||||
mEngine.ProcessBlock(v, 0, outputBlock, 0);
|
||||
|
||||
int bytesToCopy = System.Math.Min(outLen, temp.Length - i * outLen);
|
||||
Array.Copy(outputBlock, 0, temp, i * outLen, bytesToCopy);
|
||||
++i;
|
||||
}
|
||||
|
||||
Xor(temp, seed, temp, 0);
|
||||
|
||||
Array.Copy(temp, 0, key, 0, key.Length);
|
||||
Array.Copy(temp, key.Length, v, 0, v.Length);
|
||||
}
|
||||
#endif
|
||||
|
||||
private void CTR_DRBG_Reseed_algorithm(byte[] additionalInput)
|
||||
{
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
CTR_DRBG_Reseed_algorithm(Spans.FromNullableReadOnly(additionalInput));
|
||||
#else
|
||||
byte[] seedMaterial = Arrays.Concatenate(GetEntropy(), additionalInput);
|
||||
|
||||
seedMaterial = BlockCipherDF(seedMaterial, mSeedLength / 8);
|
||||
|
||||
CTR_DRBG_Update(seedMaterial, mKey, mV);
|
||||
|
||||
mReseedCounter = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
private void CTR_DRBG_Reseed_algorithm(ReadOnlySpan<byte> additionalInput)
|
||||
{
|
||||
int entropyLength = GetEntropyLength();
|
||||
int seedLength = entropyLength + additionalInput.Length;
|
||||
|
||||
Span<byte> seedMaterial = seedLength <= 256
|
||||
? stackalloc byte[seedLength]
|
||||
: new byte[seedLength];
|
||||
|
||||
GetEntropy(seedMaterial[..entropyLength]);
|
||||
additionalInput.CopyTo(seedMaterial[entropyLength..]);
|
||||
|
||||
seedMaterial = BlockCipherDF(seedMaterial, mSeedLength / 8);
|
||||
|
||||
CTR_DRBG_Update(seedMaterial, mKey, mV);
|
||||
|
||||
mReseedCounter = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
private void Xor(ReadOnlySpan<byte> x, ReadOnlySpan<byte> y, Span<byte> z)
|
||||
{
|
||||
for (int i = 0; i < z.Length; ++i)
|
||||
{
|
||||
z[i] = (byte)(x[i] ^ y[i]);
|
||||
}
|
||||
}
|
||||
|
||||
private void XorWith(ReadOnlySpan<byte> x, Span<byte> z)
|
||||
{
|
||||
for (int i = 0; i < z.Length; ++i)
|
||||
{
|
||||
z[i] ^= x[i];
|
||||
}
|
||||
}
|
||||
#else
|
||||
private void Xor(byte[] output, byte[] a, byte[] b, int bOff)
|
||||
{
|
||||
for (int i = 0; i < output.Length; i++)
|
||||
{
|
||||
output[i] = (byte)(a[i] ^ b[bOff + i]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
private void AddOneTo(Span<byte> longer)
|
||||
#else
|
||||
private void AddOneTo(byte[] longer)
|
||||
#endif
|
||||
{
|
||||
uint carry = 1;
|
||||
int i = longer.Length;
|
||||
while (--i >= 0)
|
||||
{
|
||||
carry += longer[i];
|
||||
longer[i] = (byte)carry;
|
||||
carry >>= 8;
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] GetEntropy()
|
||||
{
|
||||
byte[] entropy = mEntropySource.GetEntropy();
|
||||
if (entropy.Length < (mSecurityStrength + 7) / 8)
|
||||
throw new InvalidOperationException("Insufficient entropy provided by entropy source");
|
||||
return entropy;
|
||||
}
|
||||
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
private int GetEntropy(Span<byte> output)
|
||||
{
|
||||
int length = mEntropySource.GetEntropy(output);
|
||||
if (length < (mSecurityStrength + 7) / 8)
|
||||
throw new InvalidOperationException("Insufficient entropy provided by entropy source");
|
||||
return length;
|
||||
}
|
||||
|
||||
private int GetEntropyLength()
|
||||
{
|
||||
return (mEntropySource.EntropySize + 7) / 8;
|
||||
}
|
||||
#endif
|
||||
|
||||
// -- Internal state migration ---
|
||||
|
||||
private static readonly byte[] K_BITS = Hex.DecodeStrict(
|
||||
"000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F");
|
||||
|
||||
// 1. If (number_of_bits_to_return > max_number_of_bits), then return an
|
||||
// ERROR_FLAG.
|
||||
// 2. L = len (input_string)/8.
|
||||
// 3. N = number_of_bits_to_return/8.
|
||||
// Comment: L is the bitstring represention of
|
||||
// the integer resulting from len (input_string)/8.
|
||||
// L shall be represented as a 32-bit integer.
|
||||
//
|
||||
// Comment : N is the bitstring represention of
|
||||
// the integer resulting from
|
||||
// number_of_bits_to_return/8. N shall be
|
||||
// represented as a 32-bit integer.
|
||||
//
|
||||
// 4. S = L || N || input_string || 0x80.
|
||||
// 5. While (len (S) mod outlen)
|
||||
// Comment : Pad S with zeros, if necessary.
|
||||
// 0, S = S || 0x00.
|
||||
//
|
||||
// Comment : Compute the starting value.
|
||||
// 6. temp = the Null string.
|
||||
// 7. i = 0.
|
||||
// 8. K = Leftmost keylen bits of 0x00010203...1D1E1F.
|
||||
// 9. While len (temp) < keylen + outlen, do
|
||||
//
|
||||
// IV = i || 0outlen - len (i).
|
||||
//
|
||||
// 9.1
|
||||
//
|
||||
// temp = temp || BCC (K, (IV || S)).
|
||||
//
|
||||
// 9.2
|
||||
//
|
||||
// i = i + 1.
|
||||
//
|
||||
// 9.3
|
||||
//
|
||||
// Comment : i shall be represented as a 32-bit
|
||||
// integer, i.e., len (i) = 32.
|
||||
//
|
||||
// Comment: The 32-bit integer represenation of
|
||||
// i is padded with zeros to outlen bits.
|
||||
//
|
||||
// Comment: Compute the requested number of
|
||||
// bits.
|
||||
//
|
||||
// 10. K = Leftmost keylen bits of temp.
|
||||
//
|
||||
// 11. X = Next outlen bits of temp.
|
||||
//
|
||||
// 12. temp = the Null string.
|
||||
//
|
||||
// 13. While len (temp) < number_of_bits_to_return, do
|
||||
//
|
||||
// 13.1 X = Block_Encrypt (K, X).
|
||||
//
|
||||
// 13.2 temp = temp || X.
|
||||
//
|
||||
// 14. requested_bits = Leftmost number_of_bits_to_return of temp.
|
||||
//
|
||||
// 15. Return SUCCESS and requested_bits.
|
||||
private byte[] BlockCipherDF(byte[] input, int N)
|
||||
{
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
return BlockCipherDF(input.AsSpan(), N);
|
||||
#else
|
||||
int outLen = mEngine.GetBlockSize();
|
||||
int L = input.Length; // already in bytes
|
||||
// 4 S = L || N || input || 0x80
|
||||
int sLen = 4 + 4 + L + 1;
|
||||
int blockLen = ((sLen + outLen - 1) / outLen) * outLen;
|
||||
byte[] S = new byte[blockLen];
|
||||
Pack.UInt32_To_BE((uint)L, S, 0);
|
||||
Pack.UInt32_To_BE((uint)N, S, 4);
|
||||
Array.Copy(input, 0, S, 8, L);
|
||||
S[8 + L] = 0x80;
|
||||
// S already padded with zeros
|
||||
|
||||
byte[] temp = new byte[mKeySizeInBits / 8 + outLen];
|
||||
byte[] bccOut = new byte[outLen];
|
||||
|
||||
byte[] IV = new byte[outLen];
|
||||
|
||||
int i = 0;
|
||||
byte[] K = new byte[mKeySizeInBits / 8];
|
||||
Array.Copy(K_BITS, 0, K, 0, K.Length);
|
||||
var K1 = ExpandToKeyParameter(K);
|
||||
mEngine.Init(true, K1);
|
||||
|
||||
while (i*outLen*8 < mKeySizeInBits + outLen *8)
|
||||
{
|
||||
Pack.UInt32_To_BE((uint)i, IV, 0);
|
||||
BCC(bccOut, IV, S);
|
||||
|
||||
int bytesToCopy = System.Math.Min(outLen, temp.Length - i * outLen);
|
||||
Array.Copy(bccOut, 0, temp, i * outLen, bytesToCopy);
|
||||
++i;
|
||||
}
|
||||
|
||||
byte[] X = new byte[outLen];
|
||||
Array.Copy(temp, 0, K, 0, K.Length);
|
||||
Array.Copy(temp, K.Length, X, 0, X.Length);
|
||||
|
||||
temp = new byte[N];
|
||||
|
||||
i = 0;
|
||||
mEngine.Init(true, ExpandToKeyParameter(K));
|
||||
|
||||
while (i * outLen < temp.Length)
|
||||
{
|
||||
mEngine.ProcessBlock(X, 0, X, 0);
|
||||
|
||||
int bytesToCopy = System.Math.Min(outLen, temp.Length - i * outLen);
|
||||
Array.Copy(X, 0, temp, i * outLen, bytesToCopy);
|
||||
i++;
|
||||
}
|
||||
|
||||
return temp;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
private byte[] BlockCipherDF(ReadOnlySpan<byte> input, int N)
|
||||
{
|
||||
int blockSize = mEngine.GetBlockSize();
|
||||
int L = input.Length; // already in bytes
|
||||
// 4 S = L || N || input || 0x80
|
||||
int sLen = 4 + 4 + L + 1;
|
||||
int blockLen = ((sLen + blockSize - 1) / blockSize) * blockSize;
|
||||
Span<byte> S = blockLen <= 256
|
||||
? stackalloc byte[blockLen]
|
||||
: new byte[blockLen];
|
||||
Pack.UInt32_To_BE((uint)L, S);
|
||||
Pack.UInt32_To_BE((uint)N, S[4..]);
|
||||
input.CopyTo(S[8..]);
|
||||
S[8 + L] = 0x80;
|
||||
// S already padded with zeros
|
||||
|
||||
int keySize = mKeySizeInBits / 8;
|
||||
int tempSize = keySize + blockSize;
|
||||
Span<byte> temp = tempSize <= 128
|
||||
? stackalloc byte[tempSize]
|
||||
: new byte[tempSize];
|
||||
|
||||
Span<byte> bccOut = blockSize <= 64
|
||||
? stackalloc byte[blockSize]
|
||||
: new byte[blockSize];
|
||||
|
||||
Span<byte> IV = blockSize <= 64
|
||||
? stackalloc byte[blockSize]
|
||||
: new byte[blockSize];
|
||||
|
||||
var K1 = ExpandToKeyParameter(K_BITS.AsSpan(0, keySize));
|
||||
mEngine.Init(true, K1);
|
||||
|
||||
for (int i = 0; i * blockSize < tempSize; ++i)
|
||||
{
|
||||
Pack.UInt32_To_BE((uint)i, IV);
|
||||
BCC(bccOut, IV, S);
|
||||
|
||||
int bytesToCopy = System.Math.Min(blockSize, tempSize - i * blockSize);
|
||||
bccOut[..bytesToCopy].CopyTo(temp[(i * blockSize)..]);
|
||||
}
|
||||
|
||||
var K2 = ExpandToKeyParameter(temp[..keySize]);
|
||||
mEngine.Init(true, K2);
|
||||
var X = temp[keySize..];
|
||||
|
||||
byte[] result = new byte[N];
|
||||
for (int i = 0; i * blockSize < result.Length; ++i)
|
||||
{
|
||||
mEngine.ProcessBlock(X, X);
|
||||
|
||||
int bytesToCopy = System.Math.Min(blockSize, result.Length - i * blockSize);
|
||||
X[..bytesToCopy].CopyTo(result.AsSpan(i * blockSize));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 1. chaining_value = 0^outlen
|
||||
* . Comment: Set the first chaining value to outlen zeros.
|
||||
* 2. n = len (data)/outlen.
|
||||
* 3. Starting with the leftmost bits of data, split the data into n blocks of outlen bits
|
||||
* each, forming block(1) to block(n).
|
||||
* 4. For i = 1 to n do
|
||||
* 4.1 input_block = chaining_value ^ block(i) .
|
||||
* 4.2 chaining_value = Block_Encrypt (Key, input_block).
|
||||
* 5. output_block = chaining_value.
|
||||
* 6. Return output_block.
|
||||
*/
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
private void BCC(Span<byte> bccOut, ReadOnlySpan<byte> iV, ReadOnlySpan<byte> data)
|
||||
{
|
||||
int blockSize = mEngine.GetBlockSize();
|
||||
|
||||
Span<byte> chainingValue = blockSize <= 64
|
||||
? stackalloc byte[blockSize]
|
||||
: new byte[blockSize];
|
||||
Span<byte> inputBlock = blockSize <= 64
|
||||
? stackalloc byte[blockSize]
|
||||
: new byte[blockSize];
|
||||
|
||||
mEngine.ProcessBlock(iV, chainingValue);
|
||||
|
||||
int n = data.Length / blockSize;
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
Xor(chainingValue, data[(i * blockSize)..], inputBlock);
|
||||
mEngine.ProcessBlock(inputBlock, chainingValue);
|
||||
}
|
||||
|
||||
bccOut.CopyFrom(chainingValue);
|
||||
}
|
||||
#else
|
||||
private void BCC(byte[] bccOut, byte[] iV, byte[] data)
|
||||
{
|
||||
int outlen = mEngine.GetBlockSize();
|
||||
byte[] chainingValue = new byte[outlen]; // initial values = 0
|
||||
int n = data.Length / outlen;
|
||||
|
||||
byte[] inputBlock = new byte[outlen];
|
||||
|
||||
mEngine.ProcessBlock(iV, 0, chainingValue, 0);
|
||||
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
Xor(inputBlock, chainingValue, data, i*outlen);
|
||||
mEngine.ProcessBlock(inputBlock, 0, chainingValue, 0);
|
||||
}
|
||||
|
||||
Array.Copy(chainingValue, 0, bccOut, 0, bccOut.Length);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Return the block size (in bits) of the DRBG.
|
||||
*
|
||||
* @return the number of bits produced on each internal round of the DRBG.
|
||||
*/
|
||||
public int BlockSize
|
||||
{
|
||||
get { return mV.Length * 8; }
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate a passed in array with random data.
|
||||
*
|
||||
* @param output output array for generated bits.
|
||||
* @param additionalInput additional input to be added to the DRBG in this step.
|
||||
* @param predictionResistant true if a reseed should be forced, false otherwise.
|
||||
*
|
||||
* @return number of bits generated, -1 if a reseed required.
|
||||
*/
|
||||
public int Generate(byte[] output, int outputOff, int outputLen, byte[] additionalInput,
|
||||
bool predictionResistant)
|
||||
{
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
return additionalInput == null
|
||||
? Generate(output.AsSpan(outputOff, outputLen), predictionResistant)
|
||||
: GenerateWithInput(output.AsSpan(outputOff, outputLen), additionalInput.AsSpan(), predictionResistant);
|
||||
#else
|
||||
if (mIsTdea)
|
||||
{
|
||||
if (mReseedCounter > TDEA_RESEED_MAX)
|
||||
return -1;
|
||||
|
||||
if (outputLen > TDEA_MAX_BITS_REQUEST / 8)
|
||||
throw new ArgumentException("Number of bits per request limited to " + TDEA_MAX_BITS_REQUEST, "output");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mReseedCounter > AES_RESEED_MAX)
|
||||
return -1;
|
||||
|
||||
if (outputLen > AES_MAX_BITS_REQUEST / 8)
|
||||
throw new ArgumentException("Number of bits per request limited to " + AES_MAX_BITS_REQUEST, "output");
|
||||
}
|
||||
|
||||
if (predictionResistant)
|
||||
{
|
||||
CTR_DRBG_Reseed_algorithm(additionalInput);
|
||||
additionalInput = null;
|
||||
}
|
||||
|
||||
if (additionalInput != null)
|
||||
{
|
||||
additionalInput = BlockCipherDF(additionalInput, mSeedLength / 8);
|
||||
CTR_DRBG_Update(additionalInput, mKey, mV);
|
||||
}
|
||||
else
|
||||
{
|
||||
additionalInput = new byte[mSeedLength];
|
||||
}
|
||||
|
||||
byte[] tmp = new byte[mV.Length];
|
||||
|
||||
mEngine.Init(true, ExpandToKeyParameter(mKey));
|
||||
|
||||
for (int i = 0, limit = outputLen / tmp.Length; i <= limit; i++)
|
||||
{
|
||||
int bytesToCopy = System.Math.Min(tmp.Length, outputLen - i * tmp.Length);
|
||||
|
||||
if (bytesToCopy != 0)
|
||||
{
|
||||
AddOneTo(mV);
|
||||
|
||||
mEngine.ProcessBlock(mV, 0, tmp, 0);
|
||||
|
||||
Array.Copy(tmp, 0, output, outputOff + i * tmp.Length, bytesToCopy);
|
||||
}
|
||||
}
|
||||
|
||||
CTR_DRBG_Update(additionalInput, mKey, mV);
|
||||
|
||||
mReseedCounter++;
|
||||
|
||||
return outputLen * 8;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
public int Generate(Span<byte> output, bool predictionResistant)
|
||||
{
|
||||
int outputLen = output.Length;
|
||||
if (mIsTdea)
|
||||
{
|
||||
if (mReseedCounter > TDEA_RESEED_MAX)
|
||||
return -1;
|
||||
|
||||
if (outputLen > TDEA_MAX_BITS_REQUEST / 8)
|
||||
throw new ArgumentException("Number of bits per request limited to " + TDEA_MAX_BITS_REQUEST, "output");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mReseedCounter > AES_RESEED_MAX)
|
||||
return -1;
|
||||
|
||||
if (outputLen > AES_MAX_BITS_REQUEST / 8)
|
||||
throw new ArgumentException("Number of bits per request limited to " + AES_MAX_BITS_REQUEST, "output");
|
||||
}
|
||||
|
||||
if (predictionResistant)
|
||||
{
|
||||
CTR_DRBG_Reseed_algorithm(ReadOnlySpan<byte>.Empty);
|
||||
}
|
||||
|
||||
byte[] seed = new byte[mSeedLength / 8];
|
||||
|
||||
return ImplGenerate(seed, output);
|
||||
}
|
||||
|
||||
public int GenerateWithInput(Span<byte> output, ReadOnlySpan<byte> additionalInput, bool predictionResistant)
|
||||
{
|
||||
int outputLen = output.Length;
|
||||
if (mIsTdea)
|
||||
{
|
||||
if (mReseedCounter > TDEA_RESEED_MAX)
|
||||
return -1;
|
||||
|
||||
if (outputLen > TDEA_MAX_BITS_REQUEST / 8)
|
||||
throw new ArgumentException("Number of bits per request limited to " + TDEA_MAX_BITS_REQUEST, "output");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mReseedCounter > AES_RESEED_MAX)
|
||||
return -1;
|
||||
|
||||
if (outputLen > AES_MAX_BITS_REQUEST / 8)
|
||||
throw new ArgumentException("Number of bits per request limited to " + AES_MAX_BITS_REQUEST, "output");
|
||||
}
|
||||
|
||||
int seedLength = mSeedLength / 8;
|
||||
byte[] seed;
|
||||
if (predictionResistant)
|
||||
{
|
||||
CTR_DRBG_Reseed_algorithm(additionalInput);
|
||||
seed = new byte[seedLength];
|
||||
}
|
||||
else
|
||||
{
|
||||
seed = BlockCipherDF(additionalInput, seedLength);
|
||||
CTR_DRBG_Update(seed, mKey, mV);
|
||||
}
|
||||
|
||||
return ImplGenerate(seed, output);
|
||||
}
|
||||
|
||||
private int ImplGenerate(ReadOnlySpan<byte> seed, Span<byte> output)
|
||||
{
|
||||
byte[] tmp = new byte[mV.Length];
|
||||
|
||||
mEngine.Init(true, ExpandToKeyParameter(mKey));
|
||||
|
||||
int outputLen = output.Length;
|
||||
for (int i = 0, limit = outputLen / tmp.Length; i <= limit; i++)
|
||||
{
|
||||
int bytesToCopy = System.Math.Min(tmp.Length, outputLen - i * tmp.Length);
|
||||
|
||||
if (bytesToCopy != 0)
|
||||
{
|
||||
AddOneTo(mV);
|
||||
|
||||
mEngine.ProcessBlock(mV, 0, tmp, 0);
|
||||
|
||||
tmp[..bytesToCopy].CopyTo(output[(i * tmp.Length)..]);
|
||||
}
|
||||
}
|
||||
|
||||
CTR_DRBG_Update(seed, mKey, mV);
|
||||
|
||||
mReseedCounter++;
|
||||
|
||||
return outputLen * 8;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Reseed the DRBG.
|
||||
*
|
||||
* @param additionalInput additional input to be added to the DRBG in this step.
|
||||
*/
|
||||
public void Reseed(byte[] additionalInput)
|
||||
{
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
Reseed(Spans.FromNullableReadOnly(additionalInput));
|
||||
#else
|
||||
CTR_DRBG_Reseed_algorithm(additionalInput);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
public void Reseed(ReadOnlySpan<byte> additionalInput)
|
||||
{
|
||||
CTR_DRBG_Reseed_algorithm(additionalInput);
|
||||
}
|
||||
#endif
|
||||
|
||||
private bool IsTdea(IBlockCipher cipher)
|
||||
{
|
||||
return cipher.AlgorithmName.Equals("DESede") || cipher.AlgorithmName.Equals("TDEA");
|
||||
}
|
||||
|
||||
private int GetMaxSecurityStrength(IBlockCipher cipher, int keySizeInBits)
|
||||
{
|
||||
if (IsTdea(cipher) && keySizeInBits == 168)
|
||||
{
|
||||
return 112;
|
||||
}
|
||||
if (cipher.AlgorithmName.Equals("AES"))
|
||||
{
|
||||
return keySizeInBits;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
private KeyParameter ExpandToKeyParameter(byte[] key)
|
||||
{
|
||||
if (!mIsTdea)
|
||||
return new KeyParameter(key);
|
||||
|
||||
// expand key to 192 bits.
|
||||
byte[] tmp = new byte[24];
|
||||
|
||||
PadKey(key, 0, tmp, 0);
|
||||
PadKey(key, 7, tmp, 8);
|
||||
PadKey(key, 14, tmp, 16);
|
||||
|
||||
return new KeyParameter(tmp);
|
||||
}
|
||||
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
private KeyParameter ExpandToKeyParameter(ReadOnlySpan<byte> key)
|
||||
{
|
||||
if (!mIsTdea)
|
||||
return new KeyParameter(key);
|
||||
|
||||
// expand key to 192 bits.
|
||||
Span<byte> tmp = stackalloc byte[24];
|
||||
|
||||
PadKey(key, tmp);
|
||||
PadKey(key[7..], tmp[8..]);
|
||||
PadKey(key[14..], tmp[16..]);
|
||||
|
||||
return new KeyParameter(tmp);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Pad out a key for TDEA, setting odd parity for each byte.
|
||||
*
|
||||
* @param keyMaster
|
||||
* @param keyOff
|
||||
* @param tmp
|
||||
* @param tmpOff
|
||||
*/
|
||||
private void PadKey(byte[] keyMaster, int keyOff, byte[] tmp, int tmpOff)
|
||||
{
|
||||
tmp[tmpOff + 0] = (byte)(keyMaster[keyOff + 0] & 0xfe);
|
||||
tmp[tmpOff + 1] = (byte)((keyMaster[keyOff + 0] << 7) | ((keyMaster[keyOff + 1] & 0xfc) >> 1));
|
||||
tmp[tmpOff + 2] = (byte)((keyMaster[keyOff + 1] << 6) | ((keyMaster[keyOff + 2] & 0xf8) >> 2));
|
||||
tmp[tmpOff + 3] = (byte)((keyMaster[keyOff + 2] << 5) | ((keyMaster[keyOff + 3] & 0xf0) >> 3));
|
||||
tmp[tmpOff + 4] = (byte)((keyMaster[keyOff + 3] << 4) | ((keyMaster[keyOff + 4] & 0xe0) >> 4));
|
||||
tmp[tmpOff + 5] = (byte)((keyMaster[keyOff + 4] << 3) | ((keyMaster[keyOff + 5] & 0xc0) >> 5));
|
||||
tmp[tmpOff + 6] = (byte)((keyMaster[keyOff + 5] << 2) | ((keyMaster[keyOff + 6] & 0x80) >> 6));
|
||||
tmp[tmpOff + 7] = (byte)(keyMaster[keyOff + 6] << 1);
|
||||
|
||||
DesParameters.SetOddParity(tmp, tmpOff, 8);
|
||||
}
|
||||
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
private void PadKey(ReadOnlySpan<byte> keyMaster, Span<byte> tmp)
|
||||
{
|
||||
tmp[0] = (byte)(keyMaster[0] & 0xFE);
|
||||
tmp[1] = (byte)((keyMaster[0] << 7) | ((keyMaster[1] & 0xfc) >> 1));
|
||||
tmp[2] = (byte)((keyMaster[1] << 6) | ((keyMaster[2] & 0xf8) >> 2));
|
||||
tmp[3] = (byte)((keyMaster[2] << 5) | ((keyMaster[3] & 0xf0) >> 3));
|
||||
tmp[4] = (byte)((keyMaster[3] << 4) | ((keyMaster[4] & 0xe0) >> 4));
|
||||
tmp[5] = (byte)((keyMaster[4] << 3) | ((keyMaster[5] & 0xc0) >> 5));
|
||||
tmp[6] = (byte)((keyMaster[5] << 2) | ((keyMaster[6] & 0x80) >> 6));
|
||||
tmp[7] = (byte)(keyMaster[6] << 1);
|
||||
|
||||
DesParameters.SetOddParity(tmp[..8]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 74a60b4f0c626d946a8f1cd50fd12295
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
115
Packages/com.tivadar.best.http/Runtime/3rdParty/BouncyCastle/crypto/prng/drbg/DrbgUtilities.cs
vendored
Normal file
115
Packages/com.tivadar.best.http/Runtime/3rdParty/BouncyCastle/crypto/prng/drbg/DrbgUtilities.cs
vendored
Normal file
@@ -0,0 +1,115 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Utilities;
|
||||
|
||||
namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Prng.Drbg
|
||||
{
|
||||
internal class DrbgUtilities
|
||||
{
|
||||
private static readonly IDictionary<string, int> MaxSecurityStrengths =
|
||||
new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
static DrbgUtilities()
|
||||
{
|
||||
MaxSecurityStrengths.Add("SHA-1", 128);
|
||||
|
||||
MaxSecurityStrengths.Add("SHA-224", 192);
|
||||
MaxSecurityStrengths.Add("SHA-256", 256);
|
||||
MaxSecurityStrengths.Add("SHA-384", 256);
|
||||
MaxSecurityStrengths.Add("SHA-512", 256);
|
||||
|
||||
MaxSecurityStrengths.Add("SHA-512/224", 192);
|
||||
MaxSecurityStrengths.Add("SHA-512/256", 256);
|
||||
}
|
||||
|
||||
internal static int GetMaxSecurityStrength(IDigest d)
|
||||
{
|
||||
return MaxSecurityStrengths[d.AlgorithmName];
|
||||
}
|
||||
|
||||
internal static int GetMaxSecurityStrength(IMac m)
|
||||
{
|
||||
string name = m.AlgorithmName;
|
||||
|
||||
return MaxSecurityStrengths[name.Substring(0, name.IndexOf("/"))];
|
||||
}
|
||||
|
||||
/**
|
||||
* Used by both Dual EC and Hash.
|
||||
*/
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
internal static void HashDF(IDigest digest, ReadOnlySpan<byte> seedMaterial, int seedLength, Span<byte> output)
|
||||
#else
|
||||
internal static void HashDF(IDigest digest, byte[] seedMaterial, int seedLength, byte[] output)
|
||||
#endif
|
||||
{
|
||||
// 1. temp = the Null string.
|
||||
// 2. .
|
||||
// 3. counter = an 8-bit binary value representing the integer "1".
|
||||
// 4. For i = 1 to len do
|
||||
// Comment : In step 4.1, no_of_bits_to_return
|
||||
// is used as a 32-bit string.
|
||||
// 4.1 temp = temp || Hash (counter || no_of_bits_to_return ||
|
||||
// input_string).
|
||||
// 4.2 counter = counter + 1.
|
||||
// 5. requested_bits = Leftmost (no_of_bits_to_return) of temp.
|
||||
// 6. Return SUCCESS and requested_bits.
|
||||
int outputLength = (seedLength + 7) / 8;
|
||||
|
||||
int digestSize = digest.GetDigestSize();
|
||||
int len = outputLength / digestSize;
|
||||
int counter = 1;
|
||||
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
Span<byte> dig = digestSize <= 128
|
||||
? stackalloc byte[digestSize]
|
||||
: new byte[digestSize];
|
||||
Span<byte> header = stackalloc byte[5];
|
||||
Pack.UInt32_To_BE((uint)seedLength, header[1..]);
|
||||
#else
|
||||
byte[] dig = new byte[digestSize];
|
||||
byte[] header = new byte[5];
|
||||
Pack.UInt32_To_BE((uint)seedLength, header, 1);
|
||||
#endif
|
||||
|
||||
for (int i = 0; i <= len; i++, counter++)
|
||||
{
|
||||
header[0] = (byte)counter;
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
digest.BlockUpdate(header);
|
||||
digest.BlockUpdate(seedMaterial);
|
||||
digest.DoFinal(dig);
|
||||
|
||||
int bytesToCopy = System.Math.Min(digestSize, outputLength - i * digestSize);
|
||||
dig[..bytesToCopy].CopyTo(output[(i * digestSize)..]);
|
||||
#else
|
||||
digest.BlockUpdate(header, 0, header.Length);
|
||||
digest.BlockUpdate(seedMaterial, 0, seedMaterial.Length);
|
||||
digest.DoFinal(dig, 0);
|
||||
|
||||
int bytesToCopy = System.Math.Min(digestSize, outputLength - i * digestSize);
|
||||
Array.Copy(dig, 0, output, i * digestSize, bytesToCopy);
|
||||
#endif
|
||||
}
|
||||
|
||||
// do a left shift to get rid of excess bits.
|
||||
if (seedLength % 8 != 0)
|
||||
{
|
||||
int shift = 8 - (seedLength % 8);
|
||||
uint carry = 0;
|
||||
|
||||
for (int i = 0; i != outputLength; i++)
|
||||
{
|
||||
uint b = output[i];
|
||||
output[i] = (byte)((b >> shift) | (carry << (8 - shift)));
|
||||
carry = b;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 37ddcc3b4b61995479b0c93d93b23359
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
351
Packages/com.tivadar.best.http/Runtime/3rdParty/BouncyCastle/crypto/prng/drbg/HMacSP800Drbg.cs
vendored
Normal file
351
Packages/com.tivadar.best.http/Runtime/3rdParty/BouncyCastle/crypto/prng/drbg/HMacSP800Drbg.cs
vendored
Normal file
@@ -0,0 +1,351 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Utilities;
|
||||
|
||||
namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Prng.Drbg
|
||||
{
|
||||
/**
|
||||
* A SP800-90A HMAC DRBG.
|
||||
*/
|
||||
public sealed class HMacSP800Drbg
|
||||
: ISP80090Drbg
|
||||
{
|
||||
private readonly static long RESEED_MAX = 1L << (48 - 1);
|
||||
private readonly static int MAX_BITS_REQUEST = 1 << (19 - 1);
|
||||
|
||||
private readonly byte[] mK;
|
||||
private readonly byte[] mV;
|
||||
private readonly IEntropySource mEntropySource;
|
||||
private readonly IMac mHMac;
|
||||
private readonly int mSecurityStrength;
|
||||
|
||||
private long mReseedCounter;
|
||||
|
||||
/**
|
||||
* Construct a SP800-90A Hash DRBG.
|
||||
* <p>
|
||||
* Minimum entropy requirement is the security strength requested.
|
||||
* </p>
|
||||
* @param hMac Hash MAC to base the DRBG on.
|
||||
* @param securityStrength security strength required (in bits)
|
||||
* @param entropySource source of entropy to use for seeding/reseeding.
|
||||
* @param personalizationString personalization string to distinguish this DRBG (may be null).
|
||||
* @param nonce nonce to further distinguish this DRBG (may be null).
|
||||
*/
|
||||
public HMacSP800Drbg(IMac hMac, int securityStrength, IEntropySource entropySource,
|
||||
byte[] personalizationString, byte[] nonce)
|
||||
{
|
||||
if (securityStrength > DrbgUtilities.GetMaxSecurityStrength(hMac))
|
||||
throw new ArgumentException("Requested security strength is not supported by the derivation function");
|
||||
if (entropySource.EntropySize < securityStrength)
|
||||
throw new ArgumentException("Not enough entropy for security strength required");
|
||||
|
||||
mHMac = hMac;
|
||||
mSecurityStrength = securityStrength;
|
||||
mEntropySource = entropySource;
|
||||
|
||||
byte[] entropy = GetEntropy();
|
||||
byte[] seedMaterial = Arrays.ConcatenateAll(entropy, nonce, personalizationString);
|
||||
|
||||
mK = new byte[hMac.GetMacSize()];
|
||||
mV = new byte[mK.Length];
|
||||
Arrays.Fill(mV, (byte)1);
|
||||
|
||||
hmac_DRBG_Update(seedMaterial);
|
||||
|
||||
mReseedCounter = 1;
|
||||
}
|
||||
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
private void hmac_DRBG_Update()
|
||||
{
|
||||
hmac_DRBG_Update_Func(ReadOnlySpan<byte>.Empty, 0x00);
|
||||
}
|
||||
|
||||
private void hmac_DRBG_Update(ReadOnlySpan<byte> seedMaterial)
|
||||
{
|
||||
hmac_DRBG_Update_Func(seedMaterial, 0x00);
|
||||
hmac_DRBG_Update_Func(seedMaterial, 0x01);
|
||||
}
|
||||
|
||||
private void hmac_DRBG_Update_Func(ReadOnlySpan<byte> seedMaterial, byte vValue)
|
||||
{
|
||||
mHMac.Init(new KeyParameter(mK));
|
||||
|
||||
mHMac.BlockUpdate(mV);
|
||||
mHMac.Update(vValue);
|
||||
if (!seedMaterial.IsEmpty)
|
||||
{
|
||||
mHMac.BlockUpdate(seedMaterial);
|
||||
}
|
||||
mHMac.DoFinal(mK);
|
||||
|
||||
mHMac.Init(new KeyParameter(mK));
|
||||
mHMac.BlockUpdate(mV);
|
||||
mHMac.DoFinal(mV);
|
||||
}
|
||||
#else
|
||||
private void hmac_DRBG_Update(byte[] seedMaterial)
|
||||
{
|
||||
hmac_DRBG_Update_Func(seedMaterial, 0x00);
|
||||
if (seedMaterial != null)
|
||||
{
|
||||
hmac_DRBG_Update_Func(seedMaterial, 0x01);
|
||||
}
|
||||
}
|
||||
|
||||
private void hmac_DRBG_Update_Func(byte[] seedMaterial, byte vValue)
|
||||
{
|
||||
mHMac.Init(new KeyParameter(mK));
|
||||
|
||||
mHMac.BlockUpdate(mV, 0, mV.Length);
|
||||
mHMac.Update(vValue);
|
||||
|
||||
if (seedMaterial != null)
|
||||
{
|
||||
mHMac.BlockUpdate(seedMaterial, 0, seedMaterial.Length);
|
||||
}
|
||||
|
||||
mHMac.DoFinal(mK, 0);
|
||||
|
||||
mHMac.Init(new KeyParameter(mK));
|
||||
mHMac.BlockUpdate(mV, 0, mV.Length);
|
||||
|
||||
mHMac.DoFinal(mV, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Return the block size (in bits) of the DRBG.
|
||||
*
|
||||
* @return the number of bits produced on each round of the DRBG.
|
||||
*/
|
||||
public int BlockSize
|
||||
{
|
||||
get { return mV.Length * 8; }
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate a passed in array with random data.
|
||||
*
|
||||
* @param output output array for generated bits.
|
||||
* @param additionalInput additional input to be added to the DRBG in this step.
|
||||
* @param predictionResistant true if a reseed should be forced, false otherwise.
|
||||
*
|
||||
* @return number of bits generated, -1 if a reseed required.
|
||||
*/
|
||||
public int Generate(byte[] output, int outputOff, int outputLen, byte[] additionalInput,
|
||||
bool predictionResistant)
|
||||
{
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
return additionalInput == null
|
||||
? Generate(output.AsSpan(outputOff, outputLen), predictionResistant)
|
||||
: GenerateWithInput(output.AsSpan(outputOff, outputLen), additionalInput.AsSpan(), predictionResistant);
|
||||
#else
|
||||
int numberOfBits = outputLen * 8;
|
||||
|
||||
if (numberOfBits > MAX_BITS_REQUEST)
|
||||
throw new ArgumentException("Number of bits per request limited to " + MAX_BITS_REQUEST, "output");
|
||||
|
||||
if (mReseedCounter > RESEED_MAX)
|
||||
return -1;
|
||||
|
||||
if (predictionResistant)
|
||||
{
|
||||
Reseed(additionalInput);
|
||||
additionalInput = null;
|
||||
}
|
||||
|
||||
// 2.
|
||||
if (additionalInput != null)
|
||||
{
|
||||
hmac_DRBG_Update(additionalInput);
|
||||
}
|
||||
|
||||
// 3.
|
||||
byte[] rv = new byte[outputLen];
|
||||
|
||||
int m = outputLen / mV.Length;
|
||||
|
||||
mHMac.Init(new KeyParameter(mK));
|
||||
|
||||
for (int i = 0; i < m; i++)
|
||||
{
|
||||
mHMac.BlockUpdate(mV, 0, mV.Length);
|
||||
mHMac.DoFinal(mV, 0);
|
||||
|
||||
Array.Copy(mV, 0, rv, i * mV.Length, mV.Length);
|
||||
}
|
||||
|
||||
if (m * mV.Length < rv.Length)
|
||||
{
|
||||
mHMac.BlockUpdate(mV, 0, mV.Length);
|
||||
mHMac.DoFinal(mV, 0);
|
||||
|
||||
Array.Copy(mV, 0, rv, m * mV.Length, rv.Length - (m * mV.Length));
|
||||
}
|
||||
|
||||
hmac_DRBG_Update(additionalInput);
|
||||
|
||||
mReseedCounter++;
|
||||
|
||||
Array.Copy(rv, 0, output, outputOff, outputLen);
|
||||
|
||||
return numberOfBits;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
public int Generate(Span<byte> output, bool predictionResistant)
|
||||
{
|
||||
int numberOfBits = output.Length * 8;
|
||||
|
||||
if (numberOfBits > MAX_BITS_REQUEST)
|
||||
throw new ArgumentException("Number of bits per request limited to " + MAX_BITS_REQUEST, "output");
|
||||
|
||||
if (mReseedCounter > RESEED_MAX)
|
||||
return -1;
|
||||
|
||||
if (predictionResistant)
|
||||
{
|
||||
Reseed(ReadOnlySpan<byte>.Empty);
|
||||
}
|
||||
|
||||
// 3.
|
||||
ImplGenerate(output);
|
||||
|
||||
hmac_DRBG_Update();
|
||||
|
||||
mReseedCounter++;
|
||||
|
||||
return numberOfBits;
|
||||
}
|
||||
|
||||
public int GenerateWithInput(Span<byte> output, ReadOnlySpan<byte> additionalInput, bool predictionResistant)
|
||||
{
|
||||
int numberOfBits = output.Length * 8;
|
||||
|
||||
if (numberOfBits > MAX_BITS_REQUEST)
|
||||
throw new ArgumentException("Number of bits per request limited to " + MAX_BITS_REQUEST, "output");
|
||||
|
||||
if (mReseedCounter > RESEED_MAX)
|
||||
return -1;
|
||||
|
||||
if (predictionResistant)
|
||||
{
|
||||
Reseed(additionalInput);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 2.
|
||||
hmac_DRBG_Update(additionalInput);
|
||||
}
|
||||
|
||||
// 3.
|
||||
ImplGenerate(output);
|
||||
|
||||
if (predictionResistant)
|
||||
{
|
||||
hmac_DRBG_Update();
|
||||
}
|
||||
else
|
||||
{
|
||||
hmac_DRBG_Update(additionalInput);
|
||||
}
|
||||
|
||||
mReseedCounter++;
|
||||
|
||||
return numberOfBits;
|
||||
}
|
||||
|
||||
private void ImplGenerate(Span<byte> output)
|
||||
{
|
||||
int outputLen = output.Length;
|
||||
int m = outputLen / mV.Length;
|
||||
|
||||
mHMac.Init(new KeyParameter(mK));
|
||||
|
||||
for (int i = 0; i < m; i++)
|
||||
{
|
||||
mHMac.BlockUpdate(mV);
|
||||
mHMac.DoFinal(mV);
|
||||
|
||||
mV.CopyTo(output[(i * mV.Length)..]);
|
||||
}
|
||||
|
||||
int remaining = outputLen - m * mV.Length;
|
||||
if (remaining > 0)
|
||||
{
|
||||
mHMac.BlockUpdate(mV);
|
||||
mHMac.DoFinal(mV);
|
||||
|
||||
mV[..remaining].CopyTo(output[(m * mV.Length)..]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Reseed the DRBG.
|
||||
*
|
||||
* @param additionalInput additional input to be added to the DRBG in this step.
|
||||
*/
|
||||
public void Reseed(byte[] additionalInput)
|
||||
{
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
Reseed(Spans.FromNullableReadOnly(additionalInput));
|
||||
#else
|
||||
byte[] entropy = GetEntropy();
|
||||
byte[] seedMaterial = Arrays.Concatenate(entropy, additionalInput);
|
||||
|
||||
hmac_DRBG_Update(seedMaterial);
|
||||
|
||||
mReseedCounter = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
public void Reseed(ReadOnlySpan<byte> additionalInput)
|
||||
{
|
||||
int entropyLength = GetEntropyLength();
|
||||
int seedMaterialLength = entropyLength + additionalInput.Length;
|
||||
Span<byte> seedMaterial = seedMaterialLength <= 256
|
||||
? stackalloc byte[seedMaterialLength]
|
||||
: new byte[seedMaterialLength];
|
||||
GetEntropy(seedMaterial);
|
||||
additionalInput.CopyTo(seedMaterial[entropyLength..]);
|
||||
|
||||
hmac_DRBG_Update(seedMaterial);
|
||||
|
||||
mReseedCounter = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
private byte[] GetEntropy()
|
||||
{
|
||||
byte[] entropy = mEntropySource.GetEntropy();
|
||||
if (entropy.Length < (mSecurityStrength + 7) / 8)
|
||||
throw new InvalidOperationException("Insufficient entropy provided by entropy source");
|
||||
return entropy;
|
||||
}
|
||||
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
private int GetEntropy(Span<byte> output)
|
||||
{
|
||||
int length = mEntropySource.GetEntropy(output);
|
||||
if (length < (mSecurityStrength + 7) / 8)
|
||||
throw new InvalidOperationException("Insufficient entropy provided by entropy source");
|
||||
return length;
|
||||
}
|
||||
|
||||
private int GetEntropyLength()
|
||||
{
|
||||
return (mEntropySource.EntropySize + 7) / 8;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5e1b0fc602d5dfe4493f15095e54e608
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
502
Packages/com.tivadar.best.http/Runtime/3rdParty/BouncyCastle/crypto/prng/drbg/HashSP800Drbg.cs
vendored
Normal file
502
Packages/com.tivadar.best.http/Runtime/3rdParty/BouncyCastle/crypto/prng/drbg/HashSP800Drbg.cs
vendored
Normal file
@@ -0,0 +1,502 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Utilities;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Utilities;
|
||||
|
||||
namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Prng.Drbg
|
||||
{
|
||||
/**
|
||||
* A SP800-90A Hash DRBG.
|
||||
*/
|
||||
public sealed class HashSP800Drbg
|
||||
: ISP80090Drbg
|
||||
{
|
||||
private readonly static byte[] ONE = { 0x01 };
|
||||
|
||||
private readonly static long RESEED_MAX = 1L << (48 - 1);
|
||||
private readonly static int MAX_BITS_REQUEST = 1 << (19 - 1);
|
||||
|
||||
private static readonly IDictionary<string, int> SeedLens =
|
||||
new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
static HashSP800Drbg()
|
||||
{
|
||||
SeedLens.Add("SHA-1", 440);
|
||||
SeedLens.Add("SHA-224", 440);
|
||||
SeedLens.Add("SHA-256", 440);
|
||||
SeedLens.Add("SHA-512/256", 440);
|
||||
SeedLens.Add("SHA-512/224", 440);
|
||||
SeedLens.Add("SHA-384", 888);
|
||||
SeedLens.Add("SHA-512", 888);
|
||||
}
|
||||
|
||||
private readonly IDigest mDigest;
|
||||
private readonly IEntropySource mEntropySource;
|
||||
private readonly int mSecurityStrength;
|
||||
private readonly int mSeedLength;
|
||||
|
||||
private byte[] mV;
|
||||
private byte[] mC;
|
||||
private long mReseedCounter;
|
||||
|
||||
/**
|
||||
* Construct a SP800-90A Hash DRBG.
|
||||
* <p>
|
||||
* Minimum entropy requirement is the security strength requested.
|
||||
* </p>
|
||||
* @param digest source digest to use for DRB stream.
|
||||
* @param securityStrength security strength required (in bits)
|
||||
* @param entropySource source of entropy to use for seeding/reseeding.
|
||||
* @param personalizationString personalization string to distinguish this DRBG (may be null).
|
||||
* @param nonce nonce to further distinguish this DRBG (may be null).
|
||||
*/
|
||||
public HashSP800Drbg(IDigest digest, int securityStrength, IEntropySource entropySource, byte[] personalizationString, byte[] nonce)
|
||||
{
|
||||
if (securityStrength > DrbgUtilities.GetMaxSecurityStrength(digest))
|
||||
throw new ArgumentException("Requested security strength is not supported by the derivation function");
|
||||
if (entropySource.EntropySize < securityStrength)
|
||||
throw new ArgumentException("Not enough entropy for security strength required");
|
||||
|
||||
mDigest = digest;
|
||||
mEntropySource = entropySource;
|
||||
mSecurityStrength = securityStrength;
|
||||
mSeedLength = SeedLens[digest.AlgorithmName];
|
||||
|
||||
// 1. seed_material = entropy_input || nonce || personalization_string.
|
||||
// 2. seed = Hash_df (seed_material, seedlen).
|
||||
// 3. V = seed.
|
||||
// 4. C = Hash_df ((0x00 || V), seedlen). Comment: Preceed V with a byte
|
||||
// of zeros.
|
||||
// 5. reseed_counter = 1.
|
||||
// 6. Return V, C, and reseed_counter as the initial_working_state
|
||||
|
||||
byte[] entropy = GetEntropy();
|
||||
byte[] seedMaterial = Arrays.ConcatenateAll(entropy, nonce, personalizationString);
|
||||
mV = new byte[(mSeedLength + 7) / 8];
|
||||
DrbgUtilities.HashDF(mDigest, seedMaterial, mSeedLength, mV);
|
||||
|
||||
byte[] subV = new byte[mV.Length + 1];
|
||||
Array.Copy(mV, 0, subV, 1, mV.Length);
|
||||
mC = new byte[(mSeedLength + 7) / 8];
|
||||
DrbgUtilities.HashDF(mDigest, subV, mSeedLength, mC);
|
||||
|
||||
mReseedCounter = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the block size (in bits) of the DRBG.
|
||||
*
|
||||
* @return the number of bits produced on each internal round of the DRBG.
|
||||
*/
|
||||
public int BlockSize
|
||||
{
|
||||
get { return mDigest.GetDigestSize() * 8; }
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate a passed in array with random data.
|
||||
*
|
||||
* @param output output array for generated bits.
|
||||
* @param additionalInput additional input to be added to the DRBG in this step.
|
||||
* @param predictionResistant true if a reseed should be forced, false otherwise.
|
||||
*
|
||||
* @return number of bits generated, -1 if a reseed required.
|
||||
*/
|
||||
public int Generate(byte[] output, int outputOff, int outputLen, byte[] additionalInput,
|
||||
bool predictionResistant)
|
||||
{
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
return additionalInput == null
|
||||
? Generate(output.AsSpan(outputOff, outputLen), predictionResistant)
|
||||
: GenerateWithInput(output.AsSpan(outputOff, outputLen), additionalInput.AsSpan(), predictionResistant);
|
||||
#else
|
||||
// 1. If reseed_counter > reseed_interval, then return an indication that a
|
||||
// reseed is required.
|
||||
// 2. If (additional_input != Null), then do
|
||||
// 2.1 w = Hash (0x02 || V || additional_input).
|
||||
// 2.2 V = (V + w) mod 2^seedlen
|
||||
// .
|
||||
// 3. (returned_bits) = Hashgen (requested_number_of_bits, V).
|
||||
// 4. H = Hash (0x03 || V).
|
||||
// 5. V = (V + H + C + reseed_counter) mod 2^seedlen
|
||||
// .
|
||||
// 6. reseed_counter = reseed_counter + 1.
|
||||
// 7. Return SUCCESS, returned_bits, and the new values of V, C, and
|
||||
// reseed_counter for the new_working_state.
|
||||
int numberOfBits = outputLen * 8;
|
||||
|
||||
if (numberOfBits > MAX_BITS_REQUEST)
|
||||
throw new ArgumentException("Number of bits per request limited to " + MAX_BITS_REQUEST, "output");
|
||||
|
||||
if (mReseedCounter > RESEED_MAX)
|
||||
return -1;
|
||||
|
||||
if (predictionResistant)
|
||||
{
|
||||
Reseed(additionalInput);
|
||||
additionalInput = null;
|
||||
}
|
||||
|
||||
// 2.
|
||||
if (additionalInput != null)
|
||||
{
|
||||
byte[] newInput = new byte[1 + mV.Length + additionalInput.Length];
|
||||
newInput[0] = 0x02;
|
||||
Array.Copy(mV, 0, newInput, 1, mV.Length);
|
||||
Array.Copy(additionalInput, 0, newInput, 1 + mV.Length, additionalInput.Length);
|
||||
byte[] w = Hash(newInput);
|
||||
|
||||
AddTo(mV, w);
|
||||
}
|
||||
|
||||
// 3.
|
||||
byte[] rv = Hashgen(mV, outputLen);
|
||||
|
||||
// 4.
|
||||
byte[] subH = new byte[mV.Length + 1];
|
||||
Array.Copy(mV, 0, subH, 1, mV.Length);
|
||||
subH[0] = 0x03;
|
||||
|
||||
byte[] H = Hash(subH);
|
||||
|
||||
// 5.
|
||||
AddTo(mV, H);
|
||||
AddTo(mV, mC);
|
||||
|
||||
byte[] c = new byte[4];
|
||||
Pack.UInt32_To_BE((uint)mReseedCounter, c);
|
||||
|
||||
AddTo(mV, c);
|
||||
|
||||
mReseedCounter++;
|
||||
|
||||
Array.Copy(rv, 0, output, outputOff, outputLen);
|
||||
|
||||
return numberOfBits;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
public int Generate(Span<byte> output, bool predictionResistant)
|
||||
{
|
||||
// 1. If reseed_counter > reseed_interval, then return an indication that a
|
||||
// reseed is required.
|
||||
// 2. If (additional_input != Null), then do
|
||||
// 2.1 w = Hash (0x02 || V || additional_input).
|
||||
// 2.2 V = (V + w) mod 2^seedlen
|
||||
// .
|
||||
// 3. (returned_bits) = Hashgen (requested_number_of_bits, V).
|
||||
// 4. H = Hash (0x03 || V).
|
||||
// 5. V = (V + H + C + reseed_counter) mod 2^seedlen
|
||||
// .
|
||||
// 6. reseed_counter = reseed_counter + 1.
|
||||
// 7. Return SUCCESS, returned_bits, and the new values of V, C, and
|
||||
// reseed_counter for the new_working_state.
|
||||
int numberOfBits = output.Length * 8;
|
||||
|
||||
if (numberOfBits > MAX_BITS_REQUEST)
|
||||
throw new ArgumentException("Number of bits per request limited to " + MAX_BITS_REQUEST, "output");
|
||||
|
||||
if (mReseedCounter > RESEED_MAX)
|
||||
return -1;
|
||||
|
||||
if (predictionResistant)
|
||||
{
|
||||
Reseed(ReadOnlySpan<byte>.Empty);
|
||||
}
|
||||
|
||||
return ImplGenerate(output);
|
||||
}
|
||||
|
||||
public int GenerateWithInput(Span<byte> output, ReadOnlySpan<byte> additionalInput, bool predictionResistant)
|
||||
{
|
||||
// 1. If reseed_counter > reseed_interval, then return an indication that a
|
||||
// reseed is required.
|
||||
// 2. If (additional_input != Null), then do
|
||||
// 2.1 w = Hash (0x02 || V || additional_input).
|
||||
// 2.2 V = (V + w) mod 2^seedlen
|
||||
// .
|
||||
// 3. (returned_bits) = Hashgen (requested_number_of_bits, V).
|
||||
// 4. H = Hash (0x03 || V).
|
||||
// 5. V = (V + H + C + reseed_counter) mod 2^seedlen
|
||||
// .
|
||||
// 6. reseed_counter = reseed_counter + 1.
|
||||
// 7. Return SUCCESS, returned_bits, and the new values of V, C, and
|
||||
// reseed_counter for the new_working_state.
|
||||
int numberOfBits = output.Length * 8;
|
||||
|
||||
if (numberOfBits > MAX_BITS_REQUEST)
|
||||
throw new ArgumentException("Number of bits per request limited to " + MAX_BITS_REQUEST, "output");
|
||||
|
||||
if (mReseedCounter > RESEED_MAX)
|
||||
return -1;
|
||||
|
||||
if (predictionResistant)
|
||||
{
|
||||
Reseed(additionalInput);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 2.
|
||||
mDigest.Update(0x02);
|
||||
mDigest.BlockUpdate(mV);
|
||||
mDigest.BlockUpdate(additionalInput);
|
||||
|
||||
int digestSize = mDigest.GetDigestSize();
|
||||
Span<byte> w = digestSize <= 128
|
||||
? stackalloc byte[digestSize]
|
||||
: new byte[digestSize];
|
||||
mDigest.DoFinal(w);
|
||||
|
||||
AddTo(mV, w);
|
||||
}
|
||||
|
||||
return ImplGenerate(output);
|
||||
}
|
||||
|
||||
private int ImplGenerate(Span<byte> output)
|
||||
{
|
||||
// 3.
|
||||
Hashgen(mV, output);
|
||||
|
||||
// 4.
|
||||
mDigest.Update(0x03);
|
||||
mDigest.BlockUpdate(mV);
|
||||
|
||||
int digestSize = mDigest.GetDigestSize();
|
||||
Span<byte> H = digestSize <= 128
|
||||
? stackalloc byte[digestSize]
|
||||
: new byte[digestSize];
|
||||
mDigest.DoFinal(H);
|
||||
|
||||
// 5.
|
||||
AddTo(mV, H);
|
||||
AddTo(mV, mC);
|
||||
|
||||
Span<byte> c = stackalloc byte[4];
|
||||
Pack.UInt32_To_BE((uint)mReseedCounter, c);
|
||||
|
||||
AddTo(mV, c);
|
||||
|
||||
mReseedCounter++;
|
||||
|
||||
return output.Length * 8;
|
||||
}
|
||||
#endif
|
||||
|
||||
private byte[] GetEntropy()
|
||||
{
|
||||
byte[] entropy = mEntropySource.GetEntropy();
|
||||
if (entropy.Length < (mSecurityStrength + 7) / 8)
|
||||
throw new InvalidOperationException("Insufficient entropy provided by entropy source");
|
||||
return entropy;
|
||||
}
|
||||
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
private int GetEntropy(Span<byte> output)
|
||||
{
|
||||
int length = mEntropySource.GetEntropy(output);
|
||||
if (length < (mSecurityStrength + 7) / 8)
|
||||
throw new InvalidOperationException("Insufficient entropy provided by entropy source");
|
||||
return length;
|
||||
}
|
||||
|
||||
private int GetEntropyLength()
|
||||
{
|
||||
return (mEntropySource.EntropySize + 7) / 8;
|
||||
}
|
||||
#endif
|
||||
|
||||
// this will always add the shorter length byte array mathematically to the
|
||||
// longer length byte array.
|
||||
// be careful....
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
private void AddTo(Span<byte> longer, ReadOnlySpan<byte> shorter)
|
||||
#else
|
||||
private void AddTo(byte[] longer, byte[] shorter)
|
||||
#endif
|
||||
{
|
||||
int off = longer.Length - shorter.Length;
|
||||
|
||||
uint carry = 0;
|
||||
int i = shorter.Length;
|
||||
while (--i >= 0)
|
||||
{
|
||||
carry += (uint)longer[off + i] + shorter[i];
|
||||
longer[off + i] = (byte)carry;
|
||||
carry >>= 8;
|
||||
}
|
||||
|
||||
i = off;
|
||||
while (--i >= 0)
|
||||
{
|
||||
carry += longer[i];
|
||||
longer[i] = (byte)carry;
|
||||
carry >>= 8;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reseed the DRBG.
|
||||
*
|
||||
* @param additionalInput additional input to be added to the DRBG in this step.
|
||||
*/
|
||||
public void Reseed(byte[] additionalInput)
|
||||
{
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
Reseed(Spans.FromNullableReadOnly(additionalInput));
|
||||
#else
|
||||
// 1. seed_material = 0x01 || V || entropy_input || additional_input.
|
||||
//
|
||||
// 2. seed = Hash_df (seed_material, seedlen).
|
||||
//
|
||||
// 3. V = seed.
|
||||
//
|
||||
// 4. C = Hash_df ((0x00 || V), seedlen).
|
||||
//
|
||||
// 5. reseed_counter = 1.
|
||||
//
|
||||
// 6. Return V, C, and reseed_counter for the new_working_state.
|
||||
//
|
||||
// Comment: Precede with a byte of all zeros.
|
||||
byte[] entropy = GetEntropy();
|
||||
byte[] seedMaterial = Arrays.ConcatenateAll(ONE, mV, entropy, additionalInput);
|
||||
DrbgUtilities.HashDF(mDigest, seedMaterial, mSeedLength, mV);
|
||||
|
||||
byte[] subV = new byte[mV.Length + 1];
|
||||
subV[0] = 0x00;
|
||||
Array.Copy(mV, 0, subV, 1, mV.Length);
|
||||
DrbgUtilities.HashDF(mDigest, subV, mSeedLength, mC);
|
||||
|
||||
mReseedCounter = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
public void Reseed(ReadOnlySpan<byte> additionalInput)
|
||||
{
|
||||
// 1. seed_material = 0x01 || V || entropy_input || additional_input.
|
||||
//
|
||||
// 2. seed = Hash_df (seed_material, seedlen).
|
||||
//
|
||||
// 3. V = seed.
|
||||
//
|
||||
// 4. C = Hash_df ((0x00 || V), seedlen).
|
||||
//
|
||||
// 5. reseed_counter = 1.
|
||||
//
|
||||
// 6. Return V, C, and reseed_counter for the new_working_state.
|
||||
//
|
||||
// Comment: Precede with a byte of all zeros.
|
||||
int entropyLength = GetEntropyLength();
|
||||
|
||||
int seedMaterialLength = 1 + mV.Length + entropyLength + additionalInput.Length;
|
||||
Span<byte> seedMaterial = seedMaterialLength <= 256
|
||||
? stackalloc byte[seedMaterialLength]
|
||||
: new byte[seedMaterialLength];
|
||||
|
||||
seedMaterial[0] = 0x01;
|
||||
mV.CopyTo(seedMaterial[1..]);
|
||||
GetEntropy(seedMaterial[(1 + mV.Length)..]);
|
||||
additionalInput.CopyTo(seedMaterial[(1 + mV.Length + entropyLength)..]);
|
||||
|
||||
DrbgUtilities.HashDF(mDigest, seedMaterial, mSeedLength, mV);
|
||||
|
||||
int subVLength = 1 + mV.Length;
|
||||
Span<byte> subV = subVLength <= 128
|
||||
? stackalloc byte[subVLength]
|
||||
: new byte[subVLength];
|
||||
subV[0] = 0x00;
|
||||
mV.CopyTo(subV[1..]);
|
||||
|
||||
DrbgUtilities.HashDF(mDigest, subV, mSeedLength, mC);
|
||||
|
||||
mReseedCounter = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
private void DoHash(ReadOnlySpan<byte> input, Span<byte> output)
|
||||
{
|
||||
mDigest.BlockUpdate(input);
|
||||
mDigest.DoFinal(output);
|
||||
}
|
||||
#else
|
||||
private void DoHash(byte[] input, byte[] output)
|
||||
{
|
||||
mDigest.BlockUpdate(input, 0, input.Length);
|
||||
mDigest.DoFinal(output, 0);
|
||||
}
|
||||
|
||||
private byte[] Hash(byte[] input)
|
||||
{
|
||||
byte[] hash = new byte[mDigest.GetDigestSize()];
|
||||
DoHash(input, hash);
|
||||
return hash;
|
||||
}
|
||||
#endif
|
||||
|
||||
// 1. m = [requested_number_of_bits / outlen]
|
||||
// 2. data = V.
|
||||
// 3. W = the Null string.
|
||||
// 4. For i = 1 to m
|
||||
// 4.1 wi = Hash (data).
|
||||
// 4.2 W = W || wi.
|
||||
// 4.3 data = (data + 1) mod 2^seedlen
|
||||
// .
|
||||
// 5. returned_bits = Leftmost (requested_no_of_bits) bits of W.
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
private void Hashgen(ReadOnlySpan<byte> input, Span<byte> output)
|
||||
{
|
||||
int digestSize = mDigest.GetDigestSize();
|
||||
int m = output.Length / digestSize;
|
||||
|
||||
int dataSize = input.Length;
|
||||
Span<byte> data = dataSize <= 256
|
||||
? stackalloc byte[input.Length]
|
||||
: new byte[input.Length];
|
||||
input.CopyTo(data);
|
||||
|
||||
Span<byte> dig = digestSize <= 128
|
||||
? stackalloc byte[digestSize]
|
||||
: new byte[digestSize];
|
||||
|
||||
for (int i = 0; i <= m; i++)
|
||||
{
|
||||
DoHash(data, dig);
|
||||
|
||||
int bytesToCopy = System.Math.Min(digestSize, output.Length - i * digestSize);
|
||||
dig[..bytesToCopy].CopyTo(output[(i * digestSize)..]);
|
||||
AddTo(data, ONE);
|
||||
}
|
||||
}
|
||||
#else
|
||||
private byte[] Hashgen(byte[] input, int length)
|
||||
{
|
||||
int digestSize = mDigest.GetDigestSize();
|
||||
int m = length / digestSize;
|
||||
|
||||
byte[] data = (byte[])input.Clone();
|
||||
byte[] W = new byte[length];
|
||||
|
||||
byte[] dig = new byte[digestSize];
|
||||
for (int i = 0; i <= m; i++)
|
||||
{
|
||||
DoHash(data, dig);
|
||||
|
||||
int bytesToCopy = System.Math.Min(digestSize, length - i * digestSize);
|
||||
Array.Copy(dig, 0, W, i * digestSize, bytesToCopy);
|
||||
|
||||
AddTo(data, ONE);
|
||||
}
|
||||
|
||||
return W;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0107b79a063371b4e81b74d67d109eb0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
49
Packages/com.tivadar.best.http/Runtime/3rdParty/BouncyCastle/crypto/prng/drbg/ISP80090Drbg.cs
vendored
Normal file
49
Packages/com.tivadar.best.http/Runtime/3rdParty/BouncyCastle/crypto/prng/drbg/ISP80090Drbg.cs
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
|
||||
namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Prng.Drbg
|
||||
{
|
||||
/**
|
||||
* Interface to SP800-90A deterministic random bit generators.
|
||||
*/
|
||||
public interface ISP80090Drbg
|
||||
{
|
||||
/**
|
||||
* Return the block size of the DRBG.
|
||||
*
|
||||
* @return the block size (in bits) produced by each round of the DRBG.
|
||||
*/
|
||||
int BlockSize { get; }
|
||||
|
||||
/**
|
||||
* Populate a passed in array with random data.
|
||||
*
|
||||
* @param output output array for generated bits.
|
||||
* @param additionalInput additional input to be added to the DRBG in this step.
|
||||
* @param predictionResistant true if a reseed should be forced, false otherwise.
|
||||
*
|
||||
* @return number of bits generated, -1 if a reseed required.
|
||||
*/
|
||||
int Generate(byte[] output, int outputOff, int outputLen, byte[] additionalInput, bool predictionResistant);
|
||||
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
int Generate(Span<byte> output, bool predictionResistant);
|
||||
|
||||
int GenerateWithInput(Span<byte> output, ReadOnlySpan<byte> additionalInput, bool predictionResistant);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Reseed the DRBG.
|
||||
*
|
||||
* @param additionalInput additional input to be added to the DRBG in this step.
|
||||
*/
|
||||
void Reseed(byte[] additionalInput);
|
||||
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
void Reseed(ReadOnlySpan<byte> additionalInput);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3b5b62d297e2ef945ab39de2e2f84832
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user