feat(crypto): introduce bn_reduce and bn_copy_lower

tychovrahe/trdisplay/qr
Ondřej Vejpustek 8 months ago
parent 2b00c72094
commit 93bb4c2e35

@ -80,6 +80,15 @@
#define BN_MAX_DECIMAL_DIGITS \
79 // floor(log(2**(LIMBS * BITS_PER_LIMB), 10)) + 1
// y = (bignum256) x
// Assumes x is normalized and x < 2**261 == 2**(BITS_PER_LIMB * LIMBS)
// Guarantees y is normalized
void bn_copy_lower(const bignum512 *x, bignum256 *y) {
for (int i = 0; i < BN_LIMBS; i++) {
y->val[i] = x->val[i];
}
}
// out_number = (bignum256) in_number
// Assumes in_number is a raw bigendian 256-bit number
// Guarantees out_number is normalized
@ -667,12 +676,11 @@ void bn_multiply_reduce_step(bignum512 *res, const bignum256 *prime,
res->val[d + BN_LIMBS] = 0;
}
// Auxiliary function for bn_multiply
// Partly reduces res and stores both in x and res
// Assumes res in normalized and res < 2**519
// Partly reduces x
// Assumes x in normalized and res < 2**519
// Guarantees x is normalized and partly reduced modulo prime
// Assumes prime is normalized, 2**256 - 2**224 <= prime <= 2**256
void bn_multiply_reduce(bignum256 *x, bignum512 *res, const bignum256 *prime) {
void bn_reduce(bignum512 *x, const bignum256 *prime) {
for (int i = BN_LIMBS - 1; i >= 0; i--) {
// res < 2**(256 + 29*i + 31)
// Proof:
@ -683,11 +691,7 @@ void bn_multiply_reduce(bignum256 *x, bignum512 *res, const bignum256 *prime) {
// else:
// res < 2 * prime * 2**(29 * (i + 1))
// <= 2**256 * 2**(29*i + 29) < 2**(256 + 29*i + 31)
bn_multiply_reduce_step(res, prime, i);
}
for (int i = 0; i < BN_LIMBS; i++) {
x->val[i] = res->val[i];
bn_multiply_reduce_step(x, prime, i);
}
}
@ -699,7 +703,8 @@ void bn_multiply(const bignum256 *k, bignum256 *x, const bignum256 *prime) {
bignum512 res = {0};
bn_multiply_long(k, x, &res);
bn_multiply_reduce(x, &res, prime);
bn_reduce(&res, prime);
bn_copy_lower(&res, x);
memzero(&res, sizeof(res));
}

@ -72,6 +72,7 @@ static inline void write_le(uint8_t *data, uint32_t x) {
data[0] = x;
}
void bn_copy_lower(const bignum512 *x, bignum256 *y);
void bn_read_be(const uint8_t *in_number, bignum256 *out_number);
void bn_write_be(const bignum256 *in_number, uint8_t *out_number);
void bn_read_le(const uint8_t *in_number, bignum256 *out_number);
@ -99,6 +100,7 @@ void bn_mult_half(bignum256 *x, const bignum256 *prime);
void bn_mult_k(bignum256 *x, uint8_t k, const bignum256 *prime);
void bn_mod(bignum256 *x, const bignum256 *prime);
void bn_multiply(const bignum256 *k, bignum256 *x, const bignum256 *prime);
void bn_reduce(bignum512 *x, const bignum256 *prime);
void bn_fast_mod(bignum256 *x, const bignum256 *prime);
void bn_power_mod(const bignum256 *x, const bignum256 *e,
const bignum256 *prime, bignum256 *res);

@ -197,6 +197,16 @@ class Random(random.Random):
return self.rand_bignum(2 * limbs_number)
def assert_bn_copy_lower(x):
x_number = int_to_bignum512(x)
y_number = bignum256()
lib.bn_copy_lower(x_number, y_number)
y = bignum256_to_int(y_number)
assert bignum_is_normalised(y_number)
assert y == x
def assert_bn_read_be(in_number):
raw_in_number = integer_to_raw_number256(in_number, "big")
bn_out_number = bignum256()
@ -458,6 +468,17 @@ def assert_bn_multiply(k, x_old, prime):
assert x_new % prime == (k * x_old) % prime
def assert_bn_reduce(x_old, prime):
bn_x = int_to_bignum512(x_old)
bn_prime = int_to_bignum256(prime)
lib.bn_reduce(bn_x, bn_prime)
x_new = bignum256_to_int(bn_x)
assert bignum_is_normalised(bn_x)
assert number_is_partly_reduced(x_new, prime)
assert x_new % prime == x_old % prime
def assert_bn_fast_mod(x_old, prime):
bn_x = int_to_bignum256(x_old)
bn_prime = int_to_bignum256(prime)
@ -731,6 +752,10 @@ def assert_bn_format(x, prefix, suffix, decimals, exponent, trailing, thousands)
assert return_value == correct_return_value
def test_bn_copy_lower(r):
assert_bn_copy_lower(r.rand_int_bitsize(261))
def test_bn_read_be(r):
assert_bn_read_be(r.rand_int_256())
@ -916,6 +941,11 @@ def test_bn_multiply_reduce_step(r, prime):
assert_bn_multiply_reduce_step(res, prime, k)
def test_bn_reduce(r, prime):
x = r.rand_int_bitsize(519)
assert_bn_reduce(x, prime)
def test_bn_multiply(r, prime):
x = r.randrange(floor(sqrt(2**519)))
k = r.randrange(floor(sqrt(2**519)))

Loading…
Cancel
Save