| @@ -5,12 +5,15 @@ ii = sqrt(F(-1)) | |||
| def lobit(x): return int(x) & 1 | |||
| def hibit(x): return lobit(2*x) | |||
| magic = sqrt(F(-121666)) | |||
| magic = sqrt(dM-1) | |||
| if lobit(magic): magic = -magic | |||
| def eddsa_decode(y): | |||
| hi = int(y) & 2^255 | |||
| y = F(y-hi) | |||
| def eddsa_decode(y_ser): | |||
| """ | |||
| Recover x,y corresponding to the eddsa standard representation. | |||
| """ | |||
| hi = int(y_ser) & 2^255 | |||
| y = F(y_ser-hi) | |||
| x = sqrt((y^2-1)/(d*y^2+1)) | |||
| if int(x) & 1: x = -x | |||
| @@ -37,6 +40,11 @@ def eddsa_to_decaf(x,y): | |||
| return s | |||
| def isqrt_trick(to_isr,to_inv): | |||
| """ | |||
| The "inverse square root" trick: | |||
| Return 1/sqrt(to_isr), 1/to_inv. | |||
| Also return their product because that turns out to be useful. | |||
| """ | |||
| to_sqrt = to_isr*to_inv^2 | |||
| if to_sqrt == 0: return 0,0,0 # This happens automatically in C; just to avoid problems in SAGE | |||
| @@ -58,7 +66,7 @@ def eddsa_to_decaf_opt(x,y,z=None): | |||
| but whatever. | |||
| """ | |||
| if z is None: | |||
| # Pretend that we're in projective | |||
| # Pretend that we're in projective coordinates | |||
| z = F.random_element() | |||
| x *= z | |||
| y *= z | |||
| @@ -105,9 +113,9 @@ def decaf_to_eddsa(s): | |||
| def decaf_to_eddsa_opt(s): | |||
| """ | |||
| Convert a Decaf representation to an EdDSA point, in a manner compatible | |||
| with libdecaf. | |||
| with libdecaf. Optimized to use only one invsqrt. | |||
| This function is slightly less horrible if we don't want to decode to affine. | |||
| This function would be slightly simpler if we didn't want to decode to affine. | |||
| """ | |||
| if s < 0 or s >= F.modulus(): raise Exception("out of field!") | |||
| s = F(s) | |||
| @@ -118,13 +126,13 @@ def decaf_to_eddsa_opt(s): | |||
| isr,inv,isr_times_inv = isqrt_trick(curve_eqn,s*(1-s^2)*(1+s^2)) | |||
| if isr == 0: raise Exception("Invalid: nonstandard encoding of zero") | |||
| t = isr_times_inv * curve_eqn * (1-s^2) * (1+s^2) | |||
| x = 2 * magic * s * isr | |||
| y = (1-s^2)^2 * s * inv | |||
| hibit_t = hibit(t) | |||
| tmp = isr_times_inv * curve_eqn * (1+s^2) # = sqrt(curve_eqn) / s / (1-s^2) | |||
| hibit_t = hibit(tmp * (1-s^2)) | |||
| if hibit_t: x = -x | |||
| if lobit(t * (1+s^2)^2 * s * inv) != hibit_t: raise Exception("invalid: t/y has high bit") | |||
| if lobit(tmp * (1+s^2)) != hibit_t: raise Exception("invalid: bits don't match") | |||
| assert y^2 - x^2 == 1+d*x^2*y^2 | |||
| return (x,y) | |||
| @@ -53,8 +53,10 @@ void decaf_sponge_init ( | |||
| * @param [inout] sponge The context. | |||
| * @param [in] in The input data. | |||
| * @param [in] len The input data's length in bytes. | |||
| * @return DECAF_FAILURE if the sponge has already been used for output. | |||
| * @return DECAF_SUCCESS otherwise. | |||
| */ | |||
| void decaf_sha3_update ( | |||
| decaf_error_t decaf_sha3_update ( | |||
| struct decaf_keccak_sponge_s * __restrict__ sponge, | |||
| const uint8_t *in, | |||
| size_t len | |||
| @@ -156,8 +158,8 @@ decaf_error_t decaf_sponge_hash ( | |||
| static inline void DECAF_NONNULL decaf_shake##n##_gen_init(decaf_keccak_sponge_t sponge) { \ | |||
| decaf_sponge_init(sponge, &DECAF_SHAKE##n##_params_s); \ | |||
| } \ | |||
| static inline void DECAF_NONNULL decaf_shake##n##_update(decaf_shake##n##_ctx_t sponge, const uint8_t *in, size_t inlen ) { \ | |||
| decaf_sha3_update(sponge->s, in, inlen); \ | |||
| static inline decaf_error_t DECAF_NONNULL decaf_shake##n##_update(decaf_shake##n##_ctx_t sponge, const uint8_t *in, size_t inlen ) { \ | |||
| return decaf_sha3_update(sponge->s, in, inlen); \ | |||
| } \ | |||
| static inline void DECAF_NONNULL decaf_shake##n##_final(decaf_shake##n##_ctx_t sponge, uint8_t *out, size_t outlen ) { \ | |||
| decaf_sha3_output(sponge->s, out, outlen); \ | |||
| @@ -182,8 +184,8 @@ decaf_error_t decaf_sponge_hash ( | |||
| static inline void DECAF_NONNULL decaf_sha3_##n##_gen_init(decaf_keccak_sponge_t sponge) { \ | |||
| decaf_sponge_init(sponge, &DECAF_SHA3_##n##_params_s); \ | |||
| } \ | |||
| static inline void DECAF_NONNULL decaf_sha3_##n##_update(decaf_sha3_##n##_ctx_t sponge, const uint8_t *in, size_t inlen ) { \ | |||
| decaf_sha3_update(sponge->s, in, inlen); \ | |||
| static inline decaf_error_t DECAF_NONNULL decaf_sha3_##n##_update(decaf_sha3_##n##_ctx_t sponge, const uint8_t *in, size_t inlen ) { \ | |||
| return decaf_sha3_update(sponge->s, in, inlen); \ | |||
| } \ | |||
| static inline decaf_error_t DECAF_NONNULL decaf_sha3_##n##_final(decaf_sha3_##n##_ctx_t sponge, uint8_t *out, size_t outlen ) { \ | |||
| decaf_error_t ret = decaf_sha3_output(sponge->s, out, outlen); \ | |||
| @@ -53,8 +53,10 @@ void decaf_sponge_init ( | |||
| * @param [inout] sponge The context. | |||
| * @param [in] in The input data. | |||
| * @param [in] len The input data's length in bytes. | |||
| * @return DECAF_FAILURE if the sponge has already been used for output. | |||
| * @return DECAF_SUCCESS otherwise. | |||
| */ | |||
| void decaf_sha3_update ( | |||
| decaf_error_t decaf_sha3_update ( | |||
| struct decaf_keccak_sponge_s * __restrict__ sponge, | |||
| const uint8_t *in, | |||
| size_t len | |||
| @@ -156,8 +158,8 @@ decaf_error_t decaf_sponge_hash ( | |||
| static inline void DECAF_NONNULL decaf_shake##n##_gen_init(decaf_keccak_sponge_t sponge) { \ | |||
| decaf_sponge_init(sponge, &DECAF_SHAKE##n##_params_s); \ | |||
| } \ | |||
| static inline void DECAF_NONNULL decaf_shake##n##_update(decaf_shake##n##_ctx_t sponge, const uint8_t *in, size_t inlen ) { \ | |||
| decaf_sha3_update(sponge->s, in, inlen); \ | |||
| static inline decaf_error_t DECAF_NONNULL decaf_shake##n##_update(decaf_shake##n##_ctx_t sponge, const uint8_t *in, size_t inlen ) { \ | |||
| return decaf_sha3_update(sponge->s, in, inlen); \ | |||
| } \ | |||
| static inline void DECAF_NONNULL decaf_shake##n##_final(decaf_shake##n##_ctx_t sponge, uint8_t *out, size_t outlen ) { \ | |||
| decaf_sha3_output(sponge->s, out, outlen); \ | |||
| @@ -182,8 +184,8 @@ decaf_error_t decaf_sponge_hash ( | |||
| static inline void DECAF_NONNULL decaf_sha3_##n##_gen_init(decaf_keccak_sponge_t sponge) { \ | |||
| decaf_sponge_init(sponge, &DECAF_SHA3_##n##_params_s); \ | |||
| } \ | |||
| static inline void DECAF_NONNULL decaf_sha3_##n##_update(decaf_sha3_##n##_ctx_t sponge, const uint8_t *in, size_t inlen ) { \ | |||
| decaf_sha3_update(sponge->s, in, inlen); \ | |||
| static inline decaf_error_t DECAF_NONNULL decaf_sha3_##n##_update(decaf_sha3_##n##_ctx_t sponge, const uint8_t *in, size_t inlen ) { \ | |||
| return decaf_sha3_update(sponge->s, in, inlen); \ | |||
| } \ | |||
| static inline decaf_error_t DECAF_NONNULL decaf_sha3_##n##_final(decaf_sha3_##n##_ctx_t sponge, uint8_t *out, size_t outlen ) { \ | |||
| decaf_error_t ret = decaf_sha3_output(sponge->s, out, outlen); \ | |||
| @@ -85,12 +85,11 @@ void keccakf(kdomain_t state, uint8_t start_round) { | |||
| for (i=0; i<25; i++) a[i] = htole64(a[i]); | |||
| } | |||
| void decaf_sha3_update ( | |||
| decaf_error_t decaf_sha3_update ( | |||
| struct decaf_keccak_sponge_s * __restrict__ decaf_sponge, | |||
| const uint8_t *in, | |||
| size_t len | |||
| ) { | |||
| if (!len) return; | |||
| assert(decaf_sponge->params->position < decaf_sponge->params->rate); | |||
| assert(decaf_sponge->params->rate < sizeof(decaf_sponge->state)); | |||
| assert(decaf_sponge->params->flags == FLAG_ABSORBING); | |||
| @@ -100,7 +99,7 @@ void decaf_sha3_update ( | |||
| if (cando > len) { | |||
| for (i = 0; i < len; i += 1) state[i] ^= in[i]; | |||
| decaf_sponge->params->position += len; | |||
| return; | |||
| break; | |||
| } else { | |||
| for (i = 0; i < cando; i += 1) state[i] ^= in[i]; | |||
| dokeccak(decaf_sponge); | |||
| @@ -108,6 +107,7 @@ void decaf_sha3_update ( | |||
| in += cando; | |||
| } | |||
| } | |||
| return (decaf_sponge->params->flags == FLAG_ABSORBING) ? DECAF_SUCCESS : DECAF_FAILURE; | |||
| } | |||
| decaf_error_t decaf_sha3_output ( | |||
| @@ -136,6 +136,7 @@ decaf_error_t decaf_sha3_output ( | |||
| state[decaf_sponge->params->position] ^= decaf_sponge->params->pad; | |||
| state[decaf_sponge->params->rate - 1] ^= decaf_sponge->params->rate_pad; | |||
| dokeccak(decaf_sponge); | |||
| decaf_sponge->params->flags = FLAG_SQUEEZING; | |||
| break; | |||
| } | |||
| default: | |||
| @@ -173,6 +174,7 @@ void decaf_sha3_reset ( | |||
| decaf_keccak_sponge_t decaf_sponge | |||
| ) { | |||
| decaf_sponge_init(decaf_sponge, decaf_sponge->params); | |||
| decaf_sponge->params->flags = FLAG_ABSORBING; | |||
| decaf_sponge->params->remaining = decaf_sponge->params->max_out; | |||
| } | |||