1 °³¿ä
2 ¼Ò½º
////////////////////////////////////////////////////////////////////////////////
/// \class cRabbitStream
/// \brief "Rabbit"À̶ó´Â Stream Cipher ¾Ë°í¸®Áò ±¸Çö
////////////////////////////////////////////////////////////////////////////////
class cRabbitStream
{
private:
UINT32 m_x[8];
UINT32 m_c[8];
UINT32 m_carry;
public:
/// \brief Initialize the cipher instance as function of the key
/// \param key
cRabbitStream(const UINT8 key[16])
{
// Temporary data
UINT32 k0, k1, k2, k3, i;
// Generate four subkeys
k0 = *(UINT32*)(key + 0);
k1 = *(UINT32*)(key + 4);
k2 = *(UINT32*)(key + 8);
k3 = *(UINT32*)(key + 12);
// Generate initial state variables
m_x[0] = k0;
m_x[2] = k1;
m_x[4] = k2;
m_x[6] = k3;
m_x[1] = (k3 << 16) | (k2 >> 16);
m_x[3] = (k0 << 16) | (k3 >> 16);
m_x[5] = (k1 << 16) | (k0 >> 16);
m_x[7] = (k2 << 16) | (k1 >> 16);
// Generate initial counter values
m_c[0] = Rotate(k2, 16);
m_c[2] = Rotate(k3, 16);
m_c[4] = Rotate(k0, 16);
m_c[6] = Rotate(k1, 16);
m_c[1] = (k0 & 0xFFFF0000) | (k1 & 0xFFFF);
m_c[3] = (k1 & 0xFFFF0000) | (k2 & 0xFFFF);
m_c[5] = (k2 & 0xFFFF0000) | (k3 & 0xFFFF);
m_c[7] = (k3 & 0xFFFF0000) | (k0 & 0xFFFF);
// Reset carry bit
m_carry = 0;
// Iterate the system four times
for (i=0; i<4; i++)
ComputeNextState();
// Modify the counters
for (i=0; i<8; i++)
m_c[(i+4)&0x7] ^= m_x[i];
}
/// \brief Initialize the cipher instance as function of the IV
/// and the master instance
/// \param master
/// \param iv
cRabbitStream(const cRabbitStream* master, const UINT8 iv[8])
{
// Temporary data
UINT32 i0, i1, i2, i3, i;
// Generate four subvectors
i0 = *(UINT32*)(iv+0);
i2 = *(UINT32*)(iv+4);
i1 = (i0>>16) | (i2&0xFFFF0000);
i3 = (i2<<16) | (i0&0x0000FFFF);
// Modify counter values
m_c[0] = master->m_c[0] ^ i0;
m_c[1] = master->m_c[1] ^ i1;
m_c[2] = master->m_c[2] ^ i2;
m_c[3] = master->m_c[3] ^ i3;
m_c[4] = master->m_c[4] ^ i0;
m_c[5] = master->m_c[5] ^ i1;
m_c[6] = master->m_c[6] ^ i2;
m_c[7] = master->m_c[7] ^ i3;
// Copy internal state values
for (i=0; i<8; i++)
m_x[i] = master->m_x[i];
m_carry = master->m_carry;
// Iterate the system four times
for (i=0; i<4; i++)
ComputeNextState();
}
/// \brief Destructor
virtual ~cRabbitStream() {}
public:
/// \brief Encrypt or decrypt a block of data
/// \param buf
/// \param buflen
void XOR(UINT8* buf, size_t buflen)
{
// Error if the size of the data to encrypt is not a multiple of 16
Assert((buflen % 16) == 0);
// Temporary data
UINT32 i;
for (i=0; i<buflen; i += 16)
{
// Iterate the system
ComputeNextState();
// Encrypt 16 bytes of data
*(UINT32*)(buf + 0) = *(UINT32*)(buf + 0) ^ m_x[0] ^ (m_x[5]>>16) ^ (m_x[3] << 16);
*(UINT32*)(buf + 4) = *(UINT32*)(buf + 4) ^ m_x[2] ^ (m_x[7]>>16) ^ (m_x[5] << 16);
*(UINT32*)(buf + 8) = *(UINT32*)(buf + 8) ^ m_x[4] ^ (m_x[1]>>16) ^ (m_x[7] << 16);
*(UINT32*)(buf + 12) = *(UINT32*)(buf +12) ^ m_x[6] ^ (m_x[3]>>16) ^ (m_x[1] << 16);
// Increment pointers to source and destination data
buf += 16;
}
}
private:
/// \brief Left rotation of a 32-bit unsigned integer
/// \param x
/// \param rot
/// \return UINT32
UINT32 Rotate(UINT32 x, int rot)
{
return (x<<rot) | (x>>(32-rot));
}
/// \brief Square a 32-bit unsigned integer to obtain the 64-bit result
/// and return the 32 high bits XOR the 32 low bits
/// \param x
/// \return UINT32
UINT32 GetG(UINT32 x)
{
// Construct high and low argument for squaring
UINT32 a = x & 0xFFFF;
UINT32 b = x >> 16;
// Calculate high and low result of squaring
UINT32 h = ((((a*a)>>17) + (a*b))>>15) + b*b;
UINT32 l = x*x;
// Return high XOR low
return h ^ l;
}
/// \brief Calculate the next internal state
void ComputeNextState()
{
// Temporary data
UINT32 g[8], c_old[8], i;
// Save old counter values
for (i=0; i<8; i++)
c_old[i] = m_c[i];
// Calculate new counter values
m_c[0] += 0x4D34D34D + m_carry;
m_c[1] += 0xD34D34D3 + (m_c[0] < c_old[0]);
m_c[2] += 0x34D34D34 + (m_c[1] < c_old[1]);
m_c[3] += 0x4D34D34D + (m_c[2] < c_old[2]);
m_c[4] += 0xD34D34D3 + (m_c[3] < c_old[3]);
m_c[5] += 0x34D34D34 + (m_c[4] < c_old[4]);
m_c[6] += 0x4D34D34D + (m_c[5] < c_old[5]);
m_c[7] += 0xD34D34D3 + (m_c[6] < c_old[6]);
m_carry = (m_c[7] < c_old[7]);
// Calculate the g-functions
for (i=0;i<8;i++)
g[i] = GetG(m_x[i] + m_c[i]);
// Calculate new state values
m_x[0] = g[0] + Rotate(g[7], 16) + Rotate(g[6], 16);
m_x[1] = g[1] + Rotate(g[0], 8) + g[7];
m_x[2] = g[2] + Rotate(g[1], 16) + Rotate(g[0], 16);
m_x[3] = g[3] + Rotate(g[2], 8) + g[1];
m_x[4] = g[4] + Rotate(g[3], 16) + Rotate(g[2], 16);
m_x[5] = g[5] + Rotate(g[4], 8) + g[3];
m_x[6] = g[6] + Rotate(g[5], 16) + Rotate(g[4], 16);
m_x[7] = g[7] + Rotate(g[6], 8) + g[5];
}
};
2.2 Sample Usage
UINT8 key[] = {
0xAC, 0xC3, 0x51, 0xDC, 0xF1, 0x62, 0xFC, 0x3B,
0xFE, 0x36, 0x3D, 0x2E, 0x29, 0x13, 0x28, 0x91
};
cRabbitStream encryption(key);
cRabbitStream decryption(key);
UINT8 original[16] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
UINT8 dest[16] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
encryption.XOR(dest, 16);
decryption.XOR(dest, 16);
for (int i=0; i<16; ++i)
{
if (original[i] != dest[i])
{
Assert(false);
}
}
SeriousMoin v1 (koMoinMoin 1.0a4 Modified)