cangrepp

Some cryptographic attacks
Log | Files | Refs | README

commit 847230c311c8d9e0101a1de98f69a7f800c966fe
Author: olikru <olikru@tkruger.se>
Date:   Thu, 11 Jan 2024 10:50:32 +0100

initial

Diffstat:
AMakefile | 58++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AREADME | 20++++++++++++++++++++
ATODO | 3+++
Aexamples/hnp_instance.txt | 4++++
Ahnp.c | 96+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ahnp.h | 30++++++++++++++++++++++++++++++
Asmallfactor.c | 5+++++
Asmallfactor.h | 8++++++++
Atest_angrepp.c | 7+++++++
Atools/hnpsolve.c | 103+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
10 files changed, 334 insertions(+), 0 deletions(-)

diff --git a/Makefile b/Makefile @@ -0,0 +1,58 @@ +.SUFFIXES: .c .o .so +CC=clang +CFLAGS+=-std=c99 -pedantic -Wall -Werror -Wstrict-prototypes +CFLAGS+=-Wmissing-prototypes -Wmissing-declarations -Wshadow +CFLAGS+=-Wpointer-arith -Wcast-qual -Wsign-compare +CFLAGS+=-O2 -g +CFLAGS+=-fstack-protector-all -Wtype-limits -fno-common +CFLAGS+=-fno-builtin +CFLAGS+=-I/usr/local/include + +CFLAGS+=-I/usr/local/include/flint +LDFLAGS+=-L/usr/local/lib -lflint -lgmp + +INSTALL_PATH=$(HOME)/.local +BUILD=build + +TEST_SOURCE=test_angrepp.c +HEADERS=smallfactor.h +OBJS=\ +smallfactor.o\ +hnp.o +TOOLS=\ +hnpsolve +SHARED=angrepp.so +LIBSHARED=libangrepp.so + +BUILD_OBJS=$(OBJS:S/^/$(BUILD)\//g) +TOOLS_DIR=tools + +all: build $(OBJS) $(SHARED) $(TOOLS) test + +build: + mkdir -p $(BUILD) + mkdir -p $(BUILD)/tools + +.c.o: + $(CC) $(CFLAGS) -c $< -o $(BUILD)/$@ + +$(SHARED): + $(CC) -shared -fPIC $(BUILD_OBJS) -o $(BUILD)/$(SHARED) $(LDFLAGS) + +test: $(TEST_SOURCE) + $(CC) $(CFLAGS) -o $(BUILD)/test $(TEST_SOURCE) $(BUILD_OBJS) $(LDFLAGS) + +# -- tools + +hnpsolve: build $(OBJS) + $(CC) -I. $(CFLAGS) -o $(BUILD)/tools/hnpsolve $(TOOLS_DIR)/hnpsolve.c $(BUILD_OBJS) $(LDFLAGS) + +install: + mkdir -p $(INSTALL_PATH)/lib/angrepp + cp $(BUILD)/$(SHARED) $(INSTALL_PATH)/lib/angrepp/$(LIBSHARED) + chmod 644 $(INSTALL_PATH)/lib/angrepp/$(LIBSHARED) + mkdir -p $(INSTALL_PATH)/include/angrepp + cp $(HEADERS) $(INSTALL_PATH)/include/angrepp/ + +clean: + rm -rf $(BUILD) diff --git a/README b/README @@ -0,0 +1,20 @@ + + ________ _ __________ _______ ___ + / ___/ _ | / |/ / ___/ _ \/ __/ _ \/ _ \ + / /__/ __ |/ / (_ / , _/ _// ___/ ___/ + \___/_/ |_/_/|_/\___/_/|_/___/_/ /_/ + + +Collection of functions related to cryptographic attacks of various +kinds. This is an attempt to build a decent library which heavily +depends on FLINT (see https://flintlib.org/). + +== 0 - Table of contents + +0 - Table of contents +1 - Hidden number problem (hnp.c) + +== 1 - Hidden number problem + +The hidden number problem shows up in various contexts of cryptographic +attacks. TODO TODO , api TODO diff --git a/TODO b/TODO @@ -0,0 +1,3 @@ +* Unit tests +* Documentation, spec. README +* Implement fun stuff diff --git a/examples/hnp_instance.txt b/examples/hnp_instance.txt @@ -0,0 +1,4 @@ +3 11 131101 +46396 65911 +3185 5049 +30618 56983 diff --git a/hnp.c b/hnp.c @@ -0,0 +1,96 @@ +#include "hnp.h" + +int hidden_number_problem(fmpz *res, const slong nres, const fmpz *t, + const fmpz *a, const slong m, const fmpz_t n, + const fmpz_t B) { + if (nres < m + 1) + return (-1); + + // initialise a zero matrix + fmpz_mat_t A; + fmpz_mat_init(A, m + 2, m + 2); + fmpz_mat_zero(A); + + // set up n^2's on the diagonal + slong i; + fmpz_t n_squared; + fmpz_init_set(n_squared, n); + fmpz_pow_ui(n_squared, n_squared, 2); + for (i = 0; i < m; i++) { + fmpz *m_i_i = fmpz_mat_entry(A, i, i); + fmpz_set(m_i_i, n_squared); + } + fmpz_clear(n_squared); + + // setting up last two diagonal entries + fmpz *m_i_i = fmpz_mat_entry(A, m, m); + fmpz_set(m_i_i, B); + m_i_i = fmpz_mat_entry(A, m + 1, m + 1); + fmpz_mul(m_i_i, B, n); + + // columnwise setup + for (i = 0; i < m; i++) { + // t[i]*n + fmpz *tmp = fmpz_mat_entry(A, m, i); + fmpz_mul(tmp, &t[i], n); + + // a[i]*n + tmp = fmpz_mat_entry(A, m + 1, i); + fmpz_mul(tmp, &a[i], n); + } + + // use LLL for lattice reduction (delta = 0.99, eta = 0.501) + fmpq_t delta, eta; + fmpq_init(delta); + fmpq_init(eta); + fmpq_set_ui(delta, 99, 100); + fmpq_set_ui(eta, 501, 1000); + + fmpz_mat_lll_original(A, delta, eta); + + fmpq_clear(delta); + fmpq_clear(eta); + + // extract the potential solution + fmpz_t Bn; + fmpz_init(Bn); + fmpz_mul(Bn, B, n); + for (i = 0; i < m + 2; i++) { + if (fmpz_cmpabs(fmpz_mat_entry(A, i, m + 1), Bn) == 0) + break; + } + if (i >= m + 2) + return 1; + fmpz_clear(Bn); + + slong r = i; + + for (i = 0; i < m; i++) { + fmpz *tmp = fmpz_mat_entry(A, r, i); + fmpz_tdiv_q(&res[i], tmp, n); + } + fmpz_tdiv_q(&res[m], fmpz_mat_entry(A, r, m), B); + + fmpz_mat_clear(A); + + // test that the solution is a solution to original HNP + fmpz_t tmp; + fmpz_init(tmp); + + for (i = 0; i < m; i++) { + // tmp <- t[i]*alpha - a[i] mod n + fmpz_mul(tmp, &t[i], &res[m]); + fmpz_add(tmp, tmp, &a[i]); + fmpz_sub(tmp, tmp, &res[i]); + fmpz_mod(tmp, tmp, n); + + if (fmpz_cmp_ui(tmp, 0) != 0) { + fmpz_clear(tmp); + return 1; + } + } + + fmpz_clear(tmp); + + return 0; +} diff --git a/hnp.h b/hnp.h @@ -0,0 +1,30 @@ +#ifndef HNP_H +#define HNP_H + +#include <flint.h> +#include <fmpq.h> +#include <fmpz.h> +#include <fmpz_mat.h> +#include <gmp.h> + +/** + * Solve the hidden number problem + * t[i]*alpha - a[i] == b[i] (mod n), i = 0,1,...,m-1 + * for + * b[i], i = 0,1,...,m-1, and + * alpha + * where |b[i]| < B. + * + * @param res + * an already initialised vector that has size nres, this vector + * may be overwritten even if the result is not verified + * @return + * -1 if failure (ex. res too small to fit m+1 values) + * 1 if reduction okay, but solution fails to verify + * 0 if solution found + */ +int hidden_number_problem(fmpz *res, const slong nres, const fmpz *t, + const fmpz *a, const slong m, const fmpz_t n, + const fmpz_t B); + +#endif diff --git a/smallfactor.c b/smallfactor.c @@ -0,0 +1,5 @@ +#include "smallfactor.h" + +int smallfactor(int x, int y) { + return x * y; +} diff --git a/smallfactor.h b/smallfactor.h @@ -0,0 +1,8 @@ +#ifndef SMALLFACTOR_H +#define SMALLFACTOR_H + +#include <stdlib.h> + +int smallfactor(int x, int y); + +#endif diff --git a/test_angrepp.c b/test_angrepp.c @@ -0,0 +1,7 @@ +#include <stdlib.h> +#include <stdio.h> +#include <assert.h> + +int main() { + printf("test unimplemented\n"); +} diff --git a/tools/hnpsolve.c b/tools/hnpsolve.c @@ -0,0 +1,103 @@ +#include <stdlib.h> +#include <stdio.h> +#include <flint.h> +#include <fmpz_vec.h> +#include <hnp.h> + +#define LINE_SIZE_MAX 4096 + +static int read_next_fmpz(fmpz_t res) +{ + char buffer[LINE_SIZE_MAX]; + size_t i; + + int next_char = getchar(); + while(next_char == '\n' || next_char == ' ') + next_char = getchar(); + + if(next_char == EOF) + return -1; + + buffer[0] = next_char; + i = 1; + while(i < LINE_SIZE_MAX-1) { + next_char = getchar(); + if(next_char == EOF || next_char == '\n' || next_char == ' ') + break; + + buffer[i] = (char) next_char; + + i++; + } + buffer[i] = '\0'; + + return fmpz_set_str(res, buffer, 10); +} + +static int read_stdin_instance(fmpz** a, fmpz** t, slong* m, fmpz_t* B, fmpz_t* n) +{ + flint_scanf("%wd", m); + + if(read_next_fmpz(*B)) + return -1; + + if(read_next_fmpz(*n)) + return -1; + + *a = _fmpz_vec_init(*m); + *t = _fmpz_vec_init(*m); + + + slong i; + int fail = 0; + for(i = 0; i < *m; i++) { + if(read_next_fmpz(&(*t)[i])) { + fail = 1; + break; + } + + if(read_next_fmpz(&(*a)[i])) { + fail = 1; + break; + } + } + + if(fail) { + _fmpz_vec_clear(*a, *m); + _fmpz_vec_clear(*t, *m); + return -1; + } + + return 0; +} + +int main(int argc, char* argv[]) +{ + slong m; + fmpz* a; + fmpz* t; + fmpz_t B, n; + fmpz_init(B); + fmpz_init(n); + + if(read_stdin_instance(&a, &t, &m, &B, &n) != 0) { + fprintf(stderr, "ERROR! Bad input format?\n"); + exit(1); + } + + fmpz res[m+1]; + slong i; + for(i = 0; i < m+1; i++) fmpz_init(&res[i]); + + int ret = hidden_number_problem(res, m+1, t, a, m, n, B); + if(ret == 0) { + for(i = 0; i < m; i++) { + fmpz_print(&res[i]); + printf(" "); + } + fmpz_print(&res[m]); + printf("\n"); + } + + return 0; +}