Commit dbb02b3d authored by Davide Galassi's avatar Davide Galassi

Classical cipher: Hill

unit tests performed
parent 458ab7a6
Pipeline #32581947 passed with stages
in 1 minute and 17 seconds
#ifndef CRY_HILL_H_
#define CRY_HILL_H_
#include <stddef.h>
#define CRY_HILL_KEYDIM_MAX 10
#define CRY_HILL_KEYLEN_MAX (CRY_HILL_KEYDIM_MAX*CRY_HILL_KEYDIM_MAX)
#define CRY_HILL_KEYGEN_TRIALS 100
struct cry_hill_ctx {
unsigned char key[CRY_HILL_KEYLEN_MAX];
unsigned char ikey[CRY_HILL_KEYLEN_MAX];
size_t n;
};
typedef struct cry_hill_ctx cry_hill_ctx;
int cry_hill_init(struct cry_hill_ctx *ctx, const unsigned char *key,
const unsigned char *ikey, size_t keylen);
void cry_hill_encrypt(struct cry_hill_ctx *ctx, unsigned char *out,
const unsigned char *in, size_t len);
void cry_hill_decrypt(struct cry_hill_ctx *ctx, unsigned char *out,
const unsigned char *in, size_t len);
#endif /* CRY_HILL_H_ */
#include "cry/hill.h"
#include "cry/prng.h"
#include "misc.h"
#include <string.h>
static void mtx_minor(unsigned char *out, unsigned char *in,
size_t i, size_t j, size_t n)
{
size_t r, c, h, k;
h = 0;
for (r = 0; r < n; r++) {
if (r == i)
continue;
k = 0;
for (c = 0; c < n; c++) {
if (c == j)
continue;
out[h*(n-1) + k] = in[r*n + c];
k++;
}
h++;
}
}
static unsigned char mtx_det(unsigned char *mtx, size_t n)
{
size_t i;
long det;
unsigned char b[CRY_HILL_KEYLEN_MAX];
if (n > 2) {
det = 0;
for (i = 0; i < n; i++) {
mtx_minor(b, mtx, 0, i, n);
det += mtx[i] * ((i % 2) ? -1 : 1) * mtx_det(b, n-1);
det %= 256;
if (det < 0)
det += 256;
}
} else if (n == 2) {
det = mtx[0]*mtx[3] - mtx[1]*mtx[2];
det %= 256;
if (det < 0)
det += 256;
} else if (n == 1) {
det = mtx[0];
} else { /* n == 0 */
det = 1;
}
return (unsigned char)det;
}
#define SWAP(a, b) do { a ^= b; b ^= a; a ^= b; } while (0)
static void mtx_transpose(unsigned char *out, unsigned char *in, size_t n)
{
size_t i, j;
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++)
out[i*n+j] = in[j*n+i];
}
}
static void mtx_invert(unsigned char *imtx, unsigned char *mtx,
size_t n, unsigned char idet)
{
unsigned char t[CRY_HILL_KEYLEN_MAX]; /* Transpose */
unsigned char b[CRY_HILL_KEYLEN_MAX]; /* Minor */
size_t i, j;
long c;
mtx_transpose(t, mtx, n);
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
mtx_minor(b, t, i, j, n);
c = mtx_det(b, n-1);
if ((i+j) % 2)
c = -c;
c *= idet;
c %= 256;
if (c < 0)
c += 256;
imtx[i*n + j] = (unsigned char)c;
}
}
}
static void mtx_vec_mul(unsigned char *r, const unsigned char *m,
const unsigned char *v, size_t n)
{
size_t i, j;
long res;
for (i = 0; i < n; i++) {
res = 0;
for (j = 0; j < n; j++)
res += m[i*n + j] * v[j];
res %= 256;
if (res < 0)
res += 256;
r[i] = (unsigned char)res;
}
}
static size_t keylen_trim(size_t *keylen)
{
size_t n, z;
if (*keylen > CRY_HILL_KEYLEN_MAX)
*keylen = CRY_HILL_KEYLEN_MAX;
for (n = 1; (z=n*n) < *keylen; n++)
;
if (z > *keylen) {
n--;
*keylen = n*n;
}
return n;
}
static void hill_operate(struct cry_hill_ctx *ctx, unsigned char *out,
const unsigned char *in, size_t len,
const unsigned char *key)
{
unsigned char v[CRY_HILL_KEYDIM_MAX];
size_t n;
while (len > 0) {
n = CRY_MIN(ctx->n, len);
memcpy(v, in, n);
if (n < ctx->n)
memset(v + n, 0, ctx->n - n);
mtx_vec_mul(out, key, v, ctx->n);
out += n;
in += n;
len -= n;
}
}
void cry_hill_encrypt(struct cry_hill_ctx *ctx, unsigned char *out,
const unsigned char *in, size_t len)
{
hill_operate(ctx, out, in, len, ctx->key);
}
void cry_hill_decrypt(struct cry_hill_ctx *ctx, unsigned char *out,
const unsigned char *in, size_t len)
{
hill_operate(ctx, out, in, len, ctx->ikey);
}
static int keygen(unsigned char *key, unsigned char *ikey, size_t keylen,
unsigned int trials)
{
int res = -1;
unsigned long det;
unsigned long idet;
size_t n;
n = keylen_trim(&keylen);
do {
if (trials > 0) {
cry_prng_rand(key, keylen);
trials--;
}
det = mtx_det(key, n);
if (det != 0) {
for (idet = 1; idet < 256; idet++) {
if ((idet * det) % 256 == 1)
break;
}
if (idet != 256) {
mtx_invert(ikey, key, n, idet);
res = 0;
trials = 0;
}
}
} while (trials > 0);
return res;
}
int cry_hill_init(struct cry_hill_ctx *ctx, const unsigned char *key,
const unsigned char *ikey, size_t keylen)
{
int res = 0;
int trials = 0;
memset(ctx, 0, sizeof(*ctx));
ctx->n = keylen_trim(&keylen);
if (key != NULL)
memcpy(ctx->key, key, keylen);
else
trials = CRY_HILL_KEYGEN_TRIALS;
if (ikey == NULL)
res = keygen(ctx->key, ctx->ikey, keylen, trials);
else if (key != NULL)
memcpy(ctx->ikey, ikey, keylen);
else
res = -1;
return res;
}
# src/classic/subdir.mk
objs-y := hill.o
......@@ -18,5 +18,5 @@ objs-y := version.o \
dsa.o \
ecdsa.o
subdirs-y += mpi crc prng sum ecp
subdirs-y += mpi crc prng sum ecp classic
......@@ -14,6 +14,7 @@ objs := \
base64_test.o \
mpi_test.o \
aes_test.o \
hill_test.o \
# gcm_test.o \
des_test.o \
crc_test.o \
......
#include "test.h"
#include <cry/hill.h>
#define RAW_MAX 101
struct hill_param {
unsigned char key[RAW_MAX];
unsigned char ikey[RAW_MAX];
unsigned char src[RAW_MAX];
unsigned char dst[RAW_MAX];
size_t keylen;
size_t ikeylen;
size_t srclen;
size_t dstlen;
};
int raw_init(unsigned char *raw, unsigned int rawlen, const char *asc);
static void param_init(struct hill_param *par, char *argv[])
{
memset(par, 0, sizeof(*par));
par->keylen = raw_init(par->key, sizeof(par->key), argv[0]);
par->ikeylen = raw_init(par->ikey, sizeof(par->ikey), argv[1]);
par->srclen = raw_init(par->src, sizeof(par->src), argv[2]);
par->dstlen = raw_init(par->dst, sizeof(par->dst), argv[3]);
}
static void hill_encrypt(int argc, char *argv[])
{
struct cry_hill_ctx ctx;
struct hill_param par;
unsigned char dst[32];
unsigned char *key, *ikey;
ASSERT(argc == 4);
param_init(&par, argv);
key = (par.keylen != 0) ? par.key : NULL;
ikey = (par.ikeylen != 0) ? par.ikey : NULL;
cry_hill_init(&ctx, key, ikey, par.keylen);
cry_hill_encrypt(&ctx, dst, par.src, par.srclen);
ASSERT_EQ_BUF(dst, par.dst, par.dstlen);
}
static void hill_decrypt(int argc, char *argv[])
{
struct cry_hill_ctx ctx;
struct hill_param par;
unsigned char dst[32];
unsigned char *key, *ikey;
ASSERT(argc == 4);
param_init(&par, argv);
key = (par.keylen != 0) ? par.key : NULL;
ikey = (par.ikeylen != 0) ? par.ikey : NULL;
cry_hill_init(&ctx, key, ikey, par.keylen);
cry_hill_decrypt(&ctx, dst, par.src, par.srclen);
ASSERT_EQ_BUF(dst, par.dst, par.dstlen);
}
static void dispatch(int argc, char *argv[])
{
char *test = *argv;
argv++;
argc--;
if (strcmp(test, "hill_encrypt") == 0)
hill_encrypt(argc, argv);
else if (strcmp(test, "hill_decrypt") == 0)
hill_decrypt(argc, argv);
else
printf("Test '%s' not defined\n", test);
}
void hill_test(void)
{
printf("* HILL Test\n");
func_test("hill_test.data", dispatch);
printf("\n");
}
################################################################################
# Encode
# p0 : encrypt key
# p1 : decrypt key
# p2 : clear text
# p3 : cipher text
################################################################################
Encode 10 bytes, keylen=1
hill_encrypt
e9
59
48656c6c6f576f726c64
88ed4c4c072f07c24c04
Encode 10 bytes, keylen=4
hill_encrypt
66e94bd4
049b818e
48656c6c6f576f726c64
9dbc54146991fced0c74
Encode 10 bytes, keylen=8, trim to 4
hill_encrypt
66e94bd42089b6ac
NULL
48656c6c6f576f726c64
9dbc54146991fced0c74
Encode 10 bytes, keylen=9
hill_encrypt
2089b6acd093abe0c9
70cbd7d98688d06f44
48656c6c6f576f726c64
d57444c1b593aa38b18030cc
Encode 10 bytes, keylen=16
hill_encrypt
66e94bd4ef8a2c3b884cfa59ca342b2e
8e43d7c47d149e6f083e5cfb44cc317e
48656c6c6f576f726c64
b11e40e056e1d4630cbc1088
Encode 10 bytes, keylen=100
hill_encrypt
66e94bd4ef8a2c3b884cfa59ca342b2e58e2fccefa7e3061367f1d57a4e7455a0388dace60b6a392f328c2b971b2fe78f795aaab494b5923f7fd89ff948bc1e0200211214e7394da2089b6acd093abe0c94da219118e297d7b7ebcbcc9c388f28ade7d85
a0ad8d59906f843cfa04ceb20315f2a923b4c101bc1a86249968b30a05b64d6e977a72fb26d3be3ea4777fed181f1598252917320d53f1a0fddb6adbac90b7dff421068bbd4ecf0bae2ca32c7da47354c2353dfedf2b11ca536687cd307472c686d3ce71
48656c6c6f576f726c64
a270828e7b5ed696fbb4
Encode 10 bytes, keylen=101, trim to 100
hill_encrypt
66e94bd4ef8a2c3b884cfa59ca342b2e58e2fccefa7e3061367f1d57a4e7455a0388dace60b6a392f328c2b971b2fe78f795aaab494b5923f7fd89ff948bc1e0200211214e7394da2089b6acd093abe0c94da219118e297d7b7ebcbcc9c388f28ade7d8533
a0ad8d59906f843cfa04ceb20315f2a923b4c101bc1a86249968b30a05b64d6e977a72fb26d3be3ea4777fed181f1598252917320d53f1a0fddb6adbac90b7dff421068bbd4ecf0bae2ca32c7da47354c2353dfedf2b11ca536687cd307472c686d3ce71
48656c6c6f576f726c64
a270828e7b5ed696fbb4
################################################################################
# Decode
# p0 : encrypt key
# p1 : decrypt key
# p2 : cipher text
# p3 : clear text
################################################################################
Decode 10 bytes, keylen=1
hill_decrypt
e9
59
88ed4c4c072f07c24c04
48656c6c6f576f726c64
Decode 10 bytes, keylen=1, ikeygen
hill_decrypt
e9
NULL
88ed4c4c072f07c24c04
48656c6c6f576f726c64
Decode 10 bytes, keylen=4
hill_decrypt
66e94bd4
049b818e
9dbc54146991fced0c74
48656c6c6f576f726c64
Decode 12 bytes, keylen=9
hill_decrypt
2089b6acd093abe0c9
70cbd7d98688d06f44
d57444c1b593aa38b18030cc
48656c6c6f576f726c640000
Decode 12 bytes, keylen=9, ikeygen
hill_decrypt
07080b0c0d0f0d150b
NULL
c4d59529cc543d52a1bcb014
48656c6c6f576f726c640000
Decode 12 bytes, keylen=16
hill_decrypt
66e94bd4ef8a2c3b884cfa59ca342b2e
8e43d7c47d149e6f083e5cfb44cc317e
b11e40e056e1d4630cbc1088
48656c6c6f576f726c640000
Decode 10 bytes, keylen=100
hill_decrypt
66e94bd4ef8a2c3b884cfa59ca342b2e58e2fccefa7e3061367f1d57a4e7455a0388dace60b6a392f328c2b971b2fe78f795aaab494b5923f7fd89ff948bc1e0200211214e7394da2089b6acd093abe0c94da219118e297d7b7ebcbcc9c388f28ade7d85
a0ad8d59906f843cfa04ceb20315f2a923b4c101bc1a86249968b30a05b64d6e977a72fb26d3be3ea4777fed181f1598252917320d53f1a0fddb6adbac90b7dff421068bbd4ecf0bae2ca32c7da47354c2353dfedf2b11ca536687cd307472c686d3ce71
a270828e7b5ed696fbb4
48656c6c6f576f726c64
......@@ -5,6 +5,7 @@ void memxor_test(void);
void base64_test(void);
void mpi_test(void);
void aes_test(void);
void hill_test(void);
static int g_runs;
......@@ -18,6 +19,7 @@ static const char *g_test_str[] = {
"base64",
"mpi",
"aes",
"hill",
};
static char g_test_skip[ARLEN(g_test_str)];
......@@ -29,6 +31,7 @@ static test_func_t g_test_func[] = {
base64_test,
mpi_test,
aes_test,
hill_test,
#if 0
TEST_ELEM(cbc),
TEST_ELEM(ctr),
......@@ -204,7 +207,7 @@ static void parse_args(int argc, char *argv[])
if (argv[i][0] != '-')
break;
if (strcmp(argv[i], "-v") == 0)
g_verbose = 1;
g_verbose = 1;
else if (strcmp(argv[i], "-h") == 0)
help(NULL);
else if (strcmp(argv[i], "-l") == 0)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment