- °³¿ä
- ¼Ò½º
- Algorithm
- Sample Usage
1 °³¿ä
2 ¼Ò½º
////////////////////////////////////////////////////////////////////////////////
/// \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);
}
};
2.2 Sample Usage
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);
}
}
SeriousMoin v1 (koMoinMoin 1.0a4 Modified)