- Initial commit
This commit is contained in:
180
Runtime/3rdParty/BouncyCastle/crypto/generators/HKDFBytesGenerator.cs
vendored
Normal file
180
Runtime/3rdParty/BouncyCastle/crypto/generators/HKDFBytesGenerator.cs
vendored
Normal file
@ -0,0 +1,180 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Macs;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Utilities;
|
||||
|
||||
namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Generators
|
||||
{
|
||||
/**
|
||||
* HMAC-based Extract-and-Expand Key Derivation Function (HKDF) implemented
|
||||
* according to IETF RFC 5869, May 2010 as specified by H. Krawczyk, IBM
|
||||
* Research & P. Eronen, Nokia. It uses a HMac internally to compute de OKM
|
||||
* (output keying material) and is likely to have better security properties
|
||||
* than KDF's based on just a hash function.
|
||||
*/
|
||||
public sealed class HkdfBytesGenerator
|
||||
: IDerivationFunction
|
||||
{
|
||||
private HMac hMacHash;
|
||||
private int hashLen;
|
||||
|
||||
private byte[] info;
|
||||
private byte[] currentT;
|
||||
|
||||
private int generatedBytes;
|
||||
|
||||
/**
|
||||
* Creates a HKDFBytesGenerator based on the given hash function.
|
||||
*
|
||||
* @param hash the digest to be used as the source of generatedBytes bytes
|
||||
*/
|
||||
public HkdfBytesGenerator(IDigest hash)
|
||||
{
|
||||
this.hMacHash = new HMac(hash);
|
||||
this.hashLen = hash.GetDigestSize();
|
||||
}
|
||||
|
||||
public void Init(IDerivationParameters parameters)
|
||||
{
|
||||
if (!(parameters is HkdfParameters hkdfParameters))
|
||||
throw new ArgumentException("HKDF parameters required for HkdfBytesGenerator", "parameters");
|
||||
|
||||
if (hkdfParameters.SkipExtract)
|
||||
{
|
||||
// use IKM directly as PRK
|
||||
hMacHash.Init(new KeyParameter(hkdfParameters.GetIkm()));
|
||||
}
|
||||
else
|
||||
{
|
||||
hMacHash.Init(Extract(hkdfParameters.GetSalt(), hkdfParameters.GetIkm()));
|
||||
}
|
||||
|
||||
info = hkdfParameters.GetInfo();
|
||||
|
||||
generatedBytes = 0;
|
||||
currentT = new byte[hashLen];
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the extract part of the key derivation function.
|
||||
*
|
||||
* @param salt the salt to use
|
||||
* @param ikm the input keying material
|
||||
* @return the PRK as KeyParameter
|
||||
*/
|
||||
private KeyParameter Extract(byte[] salt, byte[] ikm)
|
||||
{
|
||||
if (salt == null)
|
||||
{
|
||||
// TODO check if hashLen is indeed same as HMAC size
|
||||
hMacHash.Init(new KeyParameter(new byte[hashLen]));
|
||||
}
|
||||
else
|
||||
{
|
||||
hMacHash.Init(new KeyParameter(salt));
|
||||
}
|
||||
|
||||
hMacHash.BlockUpdate(ikm, 0, ikm.Length);
|
||||
|
||||
byte[] prk = new byte[hashLen];
|
||||
hMacHash.DoFinal(prk, 0);
|
||||
return new KeyParameter(prk);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the expand part of the key derivation function, using currentT
|
||||
* as input and output buffer.
|
||||
*
|
||||
* @throws DataLengthException if the total number of bytes generated is larger than the one
|
||||
* specified by RFC 5869 (255 * HashLen)
|
||||
*/
|
||||
private void ExpandNext()
|
||||
{
|
||||
int n = generatedBytes / hashLen + 1;
|
||||
if (n >= 256)
|
||||
{
|
||||
throw new DataLengthException(
|
||||
"HKDF cannot generate more than 255 blocks of HashLen size");
|
||||
}
|
||||
// special case for T(0): T(0) is empty, so no update
|
||||
if (generatedBytes != 0)
|
||||
{
|
||||
hMacHash.BlockUpdate(currentT, 0, hashLen);
|
||||
}
|
||||
hMacHash.BlockUpdate(info, 0, info.Length);
|
||||
hMacHash.Update((byte)n);
|
||||
hMacHash.DoFinal(currentT, 0);
|
||||
}
|
||||
|
||||
public IDigest Digest => hMacHash.GetUnderlyingDigest();
|
||||
|
||||
public int GenerateBytes(byte[] output, int outOff, int length)
|
||||
{
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
return GenerateBytes(output.AsSpan(outOff, length));
|
||||
#else
|
||||
if (generatedBytes > 255 * hashLen - length)
|
||||
throw new DataLengthException("HKDF may only be used for 255 * HashLen bytes of output");
|
||||
|
||||
int toGenerate = length;
|
||||
int posInT = generatedBytes % hashLen;
|
||||
if (posInT != 0)
|
||||
{
|
||||
// copy what is left in the currentT (1..hash
|
||||
int toCopy = System.Math.Min(hashLen - posInT, toGenerate);
|
||||
Array.Copy(currentT, posInT, output, outOff, toCopy);
|
||||
generatedBytes += toCopy;
|
||||
toGenerate -= toCopy;
|
||||
outOff += toCopy;
|
||||
}
|
||||
|
||||
while (toGenerate > 0)
|
||||
{
|
||||
ExpandNext();
|
||||
int toCopy = System.Math.Min(hashLen, toGenerate);
|
||||
Array.Copy(currentT, 0, output, outOff, toCopy);
|
||||
generatedBytes += toCopy;
|
||||
toGenerate -= toCopy;
|
||||
outOff += toCopy;
|
||||
}
|
||||
|
||||
return length;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
public int GenerateBytes(Span<byte> output)
|
||||
{
|
||||
int length = output.Length;
|
||||
if (generatedBytes > 255 * hashLen - length)
|
||||
throw new DataLengthException("HKDF may only be used for 255 * HashLen bytes of output");
|
||||
|
||||
int posInT = generatedBytes % hashLen;
|
||||
if (posInT != 0)
|
||||
{
|
||||
// copy what is left in the currentT (1..hash
|
||||
int toCopy = System.Math.Min(hashLen - posInT, output.Length);
|
||||
currentT.AsSpan(posInT, toCopy).CopyTo(output);
|
||||
generatedBytes += toCopy;
|
||||
output = output[toCopy..];
|
||||
}
|
||||
|
||||
while (!output.IsEmpty)
|
||||
{
|
||||
ExpandNext();
|
||||
int toCopy = System.Math.Min(hashLen, output.Length);
|
||||
currentT.AsSpan(0, toCopy).CopyTo(output);
|
||||
generatedBytes += toCopy;
|
||||
output = output[toCopy..];
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
Reference in New Issue
Block a user