사용자 도구

사이트 도구


kb:scopalgorithm

차이

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

차이 보기로 링크

kb:scopalgorithm [2014/11/09 20:29] (현재)
줄 1: 줄 1:
 +====== SCOP Algorithm ======
 +see [[http://​www.geocities.com/​smaltchev/​scop.html | The SCOP Stream Cipher]] by Simeon V. Maltchev, Peter T. Antonov
 +
 +
 +====== 소스 ======
 +<code cpp>
 +////////////////////////////////////////////////////////////////////////////////​
 +/// \class cScopStream
 +/// \brief "​SCOP"​라는 Stream Cipher 알고리즘 구현.
 +///
 +/// Simeon Maltchev의 문서에 있는 소스를 대충 정리했다. 자세한 내용은 아래의
 +/// 링크를 참고하기 바란다.
 +///
 +/// http://​www.geocities.com/​smaltchev/​scop.html
 +////////////////////////////////////////////////////////////////////////////////​
 +
 +class cScopStream
 +{
 +private:
 +    struct st_key
 +    { 
 +        UINT32 v[384];
 +        UINT8  i;
 +        UINT8  j;
 +        UINT8  t3;
 +    }; 
 +
 +    struct st_gp8
 +    { 
 +        UINT8  coef[8][4];
 +        UINT32 x[4];
 +    }; 
 +
 +    st_key m_Key; ​
 +    st_gp8 m_Internal; ​
 +
 +
 +public:
 +    cScopStream(UINT8* key, UINT32 key_size)
 +    {
 +        UINT32 odd; 
 +        UINT32 t[4]; 
 +    ​
 +        ExpandKey(key,​ key_size); ​
 +    ​
 +        for (int i = 0; i < 8; i++) 
 +            GeneratePolynoms(t); ​
 +    ​
 +        for (int i = 0; i < 12; i++) 
 +        { 
 +            for (int j = 0; j < 8; j++) 
 +                GeneratePolynoms(m_Key.v + i * 32 + j * 4); 
 +    ​
 +            GeneratePolynoms(t); ​
 +        } 
 +    ​
 +        GeneratePolynoms(t); ​
 +        m_Key.i ​ =(UINT8)(t[3] >> 24); 
 +        m_Key.j ​ =(UINT8)(t[3] >> 16); 
 +        m_Key.t3 =(UINT8)(t[3] >> 8); 
 +    ​
 +        odd = t[3] & 0x7F; 
 +        m_Key.v[odd] |= 1; 
 +    }
 +
 +    virtual ~cScopStream() {}
 +
 +
 +public:
 +    void Encrypt(UINT32* buf, int buflen)
 +    {
 +        UINT8   ​i ​   = m_Key.i;
 +        UINT8   ​j ​   = m_Key.j; ​
 +        UINT32 ​ t1   = 0;
 +        UINT32 ​ t2   = 0;
 +        UINT32 ​ t3   = m_Key.t3; ​
 +        UINT32 ​ k    = 0;
 +        UINT32 ​ t    = 0; 
 +        UINT32* word = buf;
 +        UINT32* v    = m_Key.v; ​
 +    ​
 +        while (word < buf + buflen) ​
 +        { 
 +            t1 = v[128 + j]; 
 +            j  = j + static_cast<​UINT8>​(t3); ​
 +            t  = v[i]; 
 +            t2 = v[128 + j]; 
 +    ​
 +            /* If you want to compile with Borland'​s 32-bit C compiler using 
 +            optimizations,​ change the line below to: 
 +            i =(i + 1) & 255; */ 
 +            i++; 
 +    ​
 +            t3 = t2 + t; 
 +            v[128 + j] = t3; 
 +            j = j + static_cast<​UINT8>​(t2); ​
 +            k  = t1 + t2; 
 +    ​
 +            *word++ += k; 
 +        } 
 +    }
 +
 +    void Decrypt(UINT32* buf, int buflen)
 +    {
 +        UINT32 ​ k    = 0;
 +        UINT32 ​ t    = 0; 
 +        UINT8   ​i ​   = m_Key.i; ​
 +        UINT8   ​j ​   = m_Key.j; ​
 +        UINT32 ​ t1   = 0;
 +        UINT32 ​ t2   = 0;
 +        UINT32 ​ t3   = m_Key.t3; ​
 +        UINT32* v    = m_Key.v; ​
 +        UINT32* word = buf; 
 +    ​
 +        while (word < buf + buflen) ​
 +        { 
 +            t1 = v[128 + j]; 
 +            j  = j + static_cast<​UINT8>​(t3); ​
 +            t  = v[i]; 
 +            t2 = v[128 + j]; 
 +    ​
 +            // If you want to compile with Borland'​s 32-bit C compiler
 +            // using optimizations,​ change the line below to: 
 +            // i =(i + 1) & 255;
 +            i++; 
 +    ​
 +            t3 = t2 + t; 
 +            v[128 + j] = t3; 
 +            j = j + static_cast<​UINT8>​(t2); ​
 +            k  = t1 + t2;
 +    ​
 +            *word++ -= k; 
 +        } 
 +    }
 +
 +
 +private:
 +    void ExpandKey(UINT8* in, UINT32 in_size)
 +    {
 +        Assert(in_size >= 2 && in_size <= 48); 
 +    ​
 +        UINT8* p = reinterpret_cast<​UINT8*>​(&​m_Internal); ​
 +    ​
 +        for (UINT32 i = 0; i < in_size; i++) 
 +            p[i] = in[i]; ​
 +    ​
 +        for (UINT32 i = in_size; i < 48; i++) 
 +            p[i] =(UINT8)(p[i - in_size] + p[i - in_size + 1]); 
 +    ​
 +        UINT8 counter = 1; 
 +        for (UINT32 i = 0; i < 32; i++) 
 +        { 
 +            if(p[i] == 0) 
 +                p[i] = counter++; ​
 +        } 
 +    }
 +
 +    void GeneratePolynoms(UINT32* out)
 +    {
 +        UINT32 y1, y2;
 +        UINT32 x_1, x_2, x_3, x_4; 
 +        UINT32 newx[4]; ​
 +        int i, i2; 
 +    ​
 +        for (i = 0; i < 8; i += 2) 
 +        { 
 +            i2 = i >> 1; 
 +    ​
 +            x_1 = m_Internal.x[i2] >> 16; 
 +            x_2 = x_1 * x_1; 
 +            x_3 = x_2 * x_1; 
 +            x_4 = x_3 * x_1; 
 +    ​
 +            y1 = m_Internal.coef[i][0] * x_4 + 
 +                m_Internal.coef[i][1] * x_3 + 
 +                m_Internal.coef[i][2] * x_2 + 
 +                m_Internal.coef[i][3] * x_1 + 1; 
 +    ​
 +            x_1 = m_Internal.x[i2] & 0xFFFFL; ​
 +            x_2 = x_1 * x_1; 
 +            x_3 = x_2 * x_1; 
 +            x_4 = x_3 * x_1; 
 +    ​
 +            y2 = m_Internal.coef[i + 1][0] * x_4 + 
 +                m_Internal.coef[i + 1][1] * x_3 + 
 +                m_Internal.coef[i + 1][2] * x_2 + 
 +                m_Internal.coef[i + 1][3] * x_1 + 1; 
 +    ​
 +            out[i2] ​ = (y1 << 16) | (y2 & 0xFFFFL); ​
 +            newx[i2] = (y1 & 0xFFFF0000L) | (y2 >> 16); 
 +        } 
 +    ​
 +        m_Internal.x[0] = (newx[0] >> 16) | (newx[3] << 16); 
 +        m_Internal.x[1] = (newx[0] << 16) | (newx[1] >> 16); 
 +        m_Internal.x[2] = (newx[1] << 16) | (newx[2] >> 16); 
 +        m_Internal.x[3] = (newx[2] << 16) | (newx[3] >> 16); 
 +    }
 +};
 +</​code>​
 +
 +====== 샘플 ======
 +<code cpp>
 +#!cpp
 +UINT8 mykey[] = { 
 +    0x29, 0x04, 0x19, 0x72, 0xFB, 0x42, 0xBA, 0x5F,  ​
 +    0xC7, 0x12, 0x77, 0x12, 0xF1, 0x38, 0x29, 0xC9 
 +}; 
 +
 +cScopStream stream1(mykey,​ sizeof(mykey));​
 +cScopStream stream2(mykey,​ sizeof(mykey));​
 +
 +UINT32 original[] = { 100, 200, 300, 400, 500, 600 };
 +UINT32 dest[] ​    = { 100, 200, 300, 400, 500, 600 };
 +
 +stream1.Encrypt(dest,​ 6);
 +stream2.Decrypt(dest,​ 6);
 +
 +for (int i=0; i<6; ++i)
 +{
 +    if (original[i] != dest[i])
 +    {
 +        Assert(false);​
 +    }
 +}
 +</​code>​
 +
 +----
 +  * see also [[StreamCipher]]
  
kb/scopalgorithm.txt · 마지막으로 수정됨: 2014/11/09 20:29 (바깥 편집)