사용자 도구

사이트 도구


kb:rabbitalgorithm

차이

문서의 선택한 두 판 사이의 차이를 보여줍니다.

차이 보기로 링크

kb:rabbitalgorithm [2014/11/09 20:00] (현재)
줄 1: 줄 1:
 +====== Rabbit Algorithm ======
 +[[StreamCipher]] 알고리즘의 하나
 +
 +====== 소스 ======
 +<code cpp>
 +////////////////////////////////////////////////////////////////////////////////​
 +/// \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];
 +    }
 +};
 +</​code>​
 +
 +====== 샘플 ======
 +<code cpp>
 +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);​
 +    }
 +}
 +</​code>​
 +
 +----
 +  * see also [[StreamCipher]]
  
kb/rabbitalgorithm.txt · 마지막으로 수정됨: 2014/11/09 20:00 (바깥 편집)