사용자 도구

사이트 도구


kb:rabbitalgorithm

Rabbit Algorithm

StreamCipher 알고리즘의 하나

소스

////////////////////////////////////////////////////////////////////////////////
/// \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];
    }
};

샘플

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);
    }
}

kb/rabbitalgorithm.txt · 마지막으로 수정됨: 2014/11/09 20:00 (바깥 편집)