From 7a5b8998250a69db6af683e6e353fda8fd72ba60 Mon Sep 17 00:00:00 2001 From: hasufell Date: Mon, 26 May 2014 20:59:12 +0200 Subject: [PATCH] ENC/DEC: allow encryption/decryption of strings --- src/ascii_poly.c | 103 ++++++++++++++++++++++++++++++++++++++++++++--- src/ascii_poly.h | 74 ++++++++++++++++++++++++++++++---- src/common.h | 22 ++++++++++ src/decrypt.c | 35 ++++++++++++++-- src/decrypt.h | 23 +++++++++-- src/encrypt.c | 40 +++++++++++++++++- src/encrypt.h | 37 ++++++++++++++--- 7 files changed, 308 insertions(+), 26 deletions(-) diff --git a/src/ascii_poly.c b/src/ascii_poly.c index ad1904c..7b23986 100644 --- a/src/ascii_poly.c +++ b/src/ascii_poly.c @@ -111,7 +111,7 @@ get_bin_arr_to_ascii(char *binary_rep) } fmpz_poly_t ** -ascii_to_poly(char *to_poly, ntru_context *ctx) +ascii_to_tern_poly(char *to_poly, ntru_context *ctx) { uint32_t i = 0, polyc = 0; @@ -145,6 +145,14 @@ ascii_to_poly(char *to_poly, ntru_context *ctx) i++; j++; } + + /* fill the last poly with 2 */ + for (uint32_t i = j; i < ctx->N; i++) { + fmpz_poly_set_coeff_si(*new_poly, + i, + 2); + } + polyc++; } @@ -155,8 +163,50 @@ ascii_to_poly(char *to_poly, ntru_context *ctx) return poly_array; } +fmpz_poly_t ** +ascii_to_poly(string *to_poly, ntru_context *ctx) +{ + uint32_t i = 0, + polyc = 0; + fmpz_poly_t **poly_array; + + poly_array = ntru_malloc(sizeof(**poly_array) * + (strlen(to_poly->ptr) / ctx->N)); + + while (i < to_poly->len) { + uint32_t j = 0; + fmpz_poly_t *new_poly = ntru_malloc(sizeof(*new_poly)); + + fmpz_poly_init(*new_poly); + poly_array[polyc] = new_poly; + + while (i < to_poly->len && j < ctx->N) { + fmpz_poly_set_coeff_si(*new_poly, + j, + (uint8_t)(to_poly->ptr[i])); + i++; + j++; + } + + /* fill the last poly with q (which is a non-standard + * coefficient) */ + for (uint32_t i = j; i < ctx->N; i++) { + fmpz_poly_set_coeff_si(*new_poly, + i, + ctx->q); + } + + polyc++; + + } + + poly_array[polyc] = NULL; + + return poly_array; +} + char * -poly_to_ascii(fmpz_poly_t **poly_array, ntru_context *ctx) +tern_poly_to_ascii(fmpz_poly_t **tern_poly_arr, ntru_context *ctx) { fmpz_poly_t *ascii_poly; char *binary_rep = NULL; @@ -169,7 +219,7 @@ poly_to_ascii(fmpz_poly_t **poly_array, ntru_context *ctx) * parse the polynomial coefficients into a string */ binary_rep = ntru_malloc(CHAR_SIZE * (ctx->N + 1)); - while ((ascii_poly = *poly_array++)) { + while ((ascii_poly = *tern_poly_arr++)) { new_length = CHAR_SIZE * (ctx->N + 1); REALLOC(binary_rep, @@ -187,8 +237,8 @@ poly_to_ascii(fmpz_poly_t **poly_array, ntru_context *ctx) binary_rep[i] = '0'; else if (fmpz_cmp_si(coeff, -1)) binary_rep[i] = '1'; - } else { - binary_rep[i] = '0'; + else if (fmpz_cmp_si(coeff, 2)) + binary_rep[i] = '0'; } i++; } @@ -201,3 +251,46 @@ poly_to_ascii(fmpz_poly_t **poly_array, ntru_context *ctx) return ascii_string; } + +string * +poly_to_ascii(fmpz_poly_t **poly_array, + ntru_context *ctx) +{ + fmpz_poly_t *ascii_poly; + char *string_rep = NULL; + string *result_string = ntru_malloc(sizeof(*result_string)); + uint32_t i = 0; + size_t old_length = 0, + new_length; + + /* + * parse the polynomial coefficients into a string + */ + string_rep = ntru_malloc(CHAR_SIZE * (ctx->N + 1)); + while ((ascii_poly = *poly_array++)) { + new_length = CHAR_SIZE * (ctx->N + 1); + + REALLOC(string_rep, + old_length + + new_length + + 1); /* trailing null byte */ + + old_length += new_length; + + for (uint32_t j = 0; j < ctx->N; j++) { + uint8_t coeff = fmpz_poly_get_coeff_ui(*ascii_poly, j); + if (coeff == ctx->q) + string_rep[i] = '\0'; + else + string_rep[i] = (char)coeff; + i++; + } + } + + string_rep[i] = '\0'; + + result_string->ptr = string_rep; + result_string->len = i; + + return result_string; +} diff --git a/src/ascii_poly.h b/src/ascii_poly.h index 4acdf89..95f9375 100644 --- a/src/ascii_poly.h +++ b/src/ascii_poly.h @@ -29,6 +29,7 @@ #define NTRU_ASCII_POLY_H_ +#include "common.h" #include "context.h" #include @@ -36,24 +37,83 @@ /** - * Convert an ascii string to an array of polyomials. + * Convert an ascii string to an array of ternary polyomials. + * The ascii string will be converted to a binary representation + * and the following mapping will apply between binary -> poly: * - * @param to_poly the string to get into polynomial format + * 1 => 1 + * + * 0 => -1 + * + * If the last polynomial is of degree less than N -1, then it will + * be filled with trailing 2's for later use in tern_poly_to_ascii(). + * + * @param to_poly the string to get into ternary polynomial format + * @param ctx the NTRUEncrypt context + * @return newly allocated array of ternary polynomials + */ +fmpz_poly_t ** +ascii_to_tern_poly(char *to_poly, ntru_context *ctx); + +/** + * Convert an ascii string to an array of polyomials with coefficients + * which are expected to be in the range {0, q-1}. + * The chars will be converted to their integer representation and + * directly put into the coefficients. + * + * If the last polynomial is of degree less than N -1, then it will + * be filled with trailing q's for later user in poly_to_ascii(). + * + * @param to_poly the string to get into polynomial format, + * which is of type string, so we can iterate safely over it + * (the string might have null-bytes in the middle of it) * @param ctx the NTRUEncrypt context * @return newly allocated array of polynomials */ fmpz_poly_t ** -ascii_to_poly(char *to_poly, ntru_context *ctx); +ascii_to_poly(string *to_poly, ntru_context *ctx); + +/** + * Convert an array of ternary polynomials back to a real string. + * The polynomial coefficients represent a binary format of the + * ascii string with the following mapping: + * + * 1 => 1 + * + * -1 => 0 + * + * 2 => 0 + * + * The 2's are only used for filling up the last polynomial, so they will + * just end up as '\0's at the end of the string and will not confuse + * the result. + * + * @param tern_poly_arr the array of polynomials + * @param ctx the NTRUEncrypt context + * @return the real string, newly allocated + */ +char * +tern_poly_to_ascii(fmpz_poly_t **tern_poly_arr, ntru_context *ctx); /** * Convert an array of polynomials back to a real string. + * The polynomial coefficients are expected to be in the range + * {0, q-1} and will be casted back to chars without any mapping. * - * @param poly_array the array of polynomials + * Trailing q's are only used for filling up the last polynomial, + * so they will just end up as '\0's at the end of the string and + * will not confuse the result. + * + * A struct of type string is returned, because we cannot + * rely on null-termination in ascii_to_poly(), since there + * may be null-bytes in the middle of the string as well. + * + * @param poly_arr the array of polynomials * @param ctx the NTRUEncrypt context - * @return the real string + * @return the real string, newly allocated */ -char * -poly_to_ascii(fmpz_poly_t **poly_array, ntru_context *ctx); +string * +poly_to_ascii(fmpz_poly_t **poly_arr, ntru_context *ctx); #endif /* NTRU_ASCII_POLY_H_ */ diff --git a/src/common.h b/src/common.h index d8dc4d0..1cc744a 100644 --- a/src/common.h +++ b/src/common.h @@ -31,8 +31,30 @@ #define NTRU_COMMON_H +#include + + #define CHAR_SIZE sizeof(char) #define ASCII_BITS 8 +typedef struct string string; + + +/** + * Represents a string. + */ +struct string { + /** + * Pointer to the char array, + * holding the actual string. + */ + char *ptr; + /** + * Length of the string. + */ + size_t len; +}; + + #endif /* NTRU_COMMON_H */ diff --git a/src/decrypt.c b/src/decrypt.c index a0026c4..c11975d 100644 --- a/src/decrypt.c +++ b/src/decrypt.c @@ -26,8 +26,11 @@ * @brief NTRU decryption */ +#include "ascii_poly.h" #include "decrypt.h" +#include + #include #include @@ -37,7 +40,7 @@ ntru_decrypt_poly( fmpz_poly_t encr_msg, fmpz_poly_t priv_key, fmpz_poly_t priv_key_inv, - fmpz_poly_t out, + fmpz_poly_t out_tern, ntru_context *ctx) { fmpz_poly_t a; @@ -47,8 +50,34 @@ ntru_decrypt_poly( poly_starmultiply(priv_key, encr_msg, a, ctx, ctx->q); fmpz_poly_mod(a, ctx->q); - poly_starmultiply(a, priv_key_inv, out, ctx, ctx->p); - fmpz_poly_mod(out, ctx->p); + poly_starmultiply(a, priv_key_inv, out_tern, ctx, ctx->p); + fmpz_poly_mod(out_tern, ctx->p); fmpz_poly_clear(a); } + +char * +ntru_decrypt_string( + string *encr_msg, + fmpz_poly_t priv_key, + fmpz_poly_t priv_key_inv, + ntru_context *ctx) +{ + uint32_t i = 0; + char *decr_msg; + fmpz_poly_t **poly_array; + + poly_array = ascii_to_poly(encr_msg, ctx); + + while (*poly_array[i]) { + ntru_decrypt_poly(*poly_array[i], priv_key, priv_key_inv, + *poly_array[i], ctx); + i++; + } + + decr_msg = tern_poly_to_ascii(poly_array, ctx); + + poly_delete_array(poly_array); + + return decr_msg; +} diff --git a/src/decrypt.h b/src/decrypt.h index 01a9f67..000b9c4 100644 --- a/src/decrypt.h +++ b/src/decrypt.h @@ -28,8 +28,9 @@ #ifndef NTRU_DECRYPT_H #define NTRU_DECRYPT_H -#include "poly.h" +#include "common.h" #include "context.h" +#include "poly.h" #include #include @@ -44,7 +45,7 @@ * @param priv_key the polynom containing the private key to decrypt * the message * @param priv_key_inv the inverse polynome to the private key - * @param out the result polynom is written in here [out] + * @param out_tern the resulting ternary polynom [out] * @param ctx the ntru_context */ void @@ -52,7 +53,23 @@ ntru_decrypt_poly( fmpz_poly_t encr_msg, fmpz_poly_t priv_key, fmpz_poly_t priv_key_inv, - fmpz_poly_t out, + fmpz_poly_t out_tern, + ntru_context *ctx); + +/** + * Decryption of a given encrypted string. + * + * @param encr_msg the encrypted message in the form of a string + * @param priv_key the polynom containing the private key to decrypt + * the message + * @param priv_key_inv the inverse polynome to the private key + * @param ctx the ntru_context + */ +char * +ntru_decrypt_string( + string *encr_msg, + fmpz_poly_t priv_key, + fmpz_poly_t priv_key_inv, ntru_context *ctx); diff --git a/src/encrypt.c b/src/encrypt.c index 388a61d..097372f 100644 --- a/src/encrypt.c +++ b/src/encrypt.c @@ -26,7 +26,11 @@ * @brief NTRU encryption */ +#include "ascii_poly.h" #include "encrypt.h" +#include "mem.h" + +#include #include #include @@ -34,14 +38,46 @@ void ntru_encrypt_poly( - fmpz_poly_t msg, + fmpz_poly_t msg_tern, fmpz_poly_t pub_key, fmpz_poly_t rnd, fmpz_poly_t out, ntru_context *ctx) { + /* allow aliasing */ + fmpz_poly_t tmp_poly_msg; + fmpz_poly_init(tmp_poly_msg); + fmpz_poly_set(tmp_poly_msg, msg_tern); + fmpz_poly_zero(out); poly_starmultiply(pub_key, rnd, out, ctx, ctx->q); - fmpz_poly_add(out, out, msg); + fmpz_poly_add(out, out, tmp_poly_msg); fmpz_poly_mod_unsigned(out, ctx->q); + + fmpz_poly_clear(tmp_poly_msg); +} + +string * +ntru_encrypt_string( + char *msg, + fmpz_poly_t pub_key, + fmpz_poly_t rnd, + ntru_context *ctx) +{ + uint32_t i = 0; + string *enc_msg; + fmpz_poly_t **poly_array; + + poly_array = ascii_to_tern_poly(msg, ctx); + + while (*poly_array[i]) { + ntru_encrypt_poly(*poly_array[i], pub_key, rnd, *poly_array[i], ctx); + i++; + } + + enc_msg = poly_to_ascii(poly_array, ctx); + + poly_delete_array(poly_array); + + return enc_msg; } diff --git a/src/encrypt.h b/src/encrypt.h index b90254f..4b0420a 100644 --- a/src/encrypt.h +++ b/src/encrypt.h @@ -29,6 +29,7 @@ #define PQC_ENCRYPT_H +#include "common.h" #include "context.h" #include "poly.h" @@ -41,24 +42,48 @@ * e = (h ∗ r) + m (mod q) * * e = the encrypted poly + * * h = the public key + * * r = the random poly + * * m = the message poly + * * q = large mod * - * @param msg pb_poly* the message to encrypt - * @param pub_key pb_poly* the public key - * @param rnd pb_poly* the random poly - * @param out pb_poly* the output poly [out] - * @param ctx ntru_context* the ntru context + * @param msg_tern the message to encrypt, in ternary format + * @param pub_key the public key + * @param rnd the random poly (should have relatively small + * coefficients, but not restricted to {-1, 0, 1}) + * @param out the output poly which is in the range {0, q-1} + * (not ternary!) [out] + * @param ctx ntru_context the ntru context */ void ntru_encrypt_poly( - fmpz_poly_t msg, + fmpz_poly_t msg_tern, fmpz_poly_t pub_key, fmpz_poly_t rnd, fmpz_poly_t out, ntru_context *ctx); +/** + * Encrypt a message int he form of a null-terminated char array and + * return a string. + * + * @param msg the message + * @param pub_key the public key + * @param rnd the random poly (should have relatively small + * coefficients, but not restricted to {-1, 0, 1}) + * @param ctx ntru_context the ntru context + * @return the newly allocated encrypted string + */ +string * +ntru_encrypt_string( + char *msg, + fmpz_poly_t pub_key, + fmpz_poly_t rnd, + ntru_context *ctx); + #endif /* PQC_ENCRYPT_H */