Bazaar/Cypher : better handling of Initialization Vector (nonce)

git-svn-id: svn://ultimatepp.org/upp/trunk@2733 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
micio 2010-10-03 08:48:28 +00:00
parent 83be4d2245
commit 6585d5ca5c
5 changed files with 77 additions and 57 deletions

View file

@ -68,8 +68,8 @@ class CypherBase
// key setting - rekeying
// return true on success, false otherwise
// rekeyng clears all stream states and buffers and sets state to idle
virtual bool SetKey(String const &key, qword nonce = 0) = 0;
virtual bool SetKey(byte const *keyBuf, size_t keyLen, qword nonce = 0) = 0;
virtual bool SetKey(String const &key, String const &nonce = Null) = 0;
virtual bool SetKey(byte const *keyBuf, size_t keyLen, byte const *nonce = NULL, size_t nonceLen = 0) = 0;
// encrypt/decrypt functions
virtual String operator()(String const &s) = 0;

View file

@ -8,34 +8,34 @@ RC4::RC4() : CypherBase()
si = sj = 0;
}
RC4::RC4(String const &key, qword nonce) : CypherBase()
RC4::RC4(String const &key, String const &nonce) : CypherBase()
{
SetKey(key, nonce);
}
RC4::RC4(byte const *keyBuf, size_t keyLen, qword nonce)
RC4::RC4(byte const *keyBuf, size_t keyLen, byte const *nonce, size_t nonceLen)
{
SetKey(keyBuf, keyLen, nonce);
SetKey(keyBuf, keyLen, nonce, nonceLen);
}
bool RC4::SetKey(String const &key, qword nonce)
bool RC4::SetKey(String const &key, String const &nonce)
{
byte const *b = (byte const *)~key;
int keyLen = key.GetCount();
return SetKey(b, keyLen, nonce);
return SetKey(b, keyLen, (byte const *)~nonce, nonce.GetCount());
}
bool RC4::SetKey(byte const *kBuf, size_t keyLen, qword nonce)
bool RC4::SetKey(byte const *kBuf, size_t keyLen, byte const *nonce, size_t nonceLen)
{
int i, j;
unsigned char keyarr[256], swap;
// appends NONCE at key -- avoids repeated encoding of same soruce stream
Buffer<byte>keyBuf(keyLen + sizeof(qword));
Buffer<byte>keyBuf(keyLen + nonceLen);
memcpy(keyBuf, kBuf, keyLen);
memcpy(keyBuf + keyLen, &nonce, sizeof(qword));
keyLen += sizeof(qword);
memcpy(keyBuf + keyLen, nonce, nonceLen);
keyLen += nonceLen;
si = sj = 0;
for (i = j = 0; i < 256; i++, j = (j + 1) % keyLen)
@ -65,26 +65,7 @@ bool RC4::SetKey(byte const *kBuf, size_t keyLen, qword nonce)
return true;
}
void RC4::operator()(const byte *src, byte *dst, size_t len)
{
unsigned char swap;
while (len--)
{
sj += sbox[++si];
swap = sbox[si];
sbox[si] = sbox[sj];
sbox[sj] = swap;
swap = sbox[si] + sbox[sj];
*dst++ = *src++ ^ sbox[swap];
}
}
void RC4::operator()(byte *buf, size_t len)
{
operator()(buf, buf, len);
}
// encode/decode string
String RC4::operator()(String const &s)
{
unsigned char swap;
@ -104,6 +85,28 @@ String RC4::operator()(String const &s)
return res;
}
// encode/decode buffer, dest on different buffer
void RC4::operator()(const byte *src, byte *dst, size_t len)
{
unsigned char swap;
while (len--)
{
sj += sbox[++si];
swap = sbox[si];
sbox[si] = sbox[sj];
sbox[sj] = swap;
swap = sbox[si] + sbox[sj];
*dst++ = *src++ ^ sbox[swap];
}
}
// encode/decode buffer in place
void RC4::operator()(byte *buf, size_t len)
{
operator()(buf, buf, len);
}
// stream support
String RC4::StreamOut(void)
{
@ -121,6 +124,8 @@ void RC4::StreamIn(String const &s)
void RC4::Flush(void)
{
// Snow2 is already a stream Cypher,
// no need to pad last block
};

View file

@ -21,16 +21,23 @@ class RC4 : public CypherBase
public:
// constructors
RC4();
RC4(String const &key, qword nonce = 0);
RC4(byte const *keyBuf, size_t keyLen, qword nonce = 0);
RC4(String const &key, String const &nonce = Null);
RC4(byte const *keyBuf, size_t keyLen, byte const *nonce = NULL, size_t nonceLen = 0);
bool SetKey(String const &key, qword nonce = 0);
bool SetKey(byte const *keyBuf, size_t keyLen, qword nonce = 0);
// key settings
bool SetKey(String const &key, String const &nonce = Null);
bool SetKey(byte const *keyBuf, size_t keyLen, byte const *nonce = NULL, size_t nonceLen = 0);
void operator()(const byte *src, byte *dst, size_t len);
void operator()(byte *buf, size_t len);
// encode/decode string
String operator()(String const &s);
// encode/decode buffer, dest on different buffer
void operator()(const byte *src, byte *dst, size_t len);
// encode/decode buffer in place
void operator()(byte *buf, size_t len);
};
END_UPP_NAMESPACE

View file

@ -538,39 +538,45 @@ Snow2::Snow2() : CypherBase()
byteIndex = 0;
}
Snow2::Snow2(const String &key, qword nonce) : CypherBase()
Snow2::Snow2(String const &key, String const &nonce) : CypherBase()
{
SetKey(key, nonce);
}
Snow2::Snow2(byte const *keyBuf, size_t keyLen, qword nonce) : CypherBase()
Snow2::Snow2(byte const *keyBuf, size_t keyLen, byte const *nonce, size_t nonceLen) : CypherBase()
{
SetKey(keyBuf, keyLen, nonce);
SetKey(keyBuf, keyLen, nonce, nonceLen);
}
// key settings
bool Snow2::SetKey(const String &key, qword nonce)
bool Snow2::SetKey(String const &key, String const &nonce)
{
return SetKey((byte const *)~key, key.GetCount(), nonce);
return SetKey((byte const *)~key, key.GetCount(), (byte const *)~nonce, nonce.GetCount());
}
bool Snow2::SetKey(byte const *keyBuf, size_t keyLen, qword nonce)
static dword separateNonce(byte const *nonce, size_t nonceLen, size_t idx)
{
size_t pos = idx << 2;
size_t endPos = min(pos + 4, nonceLen);
dword res = 0;
while(pos < endPos)
res = (res << 8) | *(nonce + pos++);
return res;
}
bool Snow2::SetKey(byte const *keyBuf, size_t keyLen, byte const *nonce, size_t nonceLen)
{
byteIndex = 0;
if(keyLen != 16 && keyLen != 32)
return false;
// initializes the encoder box with key
// should do with 4 dwords as nonce, we simplify with 4 words( 1 qword)
dword n1 = (nonce >> 48) & 0xFFFF;
dword n2 = (nonce >> 32) & 0xFFFF;
dword n3 = (nonce >> 16) & 0xFFFF;
dword n4 = (nonce ) & 0xFFFF;
n1 |= n4 << 16;
n2 |= n3 << 16;
n3 |= n2 << 16;
n4 |= n1 << 16;
loadkey(keyBuf, keyLen, n1, n2, n3, n4);
loadkey(keyBuf, keyLen,
separateNonce(nonce, nonceLen, 0),
separateNonce(nonce, nonceLen, 1),
separateNonce(nonce, nonceLen, 2),
separateNonce(nonce, nonceLen, 3)
);
// load first 16 dword of keystream into buffer
keystream(keyStream);
@ -649,6 +655,8 @@ void Snow2::StreamIn(String const &s)
void Snow2::Flush(void)
{
// Snow2 is already a stream Cypher,
// no need to pad last block
};
END_UPP_NAMESPACE

View file

@ -64,12 +64,12 @@ class Snow2 : public CypherBase
// constructors
Snow2();
Snow2(const String &key, qword nonce = 0);
Snow2(byte const *keyBuf, size_t keyLen, qword nonce = 0);
Snow2(const String &key, String const &nonce = Null);
Snow2(byte const *keyBuf, size_t keyLen, byte const *nonce = NULL, size_t nonceLen = 0);
// key settings
bool SetKey(const String &key, qword nonce = 0);
bool SetKey(byte const *keyBuf, size_t keyLen, qword nonce = 0);
bool SetKey(String const &key, String const &nonce = Null);
bool SetKey(byte const *keyBuf, size_t keyLen, byte const *nonce = NULL, size_t nonceLen = 0);
// encode/decode string
String operator()(String const &s);