uint8_t test_keygen() { NtruEncParams param_arr[] = ALL_PARAM_SETS; uint8_t valid = 1; uint8_t i; NtruRandGen rng = NTRU_RNG_DEFAULT; for (i=0; i<sizeof(param_arr)/sizeof(param_arr[0]); i++) { NtruEncParams params = param_arr[i]; NtruEncKeyPair kp; NtruRandContext rand_ctx; ntru_rand_init(&rand_ctx, &rng); valid &= ntru_gen_key_pair(¶ms, &kp, &rand_ctx) == NTRU_SUCCESS; /* encrypt a random message */ NtruTernPoly m; ntru_rand_tern(params.N, params.N/3, params.N/3, &m, &rand_ctx); NtruIntPoly m_int; ntru_tern_to_int(&m, &m_int); NtruTernPoly r; ntru_rand_tern(params.N, params.N/3, params.N/3, &r, &rand_ctx); ntru_rand_release(&rand_ctx); NtruIntPoly e; encrypt_poly(&m_int, &r, &kp.pub.h, &e, params.q); /* decrypt and verify */ NtruIntPoly c; decrypt_poly(&e, &kp.priv, &c, params.q); valid &= ntru_equals_int(&m_int, &c); /* test deterministic key generation */ valid &= gen_key_pair("my test password", ¶ms, &kp) == NTRU_SUCCESS; char seed2_char[19]; strcpy(seed2_char, "my test password"); uint8_t seed2[strlen(seed2_char)]; str_to_uint8(seed2_char, seed2); NtruEncKeyPair kp2; NtruRandGen rng = NTRU_RNG_IGF2; NtruRandContext rand_ctx2; ntru_rand_init_det(&rand_ctx2, &rng, seed2, strlen(seed2_char)); valid &= ntru_gen_key_pair(¶ms, &kp2, &rand_ctx2) == NTRU_SUCCESS; ntru_rand_release(&rand_ctx2); valid &= equals_key_pair(&kp, &kp2); } print_result("test_keygen", valid); return valid; }
uint8_t ntru_gen_key_pair_single(const NtruEncParams *params, NtruEncPrivKey *priv, NtruEncPubKey *pub, NtruIntPoly *fq, NtruRandContext *rand_ctx) { uint16_t N = params->N; uint16_t q = params->q; uint16_t df1 = params->df1; #ifndef NTRU_AVOID_HAMMING_WT_PATENT uint16_t df2 = params->df2; uint16_t df3 = params->df3; #endif /* NTRU_AVOID_HAMMING_WT_PATENT */ if (q & (q-1)) /* check that modulus is a power of 2 */ return NTRU_ERR_INVALID_PARAM; /* choose a random f that is invertible mod q */ #ifndef NTRU_AVOID_HAMMING_WT_PATENT if (params->prod_flag) { NtruPrivPoly *t = &priv->t; t->prod_flag = 1; t->poly.prod.N = N; priv->q = q; for (;;) { /* choose random t, find the inverse of 3t+1 */ if (!ntru_rand_prod(N, df1, df2, df3, df3, &t->poly.prod, rand_ctx)) return NTRU_ERR_PRNG; if (ntru_invert(t, q-1, fq)) break; } } else #endif /* NTRU_AVOID_HAMMING_WT_PATENT */ { NtruPrivPoly *t = &priv->t; t->prod_flag = 0; priv->q = q; for (;;) { /* choose random t, find the inverse of 3t+1 */ if (!ntru_rand_tern(N, df1, df1, &t->poly.tern, rand_ctx)) return NTRU_ERR_PRNG; if (ntru_invert(t, q-1, fq)) break; } } /* choose a random g */ NtruPrivPoly g; uint8_t result = ntru_gen_g(params, &g, rand_ctx); if (result != NTRU_SUCCESS) return result; NtruIntPoly *h = &pub->h; if (!ntru_mult_priv(&g, fq, h, q-1)) return NTRU_ERR_INVALID_PARAM; ntru_mult_fac(h, 3); ntru_mod_mask(h, q-1); ntru_clear_priv(&g); pub->q = q; return NTRU_SUCCESS; }
/* Generates a random g. If NTRU_CHECK_INVERTIBILITY_G, g will be invertible mod q */ uint8_t ntru_gen_g(const NtruEncParams *params, NtruPrivPoly *g, NtruRandContext *rand_ctx) { uint16_t N = params->N; uint16_t dg = params->dg; for (;;) { if (!ntru_rand_tern(N, dg, dg, &g->poly.tern, rand_ctx)) return NTRU_ERR_PRNG; g->prod_flag = 0; if (!NTRU_CHECK_INVERTIBILITY_G) break; NtruIntPoly gq; if (ntru_invert(g, params->q-1, &gq)) break; } return NTRU_SUCCESS; }
uint8_t ntru_gen_key_pair(const NtruEncParams *params, NtruEncKeyPair *kp, NtruRandContext *rand_ctx) { uint16_t N = params->N; uint16_t q = params->q; uint16_t df1 = params->df1; #ifndef NTRU_AVOID_HAMMING_WT_PATENT uint16_t df2 = params->df2; uint16_t df3 = params->df3; #endif /* NTRU_AVOID_HAMMING_WT_PATENT */ NtruIntPoly fq; /* choose a random f that is invertible mod q */ #ifndef NTRU_AVOID_HAMMING_WT_PATENT if (params->prod_flag) { NtruPrivPoly *t = &kp->priv.t; t->prod_flag = 1; t->poly.prod.N = N; kp->priv.q = q; for (;;) { /* choose random t, find the inverse of 3t+1 */ if (!ntru_rand_prod(N, df1, df2, df3, df3, &t->poly.prod, rand_ctx)) return NTRU_ERR_PRNG; if (ntru_invert(t, q, &fq)) break; } } else #endif /* NTRU_AVOID_HAMMING_WT_PATENT */ { NtruPrivPoly *t = &kp->priv.t; t->prod_flag = 0; kp->priv.q = q; for (;;) { /* choose random t, find the inverse of 3t+1 */ if (!ntru_rand_tern(N, df1, df1, &t->poly.tern, rand_ctx)) return NTRU_ERR_PRNG; if (ntru_invert(t, q, &fq)) break; } } /* choose a random g that is invertible mod q */ NtruPrivPoly g; uint16_t dg = N / 3; for (;;) { #ifndef NTRU_AVOID_HAMMING_WT_PATENT if (params->prod_flag && !ntru_rand_prod(N, df1, df2, df3, df3, &g.poly.prod, rand_ctx)) return NTRU_ERR_PRNG; if (!params->prod_flag && !ntru_rand_tern(N, dg, dg, &g.poly.tern, rand_ctx)) return NTRU_ERR_PRNG; g.prod_flag = params->prod_flag; #else if (!ntru_rand_tern(N, dg, dg, &g.poly.tern, rand_ctx)) return NTRU_ERR_PRNG; g.prod_flag = 0; #endif /* NTRU_AVOID_HAMMING_WT_PATENT */ if (!NTRU_CHECK_INVERTIBILITY_G) break; NtruIntPoly gq; if (ntru_invert(&g, q, &gq)) break; } NtruIntPoly *h = &kp->pub.h; if (!ntru_mult_priv(&g, &fq, h, q)) return NTRU_ERR_PRNG; ntru_mult_fac(h, 3); ntru_mod(h, q); ntru_clear_priv(&g); ntru_clear_int(&fq); kp->pub.q = q; return NTRU_SUCCESS; }