mirror of
https://github.com/thunderbrewhq/squall.git
synced 2025-12-12 02:22:30 +00:00
feat(crypto): add ARC4 implementation
This commit is contained in:
parent
d7fc37cef1
commit
a9bfaa02fc
5 changed files with 127 additions and 0 deletions
|
|
@ -4,6 +4,7 @@ check_cxx_compiler_flag(-Wno-invalid-offsetof HAS_NO_INVALID_OFFSETOF)
|
||||||
file(GLOB STORM_SOURCES
|
file(GLOB STORM_SOURCES
|
||||||
"*.cpp"
|
"*.cpp"
|
||||||
"big/*.cpp"
|
"big/*.cpp"
|
||||||
|
"crypto/*.cpp"
|
||||||
"hash/*.cpp"
|
"hash/*.cpp"
|
||||||
"queue/*.cpp"
|
"queue/*.cpp"
|
||||||
"string/*.cpp"
|
"string/*.cpp"
|
||||||
|
|
|
||||||
57
storm/Crypto.cpp
Normal file
57
storm/Crypto.cpp
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
#include "storm/Crypto.hpp"
|
||||||
|
#include "storm/Error.hpp"
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
void SARC4PrepareKey(const void* data, uint32_t len, SARC4Key* key) {
|
||||||
|
STORM_ASSERT(data);
|
||||||
|
STORM_VALIDATE(data, ERROR_INVALID_PARAMETER);
|
||||||
|
|
||||||
|
key->x = 0;
|
||||||
|
key->y = 0;
|
||||||
|
|
||||||
|
// ARC4 key-scheduling algorithm
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < 256; i++) {
|
||||||
|
key->state[i] = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t j = 0;
|
||||||
|
for (uint32_t i = 0; i < 256; i++) {
|
||||||
|
j = (j + key->state[i] + static_cast<const uint8_t*>(data)[i % len]) % 256;
|
||||||
|
|
||||||
|
// Swap values
|
||||||
|
auto si = key->state[i];
|
||||||
|
auto sj = key->state[j];
|
||||||
|
key->state[i] = sj;
|
||||||
|
key->state[j] = si;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SARC4ProcessBuffer(void* data, uint32_t len, const SARC4Key* inKey, SARC4Key* outKey) {
|
||||||
|
if (inKey != outKey) {
|
||||||
|
memcpy(outKey, inKey, sizeof(SARC4Key));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note: The original implementation uses two loops. The first loop decrypts/encrypts data
|
||||||
|
// 4-bytes-at-a-time. The second loop decrypts/encrypts all bytes outside of that alignment
|
||||||
|
// 1-byte-at-a-time. For simplicity's sake, our implementation handles 1-byte-at-a-time.
|
||||||
|
|
||||||
|
auto x = outKey->x;
|
||||||
|
auto y = outKey->y;
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < len; i++) {
|
||||||
|
x += 1;
|
||||||
|
auto sx = outKey->state[x];
|
||||||
|
|
||||||
|
y += sx;
|
||||||
|
auto sy = outKey->state[y];
|
||||||
|
|
||||||
|
outKey->state[x] = sy;
|
||||||
|
outKey->state[y] = sx;
|
||||||
|
|
||||||
|
static_cast<uint8_t*>(data)[i] ^= outKey->state[static_cast<uint8_t>(sx + sy)];
|
||||||
|
}
|
||||||
|
|
||||||
|
outKey->x = x;
|
||||||
|
outKey->y = y;
|
||||||
|
}
|
||||||
10
storm/Crypto.hpp
Normal file
10
storm/Crypto.hpp
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
#ifndef STORM_CRYPTO_HPP
|
||||||
|
#define STORM_CRYPTO_HPP
|
||||||
|
|
||||||
|
#include "storm/crypto/SARC4Key.hpp"
|
||||||
|
|
||||||
|
void SARC4PrepareKey(const void* data, uint32_t len, SARC4Key* key);
|
||||||
|
|
||||||
|
void SARC4ProcessBuffer(void* data, uint32_t len, const SARC4Key* inKey, SARC4Key* outKey);
|
||||||
|
|
||||||
|
#endif
|
||||||
12
storm/crypto/SARC4Key.hpp
Normal file
12
storm/crypto/SARC4Key.hpp
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
#ifndef STORM_CRYPTO_S_ARC4_KEY_HPP
|
||||||
|
#define STORM_CRYPTO_S_ARC4_KEY_HPP
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
struct SARC4Key {
|
||||||
|
uint8_t state[256];
|
||||||
|
uint8_t x;
|
||||||
|
uint8_t y;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
47
test/Crypto.cpp
Normal file
47
test/Crypto.cpp
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
#include "storm/Crypto.hpp"
|
||||||
|
#include "test/Test.hpp"
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
TEST_CASE("SARC4ProcessBuffer", "[crypto]") {
|
||||||
|
SECTION("correctly processes given non-zero input for given non-zero key") {
|
||||||
|
uint8_t key[] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF };
|
||||||
|
|
||||||
|
SARC4Key rc4Key;
|
||||||
|
SARC4PrepareKey(key, sizeof(key), &rc4Key);
|
||||||
|
|
||||||
|
uint8_t input[] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF };
|
||||||
|
uint8_t processed[] = { 0x75, 0xB7, 0x87, 0x80, 0x99, 0xE0, 0xC5, 0x96 };
|
||||||
|
|
||||||
|
SARC4ProcessBuffer(input, sizeof(input), &rc4Key, &rc4Key);
|
||||||
|
|
||||||
|
REQUIRE(!memcmp(input, processed, sizeof(input)));
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("correctly processes given all-zero input for given non-zero key") {
|
||||||
|
uint8_t key[] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef };
|
||||||
|
|
||||||
|
SARC4Key rc4Key;
|
||||||
|
SARC4PrepareKey(key, sizeof(key), &rc4Key);
|
||||||
|
|
||||||
|
uint8_t input[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||||
|
uint8_t processed[] = { 0x74, 0x94, 0xC2, 0xE7, 0x10, 0x4B, 0x08, 0x79 };
|
||||||
|
|
||||||
|
SARC4ProcessBuffer(input, sizeof(input), &rc4Key, &rc4Key);
|
||||||
|
|
||||||
|
REQUIRE(!memcmp(input, processed, sizeof(input)));
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("correctly processes given all-zero input for given all-zero key") {
|
||||||
|
uint8_t key[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||||
|
|
||||||
|
SARC4Key rc4Key;
|
||||||
|
SARC4PrepareKey(key, sizeof(key), &rc4Key);
|
||||||
|
|
||||||
|
uint8_t input[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||||
|
uint8_t processed[] = { 0xDE, 0x18, 0x89, 0x41, 0xA3, 0x37, 0x5D, 0x3A };
|
||||||
|
|
||||||
|
SARC4ProcessBuffer(input, sizeof(input), &rc4Key, &rc4Key);
|
||||||
|
|
||||||
|
REQUIRE(!memcmp(input, processed, sizeof(input)));
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue