mirror of
https://github.com/adamhathcock/sharpcompress.git
synced 2026-02-14 05:25:41 +00:00
135 lines
3.2 KiB
C#
135 lines
3.2 KiB
C#
using System;
|
|
using System.Collections;
|
|
|
|
using Org.BouncyCastle.Crypto;
|
|
using Org.BouncyCastle.Crypto.Parameters;
|
|
|
|
namespace Org.BouncyCastle.Crypto.Macs
|
|
{
|
|
/**
|
|
* HMAC implementation based on RFC2104
|
|
*
|
|
* H(K XOR opad, H(K XOR ipad, text))
|
|
*/
|
|
public class HMac
|
|
: IMac
|
|
{
|
|
private const byte IPAD = (byte)0x36;
|
|
private const byte OPAD = (byte)0x5C;
|
|
|
|
private readonly IDigest digest;
|
|
private readonly int digestSize;
|
|
private readonly int blockLength;
|
|
|
|
private readonly byte[] inputPad;
|
|
private readonly byte[] outputPad;
|
|
|
|
public HMac(
|
|
IDigest digest)
|
|
{
|
|
this.digest = digest;
|
|
this.digestSize = digest.GetDigestSize();
|
|
this.blockLength = digest.GetByteLength();
|
|
this.inputPad = new byte[blockLength];
|
|
this.outputPad = new byte[blockLength];
|
|
}
|
|
|
|
public string AlgorithmName
|
|
{
|
|
get { return digest.AlgorithmName + "/HMAC"; }
|
|
}
|
|
|
|
public IDigest GetUnderlyingDigest()
|
|
{
|
|
return digest;
|
|
}
|
|
|
|
public void Init(
|
|
ICipherParameters parameters)
|
|
{
|
|
digest.Reset();
|
|
|
|
byte[] key = ((KeyParameter)parameters).GetKey();
|
|
int keyLength = key.Length;
|
|
|
|
if (keyLength > blockLength)
|
|
{
|
|
digest.BlockUpdate(key, 0, key.Length);
|
|
digest.DoFinal(inputPad, 0);
|
|
|
|
keyLength = digestSize;
|
|
}
|
|
else
|
|
{
|
|
Array.Copy(key, 0, inputPad, 0, keyLength);
|
|
}
|
|
|
|
Array.Clear(inputPad, keyLength, blockLength - keyLength);
|
|
Array.Copy(inputPad, 0, outputPad, 0, blockLength);
|
|
|
|
xor(inputPad, IPAD);
|
|
xor(outputPad, OPAD);
|
|
|
|
// Initialise the digest
|
|
digest.BlockUpdate(inputPad, 0, inputPad.Length);
|
|
}
|
|
|
|
public int GetMacSize()
|
|
{
|
|
return digestSize;
|
|
}
|
|
|
|
public void Update(
|
|
byte input)
|
|
{
|
|
digest.Update(input);
|
|
}
|
|
|
|
public void BlockUpdate(
|
|
byte[] input,
|
|
int inOff,
|
|
int len)
|
|
{
|
|
digest.BlockUpdate(input, inOff, len);
|
|
}
|
|
|
|
public int DoFinal(
|
|
byte[] output,
|
|
int outOff)
|
|
{
|
|
byte[] tmp = new byte[digestSize];
|
|
digest.DoFinal(tmp, 0);
|
|
|
|
digest.BlockUpdate(outputPad, 0, outputPad.Length);
|
|
digest.BlockUpdate(tmp, 0, tmp.Length);
|
|
|
|
int len = digest.DoFinal(output, outOff);
|
|
|
|
// Initialise the digest
|
|
digest.BlockUpdate(inputPad, 0, inputPad.Length);
|
|
|
|
return len;
|
|
}
|
|
|
|
/**
|
|
* Reset the mac generator.
|
|
*/
|
|
public void Reset()
|
|
{
|
|
// Reset underlying digest
|
|
digest.Reset();
|
|
|
|
// Initialise the digest
|
|
digest.BlockUpdate(inputPad, 0, inputPad.Length);
|
|
}
|
|
|
|
private static void xor(byte[] a, byte n)
|
|
{
|
|
for (int i = 0; i < a.Length; ++i)
|
|
{
|
|
a[i] ^= n;
|
|
}
|
|
}
|
|
}
|
|
}
|