Initial Commit
This commit is contained in:
236
iTechSharp/srcbc/crypto/engines/IesEngine.cs
Normal file
236
iTechSharp/srcbc/crypto/engines/IesEngine.cs
Normal file
@@ -0,0 +1,236 @@
|
||||
using System;
|
||||
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
using Org.BouncyCastle.Math;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Engines
|
||||
{
|
||||
/**
|
||||
* support class for constructing intergrated encryption ciphers
|
||||
* for doing basic message exchanges on top of key agreement ciphers
|
||||
*/
|
||||
public class IesEngine
|
||||
{
|
||||
private readonly IBasicAgreement agree;
|
||||
private readonly IDerivationFunction kdf;
|
||||
private readonly IMac mac;
|
||||
private readonly BufferedBlockCipher cipher;
|
||||
private readonly byte[] macBuf;
|
||||
|
||||
private bool forEncryption;
|
||||
private ICipherParameters privParam, pubParam;
|
||||
private IesParameters param;
|
||||
|
||||
/**
|
||||
* set up for use with stream mode, where the key derivation function
|
||||
* is used to provide a stream of bytes to xor with the message.
|
||||
*
|
||||
* @param agree the key agreement used as the basis for the encryption
|
||||
* @param kdf the key derivation function used for byte generation
|
||||
* @param mac the message authentication code generator for the message
|
||||
*/
|
||||
public IesEngine(
|
||||
IBasicAgreement agree,
|
||||
IDerivationFunction kdf,
|
||||
IMac mac)
|
||||
{
|
||||
this.agree = agree;
|
||||
this.kdf = kdf;
|
||||
this.mac = mac;
|
||||
this.macBuf = new byte[mac.GetMacSize()];
|
||||
// this.cipher = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* set up for use in conjunction with a block cipher to handle the
|
||||
* message.
|
||||
*
|
||||
* @param agree the key agreement used as the basis for the encryption
|
||||
* @param kdf the key derivation function used for byte generation
|
||||
* @param mac the message authentication code generator for the message
|
||||
* @param cipher the cipher to used for encrypting the message
|
||||
*/
|
||||
public IesEngine(
|
||||
IBasicAgreement agree,
|
||||
IDerivationFunction kdf,
|
||||
IMac mac,
|
||||
BufferedBlockCipher cipher)
|
||||
{
|
||||
this.agree = agree;
|
||||
this.kdf = kdf;
|
||||
this.mac = mac;
|
||||
this.macBuf = new byte[mac.GetMacSize()];
|
||||
this.cipher = cipher;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise the encryptor.
|
||||
*
|
||||
* @param forEncryption whether or not this is encryption/decryption.
|
||||
* @param privParam our private key parameters
|
||||
* @param pubParam the recipient's/sender's public key parameters
|
||||
* @param param encoding and derivation parameters.
|
||||
*/
|
||||
public void Init(
|
||||
bool forEncryption,
|
||||
ICipherParameters privParameters,
|
||||
ICipherParameters pubParameters,
|
||||
ICipherParameters iesParameters)
|
||||
{
|
||||
this.forEncryption = forEncryption;
|
||||
this.privParam = privParameters;
|
||||
this.pubParam = pubParameters;
|
||||
this.param = (IesParameters)iesParameters;
|
||||
}
|
||||
|
||||
private byte[] DecryptBlock(
|
||||
byte[] in_enc,
|
||||
int inOff,
|
||||
int inLen,
|
||||
byte[] z)
|
||||
{
|
||||
byte[] M = null;
|
||||
KeyParameter macKey = null;
|
||||
KdfParameters kParam = new KdfParameters(z, param.GetDerivationV());
|
||||
int macKeySize = param.MacKeySize;
|
||||
|
||||
kdf.Init(kParam);
|
||||
|
||||
inLen -= mac.GetMacSize();
|
||||
|
||||
if (cipher == null) // stream mode
|
||||
{
|
||||
byte[] Buffer = GenerateKdfBytes(kParam, inLen + (macKeySize / 8));
|
||||
|
||||
M = new byte[inLen];
|
||||
|
||||
for (int i = 0; i != inLen; i++)
|
||||
{
|
||||
M[i] = (byte)(in_enc[inOff + i] ^ Buffer[i]);
|
||||
}
|
||||
|
||||
macKey = new KeyParameter(Buffer, inLen, (macKeySize / 8));
|
||||
}
|
||||
else
|
||||
{
|
||||
int cipherKeySize = ((IesWithCipherParameters)param).CipherKeySize;
|
||||
byte[] Buffer = GenerateKdfBytes(kParam, (cipherKeySize / 8) + (macKeySize / 8));
|
||||
|
||||
cipher.Init(false, new KeyParameter(Buffer, 0, (cipherKeySize / 8)));
|
||||
|
||||
M = cipher.DoFinal(in_enc, inOff, inLen);
|
||||
|
||||
macKey = new KeyParameter(Buffer, (cipherKeySize / 8), (macKeySize / 8));
|
||||
}
|
||||
|
||||
byte[] macIV = param.GetEncodingV();
|
||||
|
||||
mac.Init(macKey);
|
||||
mac.BlockUpdate(in_enc, inOff, inLen);
|
||||
mac.BlockUpdate(macIV, 0, macIV.Length);
|
||||
mac.DoFinal(macBuf, 0);
|
||||
|
||||
inOff += inLen;
|
||||
|
||||
for (int t = 0; t < macBuf.Length; t++)
|
||||
{
|
||||
if (macBuf[t] != in_enc[inOff + t])
|
||||
{
|
||||
throw (new InvalidCipherTextException("IMac codes failed to equal."));
|
||||
}
|
||||
}
|
||||
|
||||
return M;
|
||||
}
|
||||
|
||||
private byte[] EncryptBlock(
|
||||
byte[] input,
|
||||
int inOff,
|
||||
int inLen,
|
||||
byte[] z)
|
||||
{
|
||||
byte[] C = null;
|
||||
KeyParameter macKey = null;
|
||||
KdfParameters kParam = new KdfParameters(z, param.GetDerivationV());
|
||||
int c_text_length = 0;
|
||||
int macKeySize = param.MacKeySize;
|
||||
|
||||
if (cipher == null) // stream mode
|
||||
{
|
||||
byte[] Buffer = GenerateKdfBytes(kParam, inLen + (macKeySize / 8));
|
||||
|
||||
C = new byte[inLen + mac.GetMacSize()];
|
||||
c_text_length = inLen;
|
||||
|
||||
for (int i = 0; i != inLen; i++)
|
||||
{
|
||||
C[i] = (byte)(input[inOff + i] ^ Buffer[i]);
|
||||
}
|
||||
|
||||
macKey = new KeyParameter(Buffer, inLen, (macKeySize / 8));
|
||||
}
|
||||
else
|
||||
{
|
||||
int cipherKeySize = ((IesWithCipherParameters)param).CipherKeySize;
|
||||
byte[] Buffer = GenerateKdfBytes(kParam, (cipherKeySize / 8) + (macKeySize / 8));
|
||||
|
||||
cipher.Init(true, new KeyParameter(Buffer, 0, (cipherKeySize / 8)));
|
||||
|
||||
c_text_length = cipher.GetOutputSize(inLen);
|
||||
byte[] tmp = new byte[c_text_length];
|
||||
|
||||
int len = cipher.ProcessBytes(input, inOff, inLen, tmp, 0);
|
||||
len += cipher.DoFinal(tmp, len);
|
||||
|
||||
C = new byte[len + mac.GetMacSize()];
|
||||
c_text_length = len;
|
||||
|
||||
Array.Copy(tmp, 0, C, 0, len);
|
||||
|
||||
macKey = new KeyParameter(Buffer, (cipherKeySize / 8), (macKeySize / 8));
|
||||
}
|
||||
|
||||
byte[] macIV = param.GetEncodingV();
|
||||
|
||||
mac.Init(macKey);
|
||||
mac.BlockUpdate(C, 0, c_text_length);
|
||||
mac.BlockUpdate(macIV, 0, macIV.Length);
|
||||
//
|
||||
// return the message and it's MAC
|
||||
//
|
||||
mac.DoFinal(C, c_text_length);
|
||||
return C;
|
||||
}
|
||||
|
||||
private byte[] GenerateKdfBytes(
|
||||
KdfParameters kParam,
|
||||
int length)
|
||||
{
|
||||
byte[] buf = new byte[length];
|
||||
|
||||
kdf.Init(kParam);
|
||||
|
||||
kdf.GenerateBytes(buf, 0, buf.Length);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
public byte[] ProcessBlock(
|
||||
byte[] input,
|
||||
int inOff,
|
||||
int inLen)
|
||||
{
|
||||
agree.Init(privParam);
|
||||
|
||||
BigInteger z = agree.CalculateAgreement(pubParam);
|
||||
|
||||
// TODO Check that this is right (...Unsigned? Check length?)
|
||||
byte[] zBytes = z.ToByteArray();
|
||||
|
||||
return forEncryption
|
||||
? EncryptBlock(input, inOff, inLen, zBytes)
|
||||
: DecryptBlock(input, inOff, inLen, zBytes);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user