mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-21 22:08:08 +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
|
// == 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
|
// q = x // d, r = x % d
|
||||||
// Assumes x is normalized, 1 <= d <= 61304
|
// Assumes x is normalized, 1 <= d <= 61304
|
||||||
// Guarantees q is normalized
|
// 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,
|
void bn_subtractmod(const bignum256 *x, const bignum256 *y, bignum256 *res,
|
||||||
const bignum256 *prime);
|
const bignum256 *prime);
|
||||||
void bn_subtract(const bignum256 *x, const bignum256 *y, bignum256 *res);
|
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_long_division(bignum256 *x, uint32_t d, bignum256 *q, uint32_t *r);
|
||||||
void bn_divmod58(bignum256 *x, uint32_t *r);
|
void bn_divmod58(bignum256 *x, uint32_t *r);
|
||||||
void bn_divmod1000(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
|
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):
|
def assert_bn_subtract(x, y):
|
||||||
bn_x = int_to_bignum(x)
|
bn_x = int_to_bignum(x)
|
||||||
bn_y = int_to_bignum(y)
|
bn_y = int_to_bignum(y)
|
||||||
@ -1005,6 +1020,11 @@ def test_bn_subtract_2(r):
|
|||||||
assert_bn_subtract(a, b)
|
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):
|
def test_bn_long_division(r):
|
||||||
x = r.rand_int_normalized()
|
x = r.rand_int_normalized()
|
||||||
d = r.randrange(1, 61304 + 1)
|
d = r.randrange(1, 61304 + 1)
|
||||||
|
Loading…
Reference in New Issue
Block a user