482 lines
9.9 KiB
Plaintext
482 lines
9.9 KiB
Plaintext
note
|
|
description: "Objects that ..."
|
|
author: "Colin LeMahieu"
|
|
date: "$Date$"
|
|
revision: "$Revision$"
|
|
quote: "Those who expect to reap the benefits of freedom, must, like men, undergo the fatigue of supporting it. - Thomas Paine"
|
|
|
|
class
|
|
EC_POINT_FP
|
|
|
|
inherit
|
|
EC_POINT
|
|
redefine
|
|
x,
|
|
y,
|
|
copy,
|
|
opposite_value,
|
|
product_value,
|
|
twice_value,
|
|
minus_value,
|
|
plus_value
|
|
end
|
|
EC_CONSTANTS
|
|
undefine
|
|
is_equal,
|
|
copy
|
|
end
|
|
STANDARD_CURVES
|
|
undefine
|
|
is_equal,
|
|
copy
|
|
end
|
|
|
|
create
|
|
make_curve_x_y,
|
|
make_from_bytes,
|
|
make_infinity,
|
|
make_sec_p112r1,
|
|
make_sec_p112r2,
|
|
make_sec_p128r1,
|
|
make_sec_p128r2,
|
|
make_sec_p160k1,
|
|
make_sec_p160r1,
|
|
make_sec_p160r2,
|
|
make_sec_p192k1,
|
|
make_sec_p192r1,
|
|
make_sec_p224k1,
|
|
make_sec_p224r1,
|
|
make_sec_p256k1,
|
|
make_sec_p256r1,
|
|
make_sec_p384r1,
|
|
make_sec_p521r1,
|
|
make_p192,
|
|
make_p224,
|
|
make_p256,
|
|
make_p384,
|
|
make_p521
|
|
|
|
feature
|
|
make_infinity
|
|
do
|
|
set_infinity
|
|
end
|
|
|
|
feature -- SEC curves
|
|
make_sec_p112r1
|
|
do
|
|
create x.make_p_x (sec_p112r1_gx)
|
|
create y.make_p_x (sec_p112r1_gy)
|
|
end
|
|
|
|
make_sec_p112r2
|
|
do
|
|
create x.make_p_x (sec_p112r2_gx)
|
|
create y.make_p_x (sec_p112r2_gy)
|
|
end
|
|
|
|
make_sec_p128r1
|
|
do
|
|
create x.make_p_x (sec_p128r1_gx)
|
|
create y.make_p_x (sec_p128r1_gy)
|
|
end
|
|
|
|
make_sec_p128r2
|
|
do
|
|
create x.make_p_x (sec_p128r2_gx)
|
|
create y.make_p_x (sec_p128r2_gy)
|
|
end
|
|
|
|
make_sec_p160k1
|
|
do
|
|
create x.make_p_x (sec_p160k1_gx)
|
|
create y.make_p_x (sec_p160k1_gy)
|
|
end
|
|
|
|
make_sec_p160r1
|
|
do
|
|
create x.make_p_x (sec_p160r1_gx)
|
|
create y.make_p_x (sec_p160r1_gy)
|
|
end
|
|
|
|
make_sec_p160r2
|
|
do
|
|
create x.make_p_x (sec_p160r2_gx)
|
|
create y.make_p_x (sec_p160r2_gy)
|
|
end
|
|
|
|
make_sec_p192k1
|
|
do
|
|
create x.make_p_x (sec_p192k1_gx)
|
|
create y.make_p_x (sec_p192k1_gy)
|
|
end
|
|
|
|
make_sec_p192r1
|
|
do
|
|
create x.make_p_x (sec_p192r1_gx)
|
|
create y.make_p_x (sec_p192r1_gy)
|
|
end
|
|
|
|
make_sec_p224k1
|
|
do
|
|
create x.make_p_x (sec_p224k1_gx)
|
|
create y.make_p_x (sec_p224k1_gy)
|
|
end
|
|
|
|
make_sec_p224r1
|
|
do
|
|
create x.make_p_x (sec_p224r1_gx)
|
|
create y.make_p_x (sec_p224r1_gy)
|
|
end
|
|
|
|
make_sec_p256k1
|
|
do
|
|
create x.make_p_x (sec_p256k1_gx)
|
|
create y.make_p_x (sec_p256k1_gy)
|
|
end
|
|
|
|
make_sec_p256r1
|
|
do
|
|
create x.make_p_x (sec_p256r1_gx)
|
|
create y.make_p_x (sec_p256r1_gy)
|
|
end
|
|
|
|
make_sec_p384r1
|
|
do
|
|
create x.make_p_x (sec_p384r1_gx)
|
|
create y.make_p_x (sec_p384r1_gy)
|
|
end
|
|
|
|
make_sec_p521r1
|
|
do
|
|
create x.make_p_x (sec_p521r1_gx)
|
|
create y.make_p_x (sec_p521r1_gy)
|
|
end
|
|
|
|
feature
|
|
make_p192
|
|
do
|
|
create x.make_p_x (p192_gx)
|
|
create y.make_p_x (p192_gy)
|
|
end
|
|
|
|
make_p224
|
|
do
|
|
create x.make_p_x (p224_gx)
|
|
create y.make_p_x (p224_gy)
|
|
end
|
|
|
|
make_p256
|
|
do
|
|
create x.make_p_x (p256_gx)
|
|
create y.make_p_x (p256_gy)
|
|
end
|
|
|
|
make_p384
|
|
do
|
|
create x.make_p_x (p384_gx)
|
|
create y.make_p_x (p384_gy)
|
|
end
|
|
|
|
make_p521
|
|
do
|
|
create x.make_p_x (p521_gx)
|
|
create y.make_p_x (p521_gy)
|
|
end
|
|
|
|
make_curve_x_y (x_a: EC_FIELD_ELEMENT_FP; y_a: EC_FIELD_ELEMENT_FP)
|
|
do
|
|
x := x_a
|
|
y := y_a
|
|
end
|
|
|
|
make_from_bytes (encoded: SPECIAL [NATURAL_8] curve: EC_CURVE_FP)
|
|
-- Decode a point on this curve from its ASN.1 encoding
|
|
-- encodings are taken account of, including point compression for
|
|
-- <code>F<sub>p</sub><code> (X9.62 s 4.2.1 pg 17).
|
|
-- @return The decoded point.
|
|
require
|
|
first_byte_indicator: encoded [0] = 0x02 or encoded [0] = 0x3 or encoded [0] = 0x4
|
|
do
|
|
inspect
|
|
encoded [0]
|
|
when 0x02 then
|
|
decodeCompressedPoint (encoded, 0, curve)
|
|
when 0x03 then
|
|
decodeCompressedPoint (encoded, 1, curve)
|
|
when 0x04 then
|
|
decodeUncompressedPoint (encoded)
|
|
end
|
|
end
|
|
|
|
feature
|
|
x: EC_FIELD_ELEMENT_FP
|
|
y: EC_FIELD_ELEMENT_FP
|
|
|
|
copy (other: like Current)
|
|
do
|
|
x.copy (other.x)
|
|
y.copy (other.y)
|
|
end
|
|
|
|
feature
|
|
|
|
set_infinity
|
|
do
|
|
create x.make_p_x (create {INTEGER_X}.default_create)
|
|
create y.make_p_x (create {INTEGER_X}.default_create)
|
|
infinity := True
|
|
end
|
|
|
|
to_byte_array_compressed (curve: EC_CURVE_FP): SPECIAL [NATURAL_8]
|
|
-- Return a compressed encoded version of this point
|
|
local
|
|
x_array: SPECIAL [NATURAL_8]
|
|
do
|
|
x_array := x.x.as_fixed_width_byte_array (x.encoded_field_size (curve))
|
|
create result.make_filled (0, x_array.count + 1)
|
|
result.copy_data (x_array, 0, 1, x_array.count)
|
|
result [0] := compressed_PC_byte (y.x)
|
|
end
|
|
|
|
to_byte_array_uncompressed (curve: EC_CURVE_FP): SPECIAL [NATURAL_8]
|
|
-- Return an uncompressed encoded version of this point
|
|
local
|
|
x_array: SPECIAL [NATURAL_8]
|
|
y_array: SPECIAL [NATURAL_8]
|
|
p0: SPECIAL [NATURAL_8]
|
|
qLength: INTEGER_32
|
|
do
|
|
qLength := x.encoded_field_size (curve)
|
|
x_array := x.x.as_fixed_width_byte_array (qlength)
|
|
y_array := y.x.as_fixed_width_byte_array (qLength)
|
|
check
|
|
x_array.capacity = qlength
|
|
y_array.capacity = qlength
|
|
end
|
|
create p0.make_filled (0, x_array.capacity + y_array.capacity + 1)
|
|
p0.copy_data (x_array, 0, x_array.upper, 1)
|
|
p0.copy_data (y_array, 0, y_array.upper, x_array.capacity + 1)
|
|
p0.put (0x04, 0)
|
|
result := p0
|
|
end
|
|
|
|
plus_value (other: like Current; curve: EC_CURVE_FP): EC_POINT_FP
|
|
do
|
|
Result := Precursor (other, curve)
|
|
end
|
|
|
|
plus (other: like Current; curve: EC_CURVE_FP)
|
|
-- Addition over FP
|
|
local
|
|
gamma: EC_FIELD_ELEMENT_FP
|
|
x3: EC_FIELD_ELEMENT_FP
|
|
y3: EC_FIELD_ELEMENT_FP
|
|
do
|
|
if
|
|
infinity
|
|
then
|
|
copy (other)
|
|
elseif
|
|
other.infinity
|
|
then
|
|
elseif
|
|
x ~ other.x
|
|
then
|
|
if
|
|
y ~ other.y
|
|
then
|
|
copy (twice_value (curve))
|
|
else
|
|
set_infinity
|
|
end
|
|
else
|
|
gamma := (other.y.minus_value (y, curve)).quotient_value (other.x.minus_value (x, curve), curve)
|
|
x3 := (gamma.product_value (gamma, curve)).minus_value (x, curve).minus_value (other.x, curve)
|
|
y3 := (gamma.product_value (x.minus_value (x3, curve), curve)).minus_value (y, curve)
|
|
x := x3
|
|
y := y3
|
|
end
|
|
end
|
|
|
|
twice_value (curve: EC_CURVE_FP): EC_POINT_FP
|
|
do
|
|
Result := Precursor (curve)
|
|
end
|
|
|
|
twice (curve: EC_CURVE_FP)
|
|
-- Return current * current over FP
|
|
local
|
|
two_element: EC_FIELD_ELEMENT_FP
|
|
three_element: EC_FIELD_ELEMENT_FP
|
|
gamma: EC_FIELD_ELEMENT_FP
|
|
x3: EC_FIELD_ELEMENT_FP
|
|
y3: EC_FIELD_ELEMENT_FP
|
|
do
|
|
if
|
|
infinity
|
|
then
|
|
elseif
|
|
y.x.is_zero
|
|
then
|
|
set_infinity
|
|
else
|
|
create two_element.make_p_x (two)
|
|
create three_element.make_p_x (three)
|
|
gamma := (((x.product_value (x, curve)).product_value (three_element, curve)).plus_value (curve.a, curve)).quotient_value (y.product_value (two_element, curve), curve)
|
|
x3 := (gamma.product_value (gamma, curve)).minus_value (x.product_value (two_element, curve), curve)
|
|
y3 := (gamma.product_value (x.minus_value (x3, curve), curve)).minus_value (y, curve)
|
|
x := x3
|
|
y := y3
|
|
end
|
|
end
|
|
|
|
minus_value (other: like Current; curve: EC_CURVE_FP): EC_POINT_FP
|
|
do
|
|
Result := Precursor (other, curve)
|
|
end
|
|
|
|
minus (other: like Current; curve: EC_CURVE_FP)
|
|
do
|
|
if
|
|
other.infinity
|
|
then
|
|
else
|
|
plus (other.opposite_value (curve), curve)
|
|
end
|
|
end
|
|
|
|
product_value (other: INTEGER_X; curve: EC_CURVE_FP): EC_POINT_FP
|
|
do
|
|
Result := Precursor (other, curve)
|
|
end
|
|
|
|
product (other: INTEGER_X; curve: EC_CURVE_FP)
|
|
-- return current * k over FP
|
|
local
|
|
e: INTEGER_X
|
|
h: INTEGER_X
|
|
R: like Current
|
|
i: INTEGER_32
|
|
do
|
|
if
|
|
infinity
|
|
then
|
|
elseif
|
|
other.is_zero
|
|
then
|
|
set_infinity
|
|
else
|
|
e := other
|
|
h := e * three
|
|
R := deep_twin
|
|
from
|
|
i := (h.bits - 2)
|
|
until
|
|
i <= 0
|
|
loop
|
|
R := r.twice_value (curve)
|
|
if
|
|
h.bit_test (i) and not e.bit_test (i)
|
|
then
|
|
r := r.plus_value (Current, curve)
|
|
elseif
|
|
not h.bit_test (i) and e.bit_test (i)
|
|
then
|
|
r := r.minus_value (Current, curve)
|
|
end
|
|
i := i - 1
|
|
end
|
|
copy (r)
|
|
end
|
|
end
|
|
|
|
opposite_value (curve: EC_CURVE_FP): like Current
|
|
do
|
|
Result := Precursor (curve)
|
|
end
|
|
|
|
opposite (curve: EC_CURVE_FP)
|
|
do
|
|
y.opposite (curve)
|
|
end
|
|
|
|
feature {NONE} -- support features
|
|
ytilde_set (source: INTEGER_X): BOOLEAN
|
|
-- Test the least significant bit, this is ytilde
|
|
-- X9.62 4.2.1
|
|
do
|
|
result := source.bit_test (0)
|
|
end
|
|
|
|
compressed_PC_byte (source: INTEGER_X): NATURAL_8
|
|
-- Return the PC byte depending on if ytilde is set
|
|
-- X9.62 4.3.6
|
|
do
|
|
if
|
|
ytilde_set (source)
|
|
then
|
|
result := 0x03
|
|
else
|
|
result := 0x02
|
|
end
|
|
end
|
|
|
|
feature {NONE}
|
|
decodeCompressedPoint (encoded: SPECIAL [NATURAL_8] ytilde: INTEGER curve: EC_CURVE_FP)
|
|
-- Decode a compressed point
|
|
require
|
|
encoded.lower = 0
|
|
local
|
|
i: SPECIAL [NATURAL_8]
|
|
x_new: EC_FIELD_ELEMENT_FP
|
|
alpha: EC_FIELD_ELEMENT_FP
|
|
beta: EC_FIELD_ELEMENT_FP
|
|
x_int: INTEGER_X
|
|
bit0: INTEGER
|
|
q_minus_beta: EC_FIELD_ELEMENT_FP
|
|
do
|
|
create i.make_filled (0, encoded.count - 1)
|
|
i.copy_data (encoded, 1, 0, i.count)
|
|
create x_int.make_from_bytes (i, i.lower, i.upper)
|
|
create x_new.make_p_x (x_int)
|
|
alpha := (x_new.product_value (x_new.square_value (curve).plus_value (curve.a, curve), curve)).plus_value (curve.b, curve)
|
|
beta := alpha.sqrt (curve)
|
|
if
|
|
beta.x.bit_test (0)
|
|
then
|
|
bit0 := 1
|
|
else
|
|
bit0 := 0
|
|
end
|
|
if
|
|
bit0 = ytilde
|
|
then
|
|
make_curve_x_y (x_new, beta)
|
|
else
|
|
create q_minus_beta.make_p_x (curve.q - beta.x)
|
|
make_curve_x_y (x_new, q_minus_beta)
|
|
end
|
|
end
|
|
|
|
decodeUncompressedPoint (encoded: SPECIAL [NATURAL_8])
|
|
-- Decode an uncompressed point
|
|
require
|
|
encoded_not_split_even: (encoded.count \\ 2) = 1
|
|
local
|
|
xEnc: SPECIAL [NATURAL_8]
|
|
yEnc: SPECIAL [NATURAL_8]
|
|
x_new: EC_FIELD_ELEMENT_FP
|
|
y_new: EC_FIELD_ELEMENT_FP
|
|
do
|
|
create xEnc.make_filled (0, (encoded.capacity - 1) // 2)
|
|
create yEnc.make_filled (0, (encoded.capacity - 1) // 2)
|
|
encoded.copy_data (xEnc, 1, 0, xEnc.capacity)
|
|
encoded.copy_data (yEnc, xEnc.capacity, 0, yEnc.capacity)
|
|
create x_new.make_p_x (create {INTEGER_X}.make_from_bytes (xEnc, xEnc.lower, xEnc.upper))
|
|
create y_new.make_p_x (create {INTEGER_X}.make_from_bytes (yEnc, yEnc.lower, yEnc.upper))
|
|
x := x_new
|
|
y := y_new
|
|
end
|
|
end
|