2025-05-07 11:20:40 +08:00

138 lines
3.9 KiB
C#

#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
#pragma warning disable
using System;
using BestHTTP.SecureProtocol.Org.BouncyCastle.Security;
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Tls
{
/**
* A combined hash, which implements md5(m) || sha1(m).
*/
internal class CombinedHash
: TlsHandshakeHash
{
protected TlsContext mContext;
protected IDigest mMd5;
protected IDigest mSha1;
internal CombinedHash()
{
this.mMd5 = TlsUtilities.CreateHash(HashAlgorithm.md5);
this.mSha1 = TlsUtilities.CreateHash(HashAlgorithm.sha1);
}
internal CombinedHash(CombinedHash t)
{
this.mContext = t.mContext;
this.mMd5 = TlsUtilities.CloneHash(HashAlgorithm.md5, t.mMd5);
this.mSha1 = TlsUtilities.CloneHash(HashAlgorithm.sha1, t.mSha1);
}
public virtual void Init(TlsContext context)
{
this.mContext = context;
}
public virtual TlsHandshakeHash NotifyPrfDetermined()
{
return this;
}
public virtual void TrackHashAlgorithm(byte hashAlgorithm)
{
throw new InvalidOperationException("CombinedHash only supports calculating the legacy PRF for handshake hash");
}
public virtual void SealHashAlgorithms()
{
}
public virtual TlsHandshakeHash StopTracking()
{
return new CombinedHash(this);
}
public virtual IDigest ForkPrfHash()
{
return new CombinedHash(this);
}
public virtual byte[] GetFinalHash(byte hashAlgorithm)
{
throw new InvalidOperationException("CombinedHash doesn't support multiple hashes");
}
public virtual string AlgorithmName
{
get { return mMd5.AlgorithmName + " and " + mSha1.AlgorithmName; }
}
public virtual int GetByteLength()
{
return System.Math.Max(mMd5.GetByteLength(), mSha1.GetByteLength());
}
public virtual int GetDigestSize()
{
return mMd5.GetDigestSize() + mSha1.GetDigestSize();
}
public virtual void Update(byte input)
{
mMd5.Update(input);
mSha1.Update(input);
}
/**
* @see org.bouncycastle.crypto.Digest#update(byte[], int, int)
*/
public virtual void BlockUpdate(byte[] input, int inOff, int len)
{
mMd5.BlockUpdate(input, inOff, len);
mSha1.BlockUpdate(input, inOff, len);
}
/**
* @see org.bouncycastle.crypto.Digest#doFinal(byte[], int)
*/
public virtual int DoFinal(byte[] output, int outOff)
{
if (mContext != null && TlsUtilities.IsSsl(mContext))
{
Ssl3Complete(mMd5, Ssl3Mac.IPAD, Ssl3Mac.OPAD, 48);
Ssl3Complete(mSha1, Ssl3Mac.IPAD, Ssl3Mac.OPAD, 40);
}
int i1 = mMd5.DoFinal(output, outOff);
int i2 = mSha1.DoFinal(output, outOff + i1);
return i1 + i2;
}
/**
* @see org.bouncycastle.crypto.Digest#reset()
*/
public virtual void Reset()
{
mMd5.Reset();
mSha1.Reset();
}
protected virtual void Ssl3Complete(IDigest d, byte[] ipad, byte[] opad, int padLength)
{
byte[] master_secret = mContext.SecurityParameters.masterSecret;
d.BlockUpdate(master_secret, 0, master_secret.Length);
d.BlockUpdate(ipad, 0, padLength);
byte[] tmp = DigestUtilities.DoFinal(d);
d.BlockUpdate(master_secret, 0, master_secret.Length);
d.BlockUpdate(opad, 0, padLength);
d.BlockUpdate(tmp, 0, tmp.Length);
}
}
}
#pragma warning restore
#endif