📄 twofish2.cpp
字号:
for ( int i = 0; i < 16; i++, scanner++ ) {
*scanner = *scanner ^ qBlockPlain[i];
}
}
// save the input and output blocks, since CBC needs these for XOR
// operations
qBlockPush( in, out );
} else {
// cipher block stealing, we are at Pn,
// but since Cn-1 must now be replaced with CnC'
// we pop it off, and recalculate Cn-1
//
char PnMinusOne[16];
char CnMinusOne[16];
if ( decrypt ) {
// We are on an odd block, and had to do cipher block stealing,
// so the PnMinusOne has to be derived differently.
qBlockPop( &CnMinusOne[0], &PnMinusOne[0] );
// First we decrypt it into CBC and C'
char CBCplusCprime[16];
blockCrypt16( &CnMinusOne[0], &CBCplusCprime[0] );
// we then xor the first few bytes with the "in" bytes (Cn)
// to recover Pn, which we put in out
char* scanner = in;
char* outScanner = out;
for ( int i = 0; i < size; i++, scanner++, outScanner++ ) {
*outScanner = *scanner ^ CBCplusCprime[i];
}
// We now recover the original CnMinusOne, which consists of
// the first "size" bytes of "in" data, followed by the
// "Cprime" portion of CBCplusCprime
scanner = in;
for ( i = 0; i < size; i++, scanner++ ) {
CnMinusOne[i] = *scanner;
}
for ( i = size; i < 16; i++ ) {
CnMinusOne[i] = CBCplusCprime[i];
}
// we now decrypt CnMinusOne to get PnMinusOne xored with Cn-2
blockCrypt16( &CnMinusOne[0], &PnMinusOne[0] );
for ( i = 0; i < 16; i++ ) {
PnMinusOne[i] = PnMinusOne[i] ^ prevCipher[i];
}
// So at this point, out has PnMinusOne
qBlockPush( &CnMinusOne[0], &PnMinusOne[0] );
qBlockFlush();
flushOutput( out, size );
} else {
qBlockPop( &PnMinusOne[0], &CnMinusOne[0] );
char Pn[16];
bzero( &Pn[0], 16 );
memcpy( &Pn[0], in, size );
for ( int i = 0; i < 16; i++ ) {
Pn[i] = CnMinusOne[i] ^ Pn[i];
}
blockCrypt16( &Pn[0], out );
qBlockPush( &Pn[0], out ); // now we officially have Cn-1
qBlockFlush(); // write them all out
flushOutput( &CnMinusOne[0], size ); // old Cn-1 becomes new partial Cn
}
qBlockDefined = false;
}
}
void TwoFish::qBlockPush( char* p, char* c ) {
if ( qBlockDefined ) {
qBlockFlush();
}
memcpy( &prevCipher[0], &qBlockPlain[0], 16 );
memcpy( &qBlockPlain[0], p, 16 );
memcpy( &qBlockCrypt[0], c, 16 );
qBlockDefined = true;
}
void TwoFish::qBlockPop( char* p, char* c ) {
memcpy( p, &qBlockPlain[0], 16 );
memcpy( c, &qBlockCrypt[0], 16 );
qBlockDefined = false;
}
//
// flush a complete block to all active output areas
// this occurs when we know the block does not need to be
// re-encrypted or re-decrypted. The redoing of encryption
// and decryption is necessary for cipher text stealing technique
// and is done on the last complete block.
//
void TwoFish::qBlockFlush() {
flushOutput( &qBlockCrypt[0], 16 );
}
void TwoFish::flush() {
if ( qBlockDefined ) {
qBlockFlush();
}
}
void TwoFish::blockCrypt16( char* in, char* out ) {
int inOffset = 0;
int outOffset = 0;
unsigned int x0 = (in[inOffset] & 0xFF) |
(in[inOffset+1] & 0xFF) << 8 |
(in[inOffset+2] & 0xFF) << 16 |
(in[inOffset+3] & 0xFF) << 24;
inOffset += 4;
unsigned int x1 = (in[inOffset] & 0xFF) |
(in[inOffset+1] & 0xFF) << 8 |
(in[inOffset+2] & 0xFF) << 16 |
(in[inOffset+3] & 0xFF) << 24;
inOffset += 4;
unsigned int x2 = (in[inOffset] & 0xFF) |
(in[inOffset+1] & 0xFF) << 8 |
(in[inOffset+2] & 0xFF) << 16 |
(in[inOffset+3] & 0xFF) << 24;
inOffset += 4;
unsigned int x3 = (in[inOffset] & 0xFF) |
(in[inOffset+1] & 0xFF) << 8 |
(in[inOffset+2] & 0xFF) << 16 |
(in[inOffset+3] & 0xFF) << 24;
/* unsigned int x0;
unsigned int x1;
unsigned int x2;
unsigned int x3;
in += inOffset;
memcpy( &x0, in, 4 );
in += 4;
memcpy( &x1, in, 4 );
in += 4;
memcpy( &x2, in, 4 );
in += 4;
memcpy( &x3, in, 4 );*/
x0 ^= subKeys[0];
x1 ^= subKeys[1];
x2 ^= subKeys[2];
x3 ^= subKeys[3];
int k, t0, t1;
if ( decrypt ) {
k = 39;
for (int R = 0; R < ROUNDS; R += 2) {
t0 = Fe320( sBox, x0 );
t1 = Fe323( sBox, x1 );
x3 ^= t0 + (t1<<1) + subKeys[k--];
x3 = x3 >> 1 | x3 << 31;
x2 = x2 << 1 | x2 >> 31;
x2 ^= t0 + t1 + subKeys[k--];
t0 = Fe320( sBox, x2 );
t1 = Fe323( sBox, x3 );
x1 ^= t0 + (t1<<1) + subKeys[k--];
x1 = x1 >> 1 | x1 << 31;
x0 = x0 << 1 | x0 >> 31;
x0 ^= t0 + t1 + subKeys[k--];
}
} else {
k = 8;
for (int R = 0; R < ROUNDS; R += 2) {
t0 = Fe320( sBox, x0 );
t1 = Fe323( sBox, x1 );
x2 ^= t0 + t1 + subKeys[k++];
x2 = x2 >> 1 | x2 << 31;
x3 = x3 << 1 | x3 >> 31;
x3 ^= t0 + (t1<<1) + subKeys[k++];
t0 = Fe320( sBox, x2 );
t1 = Fe323( sBox, x3 );
x0 ^= t0 + t1 + subKeys[k++];
x0 = x0 >> 1 | x0 << 31;
x1 = x1 << 1 | x1 >> 31;
x1 ^= t0 + (t1<<1) + subKeys[k++];
}
}
x2 ^= subKeys[4];
x3 ^= subKeys[5];
x0 ^= subKeys[6];
x1 ^= subKeys[7];
out += outOffset;
/*memcpy( out, &x2, 4 );
out += 4;
memcpy( out, &x3, 4 );
out += 4;
memcpy( out, &x0, 4 );
out += 4;
memcpy( out, &x1, 4 );*/
*out++ = (x2 );
*out++ = (x2 >> 8);
*out++ = (x2 >> 16);
*out++ = (x2 >> 24);
*out++ = (x3 );
*out++ = (x3 >> 8);
*out++ = (x3 >> 16);
*out++ = (x3 >> 24);
*out++ = (x0 );
*out++ = (x0 >> 8);
*out++ = (x0 >> 16);
*out++ = (x0 >> 24);
*out++ = (x1 );
*out++ = (x1 >> 8);
*out++ = (x1 >> 16);
*out++ = (x1 >> 24);
}
/**
* Use (12, 8) Reed-Solomon code over GF(256) to produce a key S-box
* 32-bit entity from two key material 32-bit entities.
*
* @param k0 1st 32-bit entity.
* @param k1 2nd 32-bit entity.
* @return Remainder polynomial generated using RS code
*/
int TwoFish::RS_MDS_Encode( int k0, int k1 ) {
int r = k1;
for (int i = 0; i < 4; i++) // shift 1 byte at a time
RS_rem( r );
r ^= k0;
for ( i = 0; i < 4; i++)
RS_rem( r );
return r;
}
int TwoFish::F32( int k64Cnt, int x, int* k32 ) {
int b0 = b0(x);
int b1 = b1(x);
int b2 = b2(x);
int b3 = b3(x);
int k0 = k32[0];
int k1 = k32[1];
int k2 = k32[2];
int k3 = k32[3];
int result = 0;
switch (k64Cnt & 3) {
case 1:
result =
MDS[0][(P[P_01][b0] & 0xFF) ^ b0(k0)] ^
MDS[1][(P[P_11][b1] & 0xFF) ^ b1(k0)] ^
MDS[2][(P[P_21][b2] & 0xFF) ^ b2(k0)] ^
MDS[3][(P[P_31][b3] & 0xFF) ^ b3(k0)];
break;
case 0: // same as 4
b0 = (P[P_04][b0] & 0xFF) ^ b0(k3);
b1 = (P[P_14][b1] & 0xFF) ^ b1(k3);
b2 = (P[P_24][b2] & 0xFF) ^ b2(k3);
b3 = (P[P_34][b3] & 0xFF) ^ b3(k3);
case 3:
b0 = (P[P_03][b0] & 0xFF) ^ b0(k2);
b1 = (P[P_13][b1] & 0xFF) ^ b1(k2);
b2 = (P[P_23][b2] & 0xFF) ^ b2(k2);
b3 = (P[P_33][b3] & 0xFF) ^ b3(k2);
case 2:
// 128-bit keys (optimize for this case)
result =
MDS[0][(P[P_01][(P[P_02][b0] & 0xFF) ^ b0(k1)] & 0xFF) ^ b0(k0)] ^
MDS[1][(P[P_11][(P[P_12][b1] & 0xFF) ^ b1(k1)] & 0xFF) ^ b1(k0)] ^
MDS[2][(P[P_21][(P[P_22][b2] & 0xFF) ^ b2(k1)] & 0xFF) ^ b2(k0)] ^
MDS[3][(P[P_31][(P[P_32][b3] & 0xFF) ^ b3(k1)] & 0xFF) ^ b3(k0)];
break;
}
return result;
}
int TwoFish::Fe320( int* sBox, int x ) {
return sBox[ b0(x) << 1 ] ^
sBox[ (b1(x) << 1) | 1] ^
sBox[0x200 + (b2(x) << 1) ] ^
sBox[0x200 + (b3(x) << 1) | 1];
}
int TwoFish::Fe323( int* sBox, int x ) {
return sBox[ (b3(x) << 1) ] ^
sBox[ (b0(x) << 1) | 1] ^
sBox[0x200 + (b1(x) << 1) ] ^
sBox[0x200 + (b2(x) << 1) | 1];
}
int TwoFish::Fe32( int* sBox, int x, int R ) {
return sBox[ 2*_b(x, R ) ] ^
sBox[ 2*_b(x, R+1) + 1] ^
sBox[0x200 + 2*_b(x, R+2) ] ^
sBox[0x200 + 2*_b(x, R+3) + 1];
}
static char key[32];
char* generateKey( char* s ) {
int sIdx = 0;
for ( int i = 0; i < 32; i++ ) {
char sval = *( s + sIdx );
if (( sval >= '0' ) && ( sval <= '9' )) {
key[i] = sval;
} else if (( sval >= 'a' ) && ( sval <= 'f' )) {
key[i] = sval;
} else {
int q = sval%16;
if ( q < 10 ) {
key[i] = ('0' + q);
} else {
key[i] = ('a' + q - 10);
}
}
sIdx++;
if ( *( s + sIdx ) == 0 ) {
sIdx = 0;
}
}
return( &key[0] );
}
AsciiTwofish::AsciiTwofish( TwoFish* e ) {
engine = e;
}
void AsciiTwofish::encryptAscii( char* in, char* out, int outBufferSize ) {
engine->setDecrypt( false );
engine->resetCBC();
unsigned char byteBuf[200];
char* originalOut = out;
// encrypt one block at a time with twofish
char inList[16];
unsigned char outList[16];
engine->setOutputBuffer( byteBuf );
int remaining = strlen( in );
int len = remaining;
int bidx = 0;
while ( remaining > 0 ) {
if ( remaining > 16 ) {
memcpy( inList, in + bidx, 16 );
engine->blockCrypt( inList, (char*)outList, 16 );
} else {
memcpy( inList, in + bidx, remaining );
engine->blockCrypt( inList, (char*)outList, remaining );
}
bidx += 16;
remaining -= 16;
}
engine->flush();
// now do totally stupid ascii encoding of bytes
if ( outBufferSize < len*3 ) {
printf( "Hey, outBufferSize is %d, but len*3 is %d\n", outBufferSize, len*3 );
} else {
for ( int i = 0; i < len; i++ ) {
sprintf( out, "%03d", byteBuf[i] );
out += 3;
}
}
engine->setOutputBuffer( NULL );
}
#define BOGUS_ASCII_BUFLEN 2000
void AsciiTwofish::decryptAscii( char* in, char* out ) {
engine->setDecrypt( true );
engine->resetCBC();
engine->setOutputBuffer( (unsigned char*)out );
int inLen = strlen( in );
if (( *( in + inLen - 1 ) == '\n' ) ||
( *( in + inLen - 1 ) == '\r' )) {
*( in + inLen - 1 ) = 0;
inLen = strlen( in );
}
unsigned char byteBuf[BOGUS_ASCII_BUFLEN];
int byteBufIdx = 0;
if ( inLen*3 > BOGUS_ASCII_BUFLEN ) {
printf( "inLength %d is too big!\n", inLen );
exit( 0 );
}
// first convert ascii to bytes, placing in another buffer
for ( int i = 0; i < inLen; i += 3 ) {
unsigned int x = 0;
x = x * 10 + ( *in++ - '0' );
x = x * 10 + ( *in++ - '0' );
x = x * 10 + ( *in++ - '0' );
byteBuf[ byteBufIdx++ ] = x;
byteBuf[ byteBufIdx ] = 0;
}
// then run it through twofish placing result into command buffer
char inList[16];
unsigned char outList[16];
int remaining = byteBufIdx;
*( out + byteBufIdx ) = 0;
int bidx = 0;
while ( remaining > 0 ) {
if ( remaining > 16 ) {
memcpy( inList, &byteBuf[bidx], 16 );
engine->blockCrypt( inList, (char*)outList, 16 );
} else {
memcpy( inList, &byteBuf[bidx], remaining );
engine->blockCrypt( inList, (char*)outList, remaining );
}
bidx += 16;
remaining -= 16;
}
engine->flush();
engine->setOutputBuffer( NULL );
*( out + byteBufIdx ) = 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -