От Yuri Myakotin (2:5020/4441.1) к All
В ответ на Заголовок предыдущего сообщения в треде (Имя Автора)
Hello All!
Вкратце - используется Threefish-1024 в комбинированном CBC+CTR (через SetTweak), результат XORится с 128бит шифром (к примеру, TwoFish или Serpent), работающим в режиме OFB.
Разумеется, ключи разные и друг от друга алгоритмически не зависят, получаются разными хеш-функциями из разных частей 1024-бит секретного ключа и 1024бит рандомной "соли", идущей в начале зашифрованного сообщения.
PS естественно, опять же предполагается, что в момент шифрования/дешифрования физического доступа к компьютеру супостат не имеет.
public class Paranoid
{
private ulong[] ThreeFishIV;
private ulong[] TwoFishOFB;
private ulong[] Counter;
private SkeinFish.Threefish1024 ThreeF;
private TwoFish TwoF;
static private void Int128ToBytes(ulong[] int128, byte[] bytes)
{
Buffer.BlockCopy(int128, 0, bytes, 0, 16);
}
static private void BytesToInt128(byte[] bytes,ulong[] int128)
{
Buffer.BlockCopy(bytes, 0, int128, 0, 16);
}
private void TickCount()
{
byte[] tmp = new byte[16];
byte[] tmp1 = new byte[16];
Int128ToBytes(TwoFishOFB, tmp);
TwoF.EncryptBlock(tmp, tmp1);
BytesToInt128(tmp1, TwoFishOFB);
}
private void Xor1024(ref ulong[] src)
{
for (int i = 0; i < 16;i++)
src[i] ^= ThreeFishIV[i];
}
public Paranoid(byte[] key, byte[] salt)
{
byte[] tmp = new byte[96];
byte[] tmp2 = new byte[32];
ulong[] Key1 = new ulong[16];
byte[] Key2 = new byte[32];
TwoFishOFB=new ulong[2];
Counter = new ulong[2];
ThreeFishIV=new ulong[16];
if ((key.Length!=128)||(salt.Length!=128)) throw new ArgumentException("Invalid arguments length");
Buffer.BlockCopy(key, 0, tmp, 0, 48);
Buffer.BlockCopy(salt, 0, tmp, 48, 48);
HashLib.Crypto.SHA3.Blake512 Blake = new HashLib.Crypto.SHA3.Blake512();
Blake.Initialize();
byte[] tmp3 = (Blake.ComputeBytes(tmp)).GetBytes();
Buffer.BlockCopy(tmp3, 0, Key1, 0, 64);
Buffer.BlockCopy(salt, 48, tmp, 0, 48);
Buffer.BlockCopy(key, 48, tmp, 48, 48);
HashLib.Crypto.SHA3.Keccak512 Keccak = new HashLib.Crypto.SHA3.Keccak512();
Keccak.Initialize();
tmp3 = (Keccak.ComputeBytes(tmp)).GetBytes();
Buffer.BlockCopy(tmp3, 0, Key1, 64, 64);
Buffer.BlockCopy(key, 96, tmp2, 0, 16);
Buffer.BlockCopy(salt, 96, tmp2, 16, 16);
SkeinFish.Skein256 Skein = new SkeinFish.Skein256();
Skein.Initialize();
tmp3 = Skein.ComputeHash(tmp2);
Buffer.BlockCopy(tmp3, 0, Key2, 0, 32);
Buffer.BlockCopy(key, 112, tmp2, 0, 16);
Buffer.BlockCopy(salt, 112, tmp2, 16, 16);
Skein.Initialize();
tmp3 = Skein.ComputeHash(tmp2);
Buffer.BlockCopy(tmp3, 0, TwoFishOFB, 0, 16);
Buffer.BlockCopy(tmp3, 16, Counter, 0, 16);
Skein.Dispose();
byte[] tmp4 = new byte[160];
Buffer.BlockCopy(key, 32, tmp4, 0, 32);
Buffer.BlockCopy(salt, 0, tmp4, 32, 128);
SkeinFish.Skein1024 Sk = new Skein1024();
Sk.Initialize();
byte[] IvBytes=Sk.ComputeHash(tmp4);
Buffer.BlockCopy(IvBytes, 0, ThreeFishIV, 0, 128);
ThreeF = new SkeinFish.Threefish1024();
ThreeF.SetKey(Key1);
for (int i = 0; i < 16; i++) Key1[i] = 0;
TwoF = new TwoFish();
TwoF.SetKey(Key2);
for (int i = 0; i < 32; i++) Key2[i] = 0;
}
public void Encrypt(byte[] InData,Stream Out)
{
ulong[] Buf1024=new ulong[16];
byte[] tmpBuf = new byte[128];
MemoryStream In = new MemoryStream();
long Len = InData.LongLength;
if ((Len%128)!=0)
{
int cnt =127-((int)Len % 128);
byte PadSize = (byte)(cnt + 1);
In.WriteByte(PadSize);
byte[] tmp = new byte[cnt];
RNGCryptoServiceProvider rnd = new RNGCryptoServiceProvider();
rnd.GetBytes(tmp);
In.Write(tmp, 0, cnt);
}
In.Write(InData, 0, InData.Length);
Len = In.Length;
In.Seek(0, SeekOrigin.Begin);
for (long i=0;i<(Len/128);i++)
{
In.Read(tmpBuf, 0, 128);
Buffer.BlockCopy(tmpBuf, 0, Buf1024, 0, 128);
ThreeF.SetTweak(Counter);
Counter[0] += 7;
Counter[1] += 19;
Xor1024(ref Buf1024);
ThreeF.Encrypt(Buf1024, ThreeFishIV);
for (int j = 0; j < 8;j++)
{
TickCount();
Buf1024[j * 2] = ThreeFishIV[j * 2] ^ TwoFishOFB[0];
Buf1024[j * 2 + 1] = ThreeFishIV[j * 2 + 1] ^ TwoFishOFB[1];
}
Buffer.BlockCopy(Buf1024, 0, tmpBuf, 0, 128);
Out.Write(tmpBuf, 0, 128);
}
In.Close();
In.Dispose();
}
public void Decrypt(Stream In, Stream Out,int OffsetIn)
{
ulong[] SrcBuf1024 = new ulong[16];
ulong[] IntermBuf1024 = new ulong[16];
byte[] tmpBuf = new byte[128];
long Len = In.Length-OffsetIn;
In.Seek(OffsetIn, SeekOrigin.Begin);
for (long i = 0; i < (Len / 128); i++)
{
ThreeF.SetTweak(Counter);
Counter[0] += 7;
Counter[1] += 19;
In.Read(tmpBuf, 0, 128);
Buffer.BlockCopy(tmpBuf, 0, SrcBuf1024, 0, 128);
for (int j = 0; j < 8; j++)
{
TickCount();
SrcBuf1024[j * 2] ^= TwoFishOFB[0];
SrcBuf1024[j * 2 + 1] ^= TwoFishOFB[1];
}
ThreeF.Decrypt(SrcBuf1024, IntermBuf1024);
Xor1024(ref IntermBuf1024);
Buffer.BlockCopy(SrcBuf1024, 0, ThreeFishIV, 0, 128);
Buffer.BlockCopy(IntermBuf1024, 0, tmpBuf, 0, 128);
Out.Write(tmpBuf, 0, 128);
}
}
}
See all in Hell,
Yuri
--- Мессагомаратель 1.1.5-b20110320
* Origin: Убей человека. Прежде всего в самом себе. (2:5020/4441.1)
Ответы на это письмо:
From: Username
Заголовок следующего сообщения в треде может быть длинным и его придется перенести на новую строку
From: Username
Или коротким