Initial Commit
This commit is contained in:
23
iTechSharp/srcbc/crypto/tls/AlwaysValidVerifyer.cs
Normal file
23
iTechSharp/srcbc/crypto/tls/AlwaysValidVerifyer.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using System;
|
||||
|
||||
using Org.BouncyCastle.Asn1.X509;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls
|
||||
{
|
||||
/// <remarks>
|
||||
/// A certificate verifyer, that will always return true.
|
||||
/// <pre>
|
||||
/// DO NOT USE THIS FILE UNLESS YOU KNOW EXACTLY WHAT YOU ARE DOING.
|
||||
/// </pre>
|
||||
/// </remarks>
|
||||
public class AlwaysValidVerifyer
|
||||
: ICertificateVerifyer
|
||||
{
|
||||
/// <summary>Return true.</summary>
|
||||
public bool IsValid(
|
||||
X509CertificateStructure[] certs)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
125
iTechSharp/srcbc/crypto/tls/ByteQueue.cs
Normal file
125
iTechSharp/srcbc/crypto/tls/ByteQueue.cs
Normal file
@@ -0,0 +1,125 @@
|
||||
using System;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls
|
||||
{
|
||||
/// <remarks>
|
||||
/// A queue for bytes.
|
||||
/// <p>
|
||||
/// This file could be more optimized.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
public class ByteQueue
|
||||
{
|
||||
/// <returns>The smallest number which can be written as 2^x which is bigger than i.</returns>
|
||||
public static int NextTwoPow(
|
||||
int i)
|
||||
{
|
||||
/*
|
||||
* This code is based of a lot of code I found on the Internet
|
||||
* which mostly referenced a book called "Hacking delight".
|
||||
*
|
||||
*/
|
||||
i |= (i >> 1);
|
||||
i |= (i >> 2);
|
||||
i |= (i >> 4);
|
||||
i |= (i >> 8);
|
||||
i |= (i >> 16);
|
||||
return i + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* The initial size for our buffer.
|
||||
*/
|
||||
private const int InitBufSize = 1024;
|
||||
|
||||
/**
|
||||
* The buffer where we store our data.
|
||||
*/
|
||||
private byte[] databuf = new byte[ByteQueue.InitBufSize];
|
||||
|
||||
/**
|
||||
* How many bytes at the beginning of the buffer are skipped.
|
||||
*/
|
||||
private int skipped = 0;
|
||||
|
||||
/**
|
||||
* How many bytes in the buffer are valid data.
|
||||
*/
|
||||
private int available = 0;
|
||||
|
||||
/// <summary>Read data from the buffer.</summary>
|
||||
/// <param name="buf">The buffer where the read data will be copied to.</param>
|
||||
/// <param name="offset">How many bytes to skip at the beginning of buf.</param>
|
||||
/// <param name="len">How many bytes to read at all.</param>
|
||||
/// <param name="skip">How many bytes from our data to skip.</param>
|
||||
public void Read(
|
||||
byte[] buf,
|
||||
int offset,
|
||||
int len,
|
||||
int skip)
|
||||
{
|
||||
if ((available - skip) < len)
|
||||
{
|
||||
throw new TlsException("Not enough data to read");
|
||||
}
|
||||
if ((buf.Length - offset) < len)
|
||||
{
|
||||
throw new TlsException("Buffer size of " + buf.Length + " is too small for a read of " + len + " bytes");
|
||||
}
|
||||
Array.Copy(databuf, skipped + skip, buf, offset, len);
|
||||
}
|
||||
|
||||
/// <summary>Add some data to our buffer.</summary>
|
||||
/// <param name="data">A byte-array to read data from.</param>
|
||||
/// <param name="offset">How many bytes to skip at the beginning of the array.</param>
|
||||
/// <param name="len">How many bytes to read from the array.</param>
|
||||
public void AddData(
|
||||
byte[] data,
|
||||
int offset,
|
||||
int len)
|
||||
{
|
||||
if ((skipped + available + len) > databuf.Length)
|
||||
{
|
||||
byte[] tmp = new byte[ByteQueue.NextTwoPow(data.Length)];
|
||||
Array.Copy(databuf, skipped, tmp, 0, available);
|
||||
skipped = 0;
|
||||
databuf = tmp;
|
||||
}
|
||||
Array.Copy(data, offset, databuf, skipped + available, len);
|
||||
available += len;
|
||||
}
|
||||
|
||||
/// <summary>Remove some bytes from our data from the beginning.</summary>
|
||||
/// <param name="i">How many bytes to remove.</param>
|
||||
public void RemoveData(
|
||||
int i)
|
||||
{
|
||||
if (i > available)
|
||||
{
|
||||
throw new TlsException("Cannot remove " + i + " bytes, only got " + available);
|
||||
}
|
||||
|
||||
/*
|
||||
* Skip the data.
|
||||
*/
|
||||
available -= i;
|
||||
skipped += i;
|
||||
|
||||
/*
|
||||
* If more than half of our data is skipped, we will move the data
|
||||
* in the buffer.
|
||||
*/
|
||||
if (skipped > (databuf.Length / 2))
|
||||
{
|
||||
Array.Copy(databuf, skipped, databuf, 0, available);
|
||||
skipped = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>The number of bytes which are available in this buffer.</summary>
|
||||
public int Available
|
||||
{
|
||||
get { return available; }
|
||||
}
|
||||
}
|
||||
}
|
78
iTechSharp/srcbc/crypto/tls/Certificate.cs
Normal file
78
iTechSharp/srcbc/crypto/tls/Certificate.cs
Normal file
@@ -0,0 +1,78 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
|
||||
using Org.BouncyCastle.Asn1;
|
||||
using Org.BouncyCastle.Asn1.X509;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls
|
||||
{
|
||||
/**
|
||||
* A representation for a certificate chain as used by an tls server.
|
||||
*/
|
||||
public class Certificate
|
||||
{
|
||||
/**
|
||||
* The certificates.
|
||||
*/
|
||||
internal X509CertificateStructure[] certs;
|
||||
|
||||
/**
|
||||
* Parse the ServerCertificate message.
|
||||
*
|
||||
* @param is The stream where to parse from.
|
||||
* @return A Certificate object with the certs, the server has sended.
|
||||
* @throws IOException If something goes wrong during parsing.
|
||||
*/
|
||||
internal static Certificate Parse(
|
||||
Stream inStr)
|
||||
{
|
||||
X509CertificateStructure[] certs;
|
||||
int left = TlsUtilities.ReadUint24(inStr);
|
||||
ArrayList tmp = new ArrayList();
|
||||
while (left > 0)
|
||||
{
|
||||
int size = TlsUtilities.ReadUint24(inStr);
|
||||
left -= 3 + size;
|
||||
byte[] buf = new byte[size];
|
||||
TlsUtilities.ReadFully(buf, inStr);
|
||||
MemoryStream bis = new MemoryStream(buf, false);
|
||||
Asn1InputStream ais = new Asn1InputStream(bis);
|
||||
Asn1Object o = ais.ReadObject();
|
||||
tmp.Add(X509CertificateStructure.GetInstance(o));
|
||||
// if (bis.available() > 0)
|
||||
if (bis.Position < bis.Length)
|
||||
{
|
||||
throw new ArgumentException("Sorry, there is garbage data left after the certificate");
|
||||
}
|
||||
}
|
||||
// certs = new X509CertificateStructure[tmp.size()];
|
||||
// for (int i = 0; i < tmp.size(); i++)
|
||||
// {
|
||||
// certs[i] = (X509CertificateStructure)tmp.elementAt(i);
|
||||
// }
|
||||
certs = (X509CertificateStructure[]) tmp.ToArray(typeof(X509CertificateStructure));
|
||||
return new Certificate(certs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Private constructure from an cert array.
|
||||
*
|
||||
* @param certs The certs the chain should contain.
|
||||
*/
|
||||
private Certificate(
|
||||
X509CertificateStructure[] certs)
|
||||
{
|
||||
this.certs = certs;
|
||||
}
|
||||
|
||||
/// <returns>An array which contains the certs, this chain contains.</returns>
|
||||
public X509CertificateStructure[] GetCerts()
|
||||
{
|
||||
// X509CertificateStructure[] result = new X509CertificateStructure[certs.Length];
|
||||
// Array.Copy(certs, 0, result, 0, certs.Length);
|
||||
// return result;
|
||||
return (X509CertificateStructure[]) certs.Clone();
|
||||
}
|
||||
}
|
||||
}
|
70
iTechSharp/srcbc/crypto/tls/CombinedHash.cs
Normal file
70
iTechSharp/srcbc/crypto/tls/CombinedHash.cs
Normal file
@@ -0,0 +1,70 @@
|
||||
using System;
|
||||
|
||||
using Org.BouncyCastle.Crypto.Digests;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls
|
||||
{
|
||||
/// <remarks>A combined hash, which implements md5(m) || sha1(m).</remarks>
|
||||
public class CombinedHash
|
||||
: IDigest
|
||||
{
|
||||
private IDigest md5 = new MD5Digest();
|
||||
private IDigest sha1 = new Sha1Digest();
|
||||
|
||||
/// <seealso cref="IDigest.AlgorithmName"/>
|
||||
public string AlgorithmName
|
||||
{
|
||||
get
|
||||
{
|
||||
return md5.AlgorithmName + " and " + sha1.AlgorithmName + " for TLS 1.0";
|
||||
}
|
||||
}
|
||||
|
||||
/// <seealso cref="IDigest.GetByteLength"/>
|
||||
public int GetByteLength()
|
||||
{
|
||||
return System.Math.Max(md5.GetByteLength(), sha1.GetByteLength());
|
||||
}
|
||||
|
||||
/// <seealso cref="IDigest.GetDigestSize"/>
|
||||
public int GetDigestSize()
|
||||
{
|
||||
return md5.GetDigestSize() + sha1.GetDigestSize();
|
||||
}
|
||||
|
||||
/// <seealso cref="IDigest.Update"/>
|
||||
public void Update(
|
||||
byte input)
|
||||
{
|
||||
md5.Update(input);
|
||||
sha1.Update(input);
|
||||
}
|
||||
|
||||
/// <seealso cref="IDigest.BlockUpdate"/>
|
||||
public void BlockUpdate(
|
||||
byte[] input,
|
||||
int inOff,
|
||||
int len)
|
||||
{
|
||||
md5.BlockUpdate(input, inOff, len);
|
||||
sha1.BlockUpdate(input, inOff, len);
|
||||
}
|
||||
|
||||
/// <seealso cref="IDigest.DoFinal"/>
|
||||
public int DoFinal(
|
||||
byte[] output,
|
||||
int outOff)
|
||||
{
|
||||
int i1 = md5.DoFinal(output, outOff);
|
||||
int i2 = sha1.DoFinal(output, outOff + i1);
|
||||
return i1 + i2;
|
||||
}
|
||||
|
||||
/// <seealso cref="IDigest.Reset"/>
|
||||
public void Reset()
|
||||
{
|
||||
md5.Reset();
|
||||
sha1.Reset();
|
||||
}
|
||||
}
|
||||
}
|
17
iTechSharp/srcbc/crypto/tls/ICertificateVerifyer.cs
Normal file
17
iTechSharp/srcbc/crypto/tls/ICertificateVerifyer.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using System;
|
||||
|
||||
using Org.BouncyCastle.Asn1.X509;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls
|
||||
{
|
||||
/// <remarks>
|
||||
/// This should be implemented by any class which can find out, if a given
|
||||
/// certificate chain is beeing accepted by an client.
|
||||
/// </remarks>
|
||||
public interface ICertificateVerifyer
|
||||
{
|
||||
/// <param name="certs">The certs, which are part of the chain.</param>
|
||||
/// <returns>True, if the chain is accepted, false otherwise</returns>
|
||||
bool IsValid(X509CertificateStructure[] certs);
|
||||
}
|
||||
}
|
107
iTechSharp/srcbc/crypto/tls/RecordStream.cs
Normal file
107
iTechSharp/srcbc/crypto/tls/RecordStream.cs
Normal file
@@ -0,0 +1,107 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls
|
||||
{
|
||||
/// <remarks>An implementation of the TLS 1.0 record layer.</remarks>
|
||||
public class RecordStream
|
||||
{
|
||||
private TlsProtocolHandler handler;
|
||||
private Stream inStr;
|
||||
private Stream outStr;
|
||||
internal CombinedHash hash1;
|
||||
internal CombinedHash hash2;
|
||||
internal TlsCipherSuite readSuite = null;
|
||||
internal TlsCipherSuite writeSuite = null;
|
||||
|
||||
internal RecordStream(
|
||||
TlsProtocolHandler handler,
|
||||
Stream inStr,
|
||||
Stream outStr)
|
||||
{
|
||||
this.handler = handler;
|
||||
this.inStr = inStr;
|
||||
this.outStr = outStr;
|
||||
hash1 = new CombinedHash();
|
||||
hash2 = new CombinedHash();
|
||||
this.readSuite = new TlsNullCipherSuite();
|
||||
this.writeSuite = this.readSuite;
|
||||
}
|
||||
|
||||
public void ReadData()
|
||||
{
|
||||
short type = TlsUtilities.ReadUint8(inStr);
|
||||
TlsUtilities.CheckVersion(inStr, handler);
|
||||
int size = TlsUtilities.ReadUint16(inStr);
|
||||
byte[] buf = DecodeAndVerify(type, inStr, size);
|
||||
handler.ProcessData(type, buf, 0, buf.Length);
|
||||
|
||||
}
|
||||
|
||||
internal byte[] DecodeAndVerify(
|
||||
short type,
|
||||
Stream inStr,
|
||||
int len)
|
||||
{
|
||||
byte[] buf = new byte[len];
|
||||
TlsUtilities.ReadFully(buf, inStr);
|
||||
byte[] result = readSuite.DecodeCiphertext(type, buf, 0, buf.Length, handler);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal void WriteMessage(
|
||||
short type,
|
||||
byte[] message,
|
||||
int offset,
|
||||
int len)
|
||||
{
|
||||
if (type == 22)
|
||||
{
|
||||
hash1.BlockUpdate(message, offset, len);
|
||||
hash2.BlockUpdate(message, offset, len);
|
||||
}
|
||||
byte[] ciphertext = writeSuite.EncodePlaintext(type, message, offset, len);
|
||||
byte[] writeMessage = new byte[ciphertext.Length + 5];
|
||||
TlsUtilities.WriteUint8(type, writeMessage, 0);
|
||||
TlsUtilities.WriteUint8((short)3, writeMessage, 1);
|
||||
TlsUtilities.WriteUint8((short)1, writeMessage, 2);
|
||||
TlsUtilities.WriteUint16(ciphertext.Length, writeMessage, 3);
|
||||
Array.Copy(ciphertext, 0, writeMessage, 5, ciphertext.Length);
|
||||
outStr.Write(writeMessage, 0, writeMessage.Length);
|
||||
outStr.Flush();
|
||||
}
|
||||
|
||||
internal void Close()
|
||||
{
|
||||
IOException e = null;
|
||||
try
|
||||
{
|
||||
inStr.Close();
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
e = ex;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// NB: This is harmless if outStr == inStr
|
||||
outStr.Close();
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
e = ex;
|
||||
}
|
||||
|
||||
if (e != null)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
internal void Flush()
|
||||
{
|
||||
outStr.Flush();
|
||||
}
|
||||
}
|
||||
}
|
196
iTechSharp/srcbc/crypto/tls/TlsBlockCipherCipherSuite.cs
Normal file
196
iTechSharp/srcbc/crypto/tls/TlsBlockCipherCipherSuite.cs
Normal file
@@ -0,0 +1,196 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
using Org.BouncyCastle.Crypto.Digests;
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls
|
||||
{
|
||||
/// <remarks>A generic TLS 1.0 block cipher suite. This can be used for AES or 3DES for example.</remarks>
|
||||
public class TlsBlockCipherCipherSuite
|
||||
: TlsCipherSuite
|
||||
{
|
||||
private IBlockCipher encryptCipher;
|
||||
|
||||
private IBlockCipher decryptCipher;
|
||||
|
||||
private IDigest writeDigest;
|
||||
|
||||
private IDigest readDigest;
|
||||
|
||||
private int cipherKeySize;
|
||||
|
||||
private short keyExchange;
|
||||
|
||||
private TlsMac writeMac;
|
||||
|
||||
private TlsMac readMac;
|
||||
|
||||
internal TlsBlockCipherCipherSuite(
|
||||
IBlockCipher encrypt,
|
||||
IBlockCipher decrypt,
|
||||
IDigest writeDigest,
|
||||
IDigest readDigest,
|
||||
int cipherKeySize,
|
||||
short keyExchange)
|
||||
{
|
||||
this.encryptCipher = encrypt;
|
||||
this.decryptCipher = decrypt;
|
||||
this.writeDigest = writeDigest;
|
||||
this.readDigest = readDigest;
|
||||
this.cipherKeySize = cipherKeySize;
|
||||
this.keyExchange = keyExchange;
|
||||
}
|
||||
|
||||
internal override void Init(byte[] ms, byte[] cr, byte[] sr)
|
||||
{
|
||||
int prfSize = (2 * cipherKeySize) + (2 * writeDigest.GetDigestSize())
|
||||
+ (2 * encryptCipher.GetBlockSize());
|
||||
byte[] key_block = new byte[prfSize];
|
||||
byte[] random = new byte[cr.Length + sr.Length];
|
||||
Array.Copy(cr, 0, random, sr.Length, cr.Length);
|
||||
Array.Copy(sr, 0, random, 0, sr.Length);
|
||||
TlsUtilities.PRF(ms, TlsUtilities.ToByteArray("key expansion"), random, key_block);
|
||||
|
||||
int offset = 0;
|
||||
|
||||
// Init MACs
|
||||
writeMac = new TlsMac(writeDigest, key_block, offset, writeDigest
|
||||
.GetDigestSize());
|
||||
offset += writeDigest.GetDigestSize();
|
||||
readMac = new TlsMac(readDigest, key_block, offset, readDigest
|
||||
.GetDigestSize());
|
||||
offset += readDigest.GetDigestSize();
|
||||
|
||||
// Init Ciphers
|
||||
this.initCipher(true, encryptCipher, key_block, cipherKeySize, offset,
|
||||
offset + (cipherKeySize * 2));
|
||||
offset += cipherKeySize;
|
||||
this.initCipher(false, decryptCipher, key_block, cipherKeySize, offset,
|
||||
offset + cipherKeySize + decryptCipher.GetBlockSize());
|
||||
}
|
||||
|
||||
private void initCipher(bool forEncryption, IBlockCipher cipher,
|
||||
byte[] key_block, int key_size, int key_offset, int iv_offset)
|
||||
{
|
||||
KeyParameter key_parameter = new KeyParameter(key_block, key_offset,
|
||||
key_size);
|
||||
ParametersWithIV parameters_with_iv = new ParametersWithIV(
|
||||
key_parameter, key_block, iv_offset, cipher.GetBlockSize());
|
||||
cipher.Init(forEncryption, parameters_with_iv);
|
||||
}
|
||||
|
||||
internal override byte[] EncodePlaintext(
|
||||
short type,
|
||||
byte[] plaintext,
|
||||
int offset,
|
||||
int len)
|
||||
{
|
||||
int blocksize = encryptCipher.GetBlockSize();
|
||||
int paddingsize = blocksize
|
||||
- ((len + writeMac.Size + 1) % blocksize);
|
||||
int totalsize = len + writeMac.Size + paddingsize + 1;
|
||||
byte[] outbuf = new byte[totalsize];
|
||||
Array.Copy(plaintext, offset, outbuf, 0, len);
|
||||
byte[] mac = writeMac.CalculateMac(type, plaintext, offset, len);
|
||||
Array.Copy(mac, 0, outbuf, len, mac.Length);
|
||||
int paddoffset = len + mac.Length;
|
||||
for (int i = 0; i <= paddingsize; i++)
|
||||
{
|
||||
outbuf[i + paddoffset] = (byte)paddingsize;
|
||||
}
|
||||
for (int i = 0; i < totalsize; i += blocksize)
|
||||
{
|
||||
encryptCipher.ProcessBlock(outbuf, i, outbuf, i);
|
||||
}
|
||||
return outbuf;
|
||||
}
|
||||
|
||||
internal override byte[] DecodeCiphertext(
|
||||
short type,
|
||||
byte[] ciphertext,
|
||||
int offset,
|
||||
int len,
|
||||
TlsProtocolHandler handler)
|
||||
{
|
||||
int blocksize = decryptCipher.GetBlockSize();
|
||||
bool decrypterror = false;
|
||||
|
||||
/*
|
||||
* Decrypt all the ciphertext using the blockcipher
|
||||
*/
|
||||
for (int i = 0; i < len; i += blocksize)
|
||||
{
|
||||
decryptCipher.ProcessBlock(ciphertext, i + offset, ciphertext, i
|
||||
+ offset);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if padding is correct
|
||||
*/
|
||||
int paddingsize = ciphertext[offset + len - 1];
|
||||
if (offset + len - 1 - paddingsize < 0)
|
||||
{
|
||||
/*
|
||||
* This would lead to an negativ array index, so this padding
|
||||
* must be incorrect!
|
||||
*/
|
||||
decrypterror = true;
|
||||
paddingsize = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Now, check all the padding-bytes.
|
||||
*/
|
||||
for (int i = 0; i <= paddingsize; i++)
|
||||
{
|
||||
if (ciphertext[offset + len - 1 - i] != paddingsize)
|
||||
{
|
||||
/* Wrong padding */
|
||||
decrypterror = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We now don't care if padding verification has failed or not,
|
||||
* we will calculate the mac to give an attacker no kind of timing
|
||||
* profile he can use to find out if mac verification failed or
|
||||
* padding verification failed.
|
||||
*/
|
||||
int plaintextlength = len - readMac.Size - paddingsize - 1;
|
||||
byte[] calculatedMac = readMac.CalculateMac(type, ciphertext, offset,
|
||||
plaintextlength);
|
||||
|
||||
/*
|
||||
* Check all bytes in the mac.
|
||||
*/
|
||||
for (int i = 0; i < calculatedMac.Length; i++)
|
||||
{
|
||||
if (ciphertext[offset + plaintextlength + i] != calculatedMac[i])
|
||||
{
|
||||
decrypterror = true;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Now, it is save to fail.
|
||||
*/
|
||||
if (decrypterror)
|
||||
{
|
||||
handler.FailWithError(TlsProtocolHandler.AL_fatal,
|
||||
TlsProtocolHandler.AP_bad_record_mac);
|
||||
}
|
||||
byte[] plaintext = new byte[plaintextlength];
|
||||
Array.Copy(ciphertext, offset, plaintext, 0, plaintextlength);
|
||||
return plaintext;
|
||||
|
||||
}
|
||||
|
||||
internal override short KeyExchangeAlgorithm
|
||||
{
|
||||
get { return this.keyExchange; }
|
||||
}
|
||||
}
|
||||
}
|
26
iTechSharp/srcbc/crypto/tls/TlsCipherSuite.cs
Normal file
26
iTechSharp/srcbc/crypto/tls/TlsCipherSuite.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using System;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls
|
||||
{
|
||||
/// <remarks>A generic class for ciphersuites in TLS 1.0.</remarks>
|
||||
public abstract class TlsCipherSuite
|
||||
{
|
||||
internal const short KE_RSA = 1;
|
||||
internal const short KE_RSA_EXPORT = 2;
|
||||
internal const short KE_DHE_DSS = 3;
|
||||
internal const short KE_DHE_DSS_EXPORT = 4;
|
||||
internal const short KE_DHE_RSA = 5;
|
||||
internal const short KE_DHE_RSA_EXPORT = 6;
|
||||
internal const short KE_DH_DSS = 7;
|
||||
internal const short KE_DH_RSA = 8;
|
||||
internal const short KE_DH_anon = 9;
|
||||
|
||||
internal abstract void Init(byte[] ms, byte[] cr, byte[] sr);
|
||||
|
||||
internal abstract byte[] EncodePlaintext(short type, byte[] plaintext, int offset, int len);
|
||||
|
||||
internal abstract byte[] DecodeCiphertext(short type, byte[] plaintext, int offset, int len, TlsProtocolHandler handler);
|
||||
|
||||
internal abstract short KeyExchangeAlgorithm { get; }
|
||||
}
|
||||
}
|
72
iTechSharp/srcbc/crypto/tls/TlsCipherSuiteManager.cs
Normal file
72
iTechSharp/srcbc/crypto/tls/TlsCipherSuiteManager.cs
Normal file
@@ -0,0 +1,72 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
using Org.BouncyCastle.Crypto.Digests;
|
||||
using Org.BouncyCastle.Crypto.Engines;
|
||||
using Org.BouncyCastle.Crypto.Modes;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls
|
||||
{
|
||||
/// <remarks>
|
||||
/// A manager for ciphersuite. This class does manage all ciphersuites
|
||||
/// which are used by MicroTLS.
|
||||
/// </remarks>
|
||||
public class TlsCipherSuiteManager
|
||||
{
|
||||
private const int TLS_RSA_WITH_3DES_EDE_CBC_SHA = 0x000a;
|
||||
private const int TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA = 0x0016;
|
||||
private const int TLS_RSA_WITH_AES_128_CBC_SHA = 0x002f;
|
||||
private const int TLS_DHE_RSA_WITH_AES_128_CBC_SHA = 0x0033;
|
||||
private const int TLS_RSA_WITH_AES_256_CBC_SHA = 0x0035;
|
||||
private const int TLS_DHE_RSA_WITH_AES_256_CBC_SHA = 0x0039;
|
||||
|
||||
internal static void WriteCipherSuites(
|
||||
Stream outStr)
|
||||
{
|
||||
TlsUtilities.WriteUint16(2 * 6, outStr);
|
||||
|
||||
TlsUtilities.WriteUint16(TLS_DHE_RSA_WITH_AES_256_CBC_SHA, outStr);
|
||||
TlsUtilities.WriteUint16(TLS_DHE_RSA_WITH_AES_128_CBC_SHA, outStr);
|
||||
TlsUtilities.WriteUint16(TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, outStr);
|
||||
|
||||
TlsUtilities.WriteUint16(TLS_RSA_WITH_AES_256_CBC_SHA, outStr);
|
||||
TlsUtilities.WriteUint16(TLS_RSA_WITH_AES_128_CBC_SHA, outStr);
|
||||
TlsUtilities.WriteUint16(TLS_RSA_WITH_3DES_EDE_CBC_SHA, outStr);
|
||||
|
||||
}
|
||||
|
||||
internal static TlsCipherSuite GetCipherSuite(
|
||||
int number,
|
||||
TlsProtocolHandler handler)
|
||||
{
|
||||
switch (number)
|
||||
{
|
||||
case TLS_RSA_WITH_3DES_EDE_CBC_SHA:
|
||||
return new TlsBlockCipherCipherSuite(new CbcBlockCipher(new DesEdeEngine()), new CbcBlockCipher(new DesEdeEngine()), new Sha1Digest(), new Sha1Digest(), 24, TlsCipherSuite.KE_RSA);
|
||||
|
||||
case TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
|
||||
return new TlsBlockCipherCipherSuite(new CbcBlockCipher(new DesEdeEngine()), new CbcBlockCipher(new DesEdeEngine()), new Sha1Digest(), new Sha1Digest(), 24, TlsCipherSuite.KE_DHE_RSA);
|
||||
|
||||
case TLS_RSA_WITH_AES_128_CBC_SHA:
|
||||
return new TlsBlockCipherCipherSuite(new CbcBlockCipher(new AesFastEngine()), new CbcBlockCipher(new AesFastEngine()), new Sha1Digest(), new Sha1Digest(), 16, TlsCipherSuite.KE_RSA);
|
||||
|
||||
case TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
|
||||
return new TlsBlockCipherCipherSuite(new CbcBlockCipher(new AesFastEngine()), new CbcBlockCipher(new AesFastEngine()), new Sha1Digest(), new Sha1Digest(), 16, TlsCipherSuite.KE_DHE_RSA);
|
||||
|
||||
case TLS_RSA_WITH_AES_256_CBC_SHA:
|
||||
return new TlsBlockCipherCipherSuite(new CbcBlockCipher(new AesFastEngine()), new CbcBlockCipher(new AesFastEngine()), new Sha1Digest(), new Sha1Digest(), 32, TlsCipherSuite.KE_RSA);
|
||||
|
||||
case TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
|
||||
return new TlsBlockCipherCipherSuite(new CbcBlockCipher(new AesFastEngine()), new CbcBlockCipher(new AesFastEngine()), new Sha1Digest(), new Sha1Digest(), 32, TlsCipherSuite.KE_DHE_RSA);
|
||||
|
||||
default:
|
||||
handler.FailWithError(TlsProtocolHandler.AL_fatal, TlsProtocolHandler.AP_handshake_failure);
|
||||
|
||||
/*
|
||||
* Unreachable Code, failWithError will always throw an exception!
|
||||
*/
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
11
iTechSharp/srcbc/crypto/tls/TlsException.cs
Normal file
11
iTechSharp/srcbc/crypto/tls/TlsException.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using System;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls
|
||||
{
|
||||
public class TlsException : Exception
|
||||
{
|
||||
public TlsException() : base() { }
|
||||
public TlsException(string message) : base(message) { }
|
||||
public TlsException(string message, Exception exception) : base(message, exception) { }
|
||||
}
|
||||
}
|
42
iTechSharp/srcbc/crypto/tls/TlsInputStream.cs
Normal file
42
iTechSharp/srcbc/crypto/tls/TlsInputStream.cs
Normal file
@@ -0,0 +1,42 @@
|
||||
using System;
|
||||
|
||||
using Org.BouncyCastle.Utilities.IO;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls
|
||||
{
|
||||
/// <remarks>An input Stream for a TLS 1.0 connection.</remarks>
|
||||
// TODO Fix name and make internal once TlsProtocolHandler.TlsInputStream is removed
|
||||
public class TlsInputStream
|
||||
: BaseInputStream
|
||||
{
|
||||
private readonly TlsProtocolHandler handler;
|
||||
|
||||
internal TlsInputStream(
|
||||
TlsProtocolHandler handler)
|
||||
{
|
||||
this.handler = handler;
|
||||
}
|
||||
|
||||
public override int Read(
|
||||
byte[] buf,
|
||||
int offset,
|
||||
int len)
|
||||
{
|
||||
return this.handler.ReadApplicationData(buf, offset, len);
|
||||
}
|
||||
|
||||
public override int ReadByte()
|
||||
{
|
||||
byte[] buf = new byte[1];
|
||||
if (this.Read(buf, 0, 1) <= 0)
|
||||
return -1;
|
||||
return buf[0];
|
||||
}
|
||||
|
||||
public override void Close()
|
||||
{
|
||||
handler.Close();
|
||||
base.Close();
|
||||
}
|
||||
}
|
||||
}
|
86
iTechSharp/srcbc/crypto/tls/TlsMac.cs
Normal file
86
iTechSharp/srcbc/crypto/tls/TlsMac.cs
Normal file
@@ -0,0 +1,86 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
using Org.BouncyCastle.Crypto.Digests;
|
||||
using Org.BouncyCastle.Crypto.Macs;
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls
|
||||
{
|
||||
/// <remarks>
|
||||
/// A generic TLS MAC implementation, which can be used with any kind of
|
||||
/// IDigest to act as an HMAC.
|
||||
/// </remarks>
|
||||
public class TlsMac
|
||||
{
|
||||
private long seqNo;
|
||||
private HMac mac;
|
||||
|
||||
/**
|
||||
* Generate a new instance of an TlsMac.
|
||||
*
|
||||
* @param digest The digest to use.
|
||||
* @param key_block A byte-array where the key for this mac is located.
|
||||
* @param offset The number of bytes to skip, before the key starts in the buffer.
|
||||
* @param len The length of the key.
|
||||
*/
|
||||
internal TlsMac(
|
||||
IDigest digest,
|
||||
byte[] key_block,
|
||||
int offset,
|
||||
int len)
|
||||
{
|
||||
this.mac = new HMac(digest);
|
||||
KeyParameter param = new KeyParameter(key_block, offset, len);
|
||||
this.mac.Init(param);
|
||||
this.seqNo = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The Keysize of the mac.
|
||||
*/
|
||||
internal int Size
|
||||
{
|
||||
get { return mac.GetMacSize(); }
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the mac for some given data.
|
||||
* <p/>
|
||||
* TlsMac will keep track of the sequence number internally.
|
||||
*
|
||||
* @param type The message type of the message.
|
||||
* @param message A byte-buffer containing the message.
|
||||
* @param offset The number of bytes to skip, before the message starts.
|
||||
* @param len The length of the message.
|
||||
* @return A new byte-buffer containing the mac value.
|
||||
*/
|
||||
internal byte[] CalculateMac(
|
||||
short type,
|
||||
byte[] message,
|
||||
int offset,
|
||||
int len)
|
||||
{
|
||||
try
|
||||
{
|
||||
MemoryStream bosMac = new MemoryStream(13 + len);
|
||||
TlsUtilities.WriteUint64(seqNo++, bosMac);
|
||||
TlsUtilities.WriteUint8(type, bosMac);
|
||||
TlsUtilities.WriteVersion(bosMac);
|
||||
TlsUtilities.WriteUint16(len, bosMac);
|
||||
bosMac.Write(message, offset, len);
|
||||
byte[] macData = bosMac.ToArray();
|
||||
mac.BlockUpdate(macData, 0, macData.Length);
|
||||
byte[] result = new byte[mac.GetMacSize()];
|
||||
mac.DoFinal(result, 0);
|
||||
mac.Reset();
|
||||
return result;
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
// This should never happen
|
||||
throw new InvalidOperationException("Internal error during mac calculation");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
45
iTechSharp/srcbc/crypto/tls/TlsNullCipherSuite.cs
Normal file
45
iTechSharp/srcbc/crypto/tls/TlsNullCipherSuite.cs
Normal file
@@ -0,0 +1,45 @@
|
||||
using System;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls
|
||||
{
|
||||
/// <remarks>A NULL CipherSuite in java, this should only be used during handshake.</remarks>
|
||||
public class TlsNullCipherSuite
|
||||
: TlsCipherSuite
|
||||
{
|
||||
internal override void Init(
|
||||
byte[] ms,
|
||||
byte[] cr,
|
||||
byte[] sr)
|
||||
{
|
||||
throw new TlsException("Sorry, init of TLS_NULL_WITH_NULL_NULL is forbidden");
|
||||
}
|
||||
|
||||
internal override byte[] EncodePlaintext(
|
||||
short type,
|
||||
byte[] plaintext,
|
||||
int offset,
|
||||
int len)
|
||||
{
|
||||
byte[] result = new byte[len];
|
||||
Array.Copy(plaintext, offset, result, 0, len);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal override byte[] DecodeCiphertext(
|
||||
short type,
|
||||
byte[] plaintext,
|
||||
int offset,
|
||||
int len,
|
||||
TlsProtocolHandler handler)
|
||||
{
|
||||
byte[] result = new byte[len];
|
||||
Array.Copy(plaintext, offset, result, 0, len);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal override short KeyExchangeAlgorithm
|
||||
{
|
||||
get { return 0; }
|
||||
}
|
||||
}
|
||||
}
|
50
iTechSharp/srcbc/crypto/tls/TlsOutputStream.cs
Normal file
50
iTechSharp/srcbc/crypto/tls/TlsOutputStream.cs
Normal file
@@ -0,0 +1,50 @@
|
||||
using System;
|
||||
|
||||
using Org.BouncyCastle.Utilities.IO;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls
|
||||
{
|
||||
/// <remarks>An output Stream for a TLS 1.0 connection.</remarks>
|
||||
// TODO Fix name and make internal once TlsProtocolHandler.TlsOuputStream is removed
|
||||
public class TlsOuputStream
|
||||
: BaseOutputStream
|
||||
{
|
||||
private readonly TlsProtocolHandler handler;
|
||||
|
||||
internal TlsOuputStream(
|
||||
TlsProtocolHandler handler)
|
||||
{
|
||||
this.handler = handler;
|
||||
}
|
||||
|
||||
public override void Write(
|
||||
byte[] buf,
|
||||
int offset,
|
||||
int len)
|
||||
{
|
||||
this.handler.WriteData(buf, offset, len);
|
||||
}
|
||||
|
||||
[Obsolete("Use version that takes a 'byte' argument")]
|
||||
public void WriteByte(int arg0)
|
||||
{
|
||||
this.Write((byte)arg0);
|
||||
}
|
||||
|
||||
public override void WriteByte(byte b)
|
||||
{
|
||||
this.Write(b);
|
||||
}
|
||||
|
||||
public override void Close()
|
||||
{
|
||||
handler.Close();
|
||||
base.Close();
|
||||
}
|
||||
|
||||
public override void Flush()
|
||||
{
|
||||
handler.Flush();
|
||||
}
|
||||
}
|
||||
}
|
1152
iTechSharp/srcbc/crypto/tls/TlsProtocolHandler.cs
Normal file
1152
iTechSharp/srcbc/crypto/tls/TlsProtocolHandler.cs
Normal file
File diff suppressed because it is too large
Load Diff
223
iTechSharp/srcbc/crypto/tls/TlsUtilities.cs
Normal file
223
iTechSharp/srcbc/crypto/tls/TlsUtilities.cs
Normal file
@@ -0,0 +1,223 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
using Org.BouncyCastle.Crypto.Digests;
|
||||
using Org.BouncyCastle.Crypto.Macs;
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
using Org.BouncyCastle.Utilities;
|
||||
using Org.BouncyCastle.Utilities.IO;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls
|
||||
{
|
||||
/// <remarks>Some helper fuctions for MicroTLS.</remarks>
|
||||
public class TlsUtilities
|
||||
{
|
||||
internal static byte[] ToByteArray(string str)
|
||||
{
|
||||
return Strings.ToByteArray(str);
|
||||
}
|
||||
|
||||
internal static void WriteUint8(short i, Stream os)
|
||||
{
|
||||
os.WriteByte((byte)i);
|
||||
}
|
||||
|
||||
internal static void WriteUint8(short i, byte[] buf, int offset)
|
||||
{
|
||||
buf[offset] = (byte)i;
|
||||
}
|
||||
|
||||
internal static void WriteUint16(int i, Stream os)
|
||||
{
|
||||
os.WriteByte((byte)(i >> 8));
|
||||
os.WriteByte((byte)i);
|
||||
}
|
||||
|
||||
internal static void WriteUint16(int i, byte[] buf, int offset)
|
||||
{
|
||||
buf[offset] = (byte)(i >> 8);
|
||||
buf[offset + 1] = (byte)i;
|
||||
}
|
||||
|
||||
internal static void WriteUint24(int i, Stream os)
|
||||
{
|
||||
os.WriteByte((byte)(i >> 16));
|
||||
os.WriteByte((byte)(i >> 8));
|
||||
os.WriteByte((byte)i);
|
||||
}
|
||||
|
||||
internal static void WriteUint24(int i, byte[] buf, int offset)
|
||||
{
|
||||
buf[offset] = (byte)(i >> 16);
|
||||
buf[offset + 1] = (byte)(i >> 8);
|
||||
buf[offset + 2] = (byte)(i);
|
||||
}
|
||||
|
||||
internal static void WriteUint32(long i, Stream os)
|
||||
{
|
||||
os.WriteByte((byte)(i >> 24));
|
||||
os.WriteByte((byte)(i >> 16));
|
||||
os.WriteByte((byte)(i >> 8));
|
||||
os.WriteByte((byte)i);
|
||||
}
|
||||
|
||||
internal static void WriteUint32(long i, byte[] buf, int offset)
|
||||
{
|
||||
buf[offset] = (byte)(i >> 24);
|
||||
buf[offset + 1] = (byte)(i >> 16);
|
||||
buf[offset + 2] = (byte)(i >> 8);
|
||||
buf[offset + 3] = (byte)(i);
|
||||
}
|
||||
|
||||
internal static void WriteUint64(long i, Stream os)
|
||||
{
|
||||
os.WriteByte((byte)(i >> 56));
|
||||
os.WriteByte((byte)(i >> 48));
|
||||
os.WriteByte((byte)(i >> 40));
|
||||
os.WriteByte((byte)(i >> 32));
|
||||
os.WriteByte((byte)(i >> 24));
|
||||
os.WriteByte((byte)(i >> 16));
|
||||
os.WriteByte((byte)(i >> 8));
|
||||
os.WriteByte((byte)i);
|
||||
}
|
||||
|
||||
internal static void WriteUint64(long i, byte[] buf, int offset)
|
||||
{
|
||||
buf[offset] = (byte)(i >> 56);
|
||||
buf[offset + 1] = (byte)(i >> 48);
|
||||
buf[offset + 2] = (byte)(i >> 40);
|
||||
buf[offset + 3] = (byte)(i >> 32);
|
||||
buf[offset + 4] = (byte)(i >> 24);
|
||||
buf[offset + 5] = (byte)(i >> 16);
|
||||
buf[offset + 6] = (byte)(i >> 8);
|
||||
buf[offset + 7] = (byte)(i);
|
||||
}
|
||||
|
||||
internal static short ReadUint8(Stream inStr)
|
||||
{
|
||||
int i = inStr.ReadByte();
|
||||
if (i < 0)
|
||||
{
|
||||
throw new EndOfStreamException();
|
||||
}
|
||||
return (short)i;
|
||||
}
|
||||
|
||||
internal static int ReadUint16(Stream inStr)
|
||||
{
|
||||
int i1 = inStr.ReadByte();
|
||||
int i2 = inStr.ReadByte();
|
||||
if ((i1 | i2) < 0)
|
||||
{
|
||||
throw new EndOfStreamException();
|
||||
}
|
||||
return i1 << 8 | i2;
|
||||
}
|
||||
|
||||
internal static int ReadUint24(Stream inStr)
|
||||
{
|
||||
int i1 = inStr.ReadByte();
|
||||
int i2 = inStr.ReadByte();
|
||||
int i3 = inStr.ReadByte();
|
||||
if ((i1 | i2 | i3) < 0)
|
||||
{
|
||||
throw new EndOfStreamException();
|
||||
}
|
||||
return (i1 << 16) | (i2 << 8) | i3;
|
||||
}
|
||||
|
||||
internal static long ReadUint32(Stream inStr)
|
||||
{
|
||||
int i1 = inStr.ReadByte();
|
||||
int i2 = inStr.ReadByte();
|
||||
int i3 = inStr.ReadByte();
|
||||
int i4 = inStr.ReadByte();
|
||||
if ((i1 | i2 | i3 | i4) < 0)
|
||||
{
|
||||
throw new EndOfStreamException();
|
||||
}
|
||||
// TODO Examine this
|
||||
// return (((long)i1) << 24) | (((long)i2) << 16) | (((long)i3) << 8) | ((long)i4);
|
||||
return ((long)i1 << 24) | ((long)i2 << 16) | ((long)i3 << 8) | (uint)i4;
|
||||
}
|
||||
|
||||
internal static void ReadFully(byte[] buf, Stream inStr)
|
||||
{
|
||||
if (Streams.ReadFully(inStr, buf, 0, buf.Length) < buf.Length)
|
||||
throw new EndOfStreamException();
|
||||
}
|
||||
|
||||
internal static void CheckVersion(byte[] readVersion, TlsProtocolHandler handler)
|
||||
{
|
||||
if ((readVersion[0] != 3) || (readVersion[1] != 1))
|
||||
{
|
||||
handler.FailWithError(TlsProtocolHandler.AL_fatal, TlsProtocolHandler.AP_protocol_version);
|
||||
}
|
||||
}
|
||||
|
||||
internal static void CheckVersion(Stream inStr, TlsProtocolHandler handler)
|
||||
{
|
||||
int i1 = inStr.ReadByte();
|
||||
int i2 = inStr.ReadByte();
|
||||
if ((i1 != 3) || (i2 != 1))
|
||||
{
|
||||
handler.FailWithError(TlsProtocolHandler.AL_fatal, TlsProtocolHandler.AP_protocol_version);
|
||||
}
|
||||
}
|
||||
|
||||
internal static void WriteVersion(Stream os)
|
||||
{
|
||||
os.WriteByte(3);
|
||||
os.WriteByte(1);
|
||||
}
|
||||
|
||||
private static void hmac_hash(IDigest digest, byte[] secret, byte[] seed, byte[] output)
|
||||
{
|
||||
HMac mac = new HMac(digest);
|
||||
KeyParameter param = new KeyParameter(secret);
|
||||
byte[] a = seed;
|
||||
int size = digest.GetDigestSize();
|
||||
int iterations = (output.Length + size - 1) / size;
|
||||
byte[] buf = new byte[mac.GetMacSize()];
|
||||
byte[] buf2 = new byte[mac.GetMacSize()];
|
||||
for (int i = 0; i < iterations; i++)
|
||||
{
|
||||
mac.Init(param);
|
||||
mac.BlockUpdate(a, 0, a.Length);
|
||||
mac.DoFinal(buf, 0);
|
||||
a = buf;
|
||||
mac.Init(param);
|
||||
mac.BlockUpdate(a, 0, a.Length);
|
||||
mac.BlockUpdate(seed, 0, seed.Length);
|
||||
mac.DoFinal(buf2, 0);
|
||||
Array.Copy(buf2, 0, output, (size * i), System.Math.Min(size, output.Length - (size * i)));
|
||||
}
|
||||
}
|
||||
|
||||
internal static void PRF(
|
||||
byte[] secret,
|
||||
byte[] label,
|
||||
byte[] seed,
|
||||
byte[] buf)
|
||||
{
|
||||
int s_half = (secret.Length + 1) / 2;
|
||||
byte[] s1 = new byte[s_half];
|
||||
byte[] s2 = new byte[s_half];
|
||||
Array.Copy(secret, 0, s1, 0, s_half);
|
||||
Array.Copy(secret, secret.Length - s_half, s2, 0, s_half);
|
||||
|
||||
byte[] ls = new byte[label.Length + seed.Length];
|
||||
Array.Copy(label, 0, ls, 0, label.Length);
|
||||
Array.Copy(seed, 0, ls, label.Length, seed.Length);
|
||||
|
||||
byte[] prf = new byte[buf.Length];
|
||||
hmac_hash(new MD5Digest(), s1, ls, prf);
|
||||
hmac_hash(new Sha1Digest(), s2, ls, buf);
|
||||
for (int i = 0; i < buf.Length; i++)
|
||||
{
|
||||
buf[i] ^= prf[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user