mirror of
https://github.com/RGBCube/serenity
synced 2025-07-10 04:27:35 +00:00

This implementation of the secp256r1 elliptic curve uses two techniques to improve the performance of the operations. 1. All coordinates are stored in Jacobian form, (X/Z^2, Y/Z^3, Z), which removes the need for division operations during point addition or doubling. The points are converted at the start of the computation, and converted back at the end. 2. All values are transformed to Montgomery form, to allow for faster modular multiplication using the Montgomery modular multiplication method. This means that all coordinates have to be converted into this form, and back out of this form before returning them.
49 lines
2.3 KiB
C++
49 lines
2.3 KiB
C++
/*
|
|
* Copyright (c) 2022, Michiel Visser <opensource@webmichiel.nl>
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <AK/ByteBuffer.h>
|
|
#include <AK/UFixedBigInt.h>
|
|
|
|
namespace Crypto::Curves {
|
|
|
|
struct JacobianPoint {
|
|
u256 x { 0u };
|
|
u256 y { 0u };
|
|
u256 z { 0u };
|
|
};
|
|
|
|
class SECP256r1 {
|
|
public:
|
|
static ErrorOr<ByteBuffer> generate_public_key(ReadonlyBytes a);
|
|
static ErrorOr<ByteBuffer> compute_coordinate(ReadonlyBytes scalar_bytes, ReadonlyBytes point_bytes);
|
|
|
|
private:
|
|
static u256 modular_reduce(u256 const& value);
|
|
static u256 modular_reduce_order(u256 const& value);
|
|
static u256 modular_add(u256 const& left, u256 const& right, bool carry_in = false);
|
|
static u256 modular_sub(u256 const& left, u256 const& right);
|
|
static u256 modular_multiply(u256 const& left, u256 const& right);
|
|
static u256 modular_square(u256 const& value);
|
|
static u256 to_montgomery(u256 const& value);
|
|
static u256 from_montgomery(u256 const& value);
|
|
static u256 modular_inverse(u256 const& value);
|
|
static void point_double(JacobianPoint& output_point, JacobianPoint const& point);
|
|
static void point_add(JacobianPoint& output_point, JacobianPoint const& point_a, JacobianPoint const& point_b);
|
|
static void convert_jacobian_to_affine(JacobianPoint& point);
|
|
static bool is_point_on_curve(JacobianPoint const& point);
|
|
|
|
static constexpr u256 REDUCE_PRIME { u128 { 0x0000000000000001ull, 0xffffffff00000000ull }, u128 { 0xffffffffffffffffull, 0x00000000fffffffe } };
|
|
static constexpr u256 REDUCE_ORDER { u128 { 0x0c46353d039cdaafull, 0x4319055258e8617bull }, u128 { 0x0000000000000000ull, 0x00000000ffffffff } };
|
|
static constexpr u256 PRIME_INVERSE_MOD_R { u128 { 0x0000000000000001ull, 0x0000000100000000ull }, u128 { 0x0000000000000000ull, 0xffffffff00000002ull } };
|
|
static constexpr u256 PRIME { u128 { 0xffffffffffffffffull, 0x00000000ffffffffull }, u128 { 0x0000000000000000ull, 0xffffffff00000001ull } };
|
|
static constexpr u256 R2_MOD_PRIME { u128 { 0x0000000000000003ull, 0xfffffffbffffffffull }, u128 { 0xfffffffffffffffeull, 0x00000004fffffffdull } };
|
|
static constexpr u256 ONE { 1u };
|
|
static constexpr u256 B_MONTGOMERY { u128 { 0xd89cdf6229c4bddfull, 0xacf005cd78843090ull }, u128 { 0xe5a220abf7212ed6ull, 0xdc30061d04874834ull } };
|
|
};
|
|
|
|
}
|