mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-18 04:18:10 +00:00
feat(crypto): implement Legendre symbol
This commit is contained in:
parent
5a9d399012
commit
3a2bdf16dd
@ -1591,6 +1591,39 @@ void bn_subtract(const bignum256 *x, const bignum256 *y, bignum256 *res) {
|
||||
// == 1
|
||||
}
|
||||
|
||||
// Returns 0 if x is zero
|
||||
// Returns 1 if x is a square modulo prime
|
||||
// Returns -1 if x is not a square modulo prime
|
||||
// Assumes x is normalized, x < 2**259
|
||||
// Assumes prime is normalized, 2**256 - 2**224 <= prime <= 2**256
|
||||
// Assumes prime is a prime
|
||||
// The function doesn't have neither constant control flow nor constant memory
|
||||
// access flow with regard to prime
|
||||
int bn_legendre(const bignum256 *x, const bignum256 *prime) {
|
||||
// This is a naive implementation
|
||||
// A better implementation would be to use the Euclidean algorithm together with the quadratic reciprocity law
|
||||
|
||||
// e = (prime - 1) / 2
|
||||
bignum256 e = {0};
|
||||
bn_copy(prime, &e);
|
||||
bn_rshift(&e);
|
||||
|
||||
// res = x**e % prime
|
||||
bignum256 res = {0};
|
||||
bn_power_mod(x, &e, prime, &res);
|
||||
bn_mod(&res, prime);
|
||||
|
||||
if (bn_is_one(&res)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (bn_is_zero(&res)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
// q = x // d, r = x % d
|
||||
// Assumes x is normalized, 1 <= d <= 61304
|
||||
// Guarantees q is normalized
|
||||
|
@ -108,6 +108,7 @@ void bn_subi(bignum256 *x, uint32_t y, const bignum256 *prime);
|
||||
void bn_subtractmod(const bignum256 *x, const bignum256 *y, bignum256 *res,
|
||||
const bignum256 *prime);
|
||||
void bn_subtract(const bignum256 *x, const bignum256 *y, bignum256 *res);
|
||||
int bn_legendre(const bignum256 *x, const bignum256 *prime);
|
||||
void bn_long_division(bignum256 *x, uint32_t d, bignum256 *q, uint32_t *r);
|
||||
void bn_divmod58(bignum256 *x, uint32_t *r);
|
||||
void bn_divmod1000(bignum256 *x, uint32_t *r);
|
||||
|
@ -551,6 +551,21 @@ def assert_bn_subtractmod(x, y, prime):
|
||||
assert res % prime == (x - y) % prime
|
||||
|
||||
|
||||
def legendre(x, prime):
|
||||
res = pow(x, (prime - 1) // 2, prime)
|
||||
if res == prime - 1:
|
||||
return -1
|
||||
return res
|
||||
|
||||
|
||||
def assert_bn_legendre(x, prime):
|
||||
bn_x = int_to_bignum(x)
|
||||
bn_prime = int_to_bignum(prime)
|
||||
return_value = lib.bn_legendre(bn_x, bn_prime)
|
||||
|
||||
assert return_value == legendre(x, prime)
|
||||
|
||||
|
||||
def assert_bn_subtract(x, y):
|
||||
bn_x = int_to_bignum(x)
|
||||
bn_y = int_to_bignum(y)
|
||||
@ -1005,6 +1020,11 @@ def test_bn_subtract_2(r):
|
||||
assert_bn_subtract(a, b)
|
||||
|
||||
|
||||
def test_bn_legendre(r, prime):
|
||||
x = r.rand_int_bitsize(259)
|
||||
assert_bn_legendre(x, prime)
|
||||
|
||||
|
||||
def test_bn_long_division(r):
|
||||
x = r.rand_int_normalized()
|
||||
d = r.randrange(1, 61304 + 1)
|
||||
|
Loading…
Reference in New Issue
Block a user