note description: "Objects that ..." author: "Colin LeMahieu" date: "$Date$" revision: "$Revision$" quote: "What this country needs are more unemployed politicians. - Edward Langley" class EC_POINT_F2M inherit EC_POINT redefine x, y, opposite_value, twice_value, product_value, minus_value, plus_value end EC_CONSTANTS undefine is_equal end STANDARD_CURVES undefine is_equal end INTEGER_X_FACILITIES undefine is_equal end create make_curve_x_y, make_infinity, make_from_bytes, make_sec_t113r1, make_sec_t113r2, make_sec_t131r1, make_sec_t131r2, make_sec_t163k1, make_sec_t163r1, make_sec_t163r2, make_sec_t193r1, make_sec_t193r2, make_sec_t233k1, make_sec_t233r1, make_sec_t239k1, make_sec_t283k1, make_sec_t283r1, make_sec_t409k1, make_sec_t409r1, make_sec_t571k1, make_sec_t571r1, make_k163, make_k233, make_k283, make_k409, make_k571, make_b163, make_b233, make_b283, make_b409, make_b571 feature make_infinity do set_infinity end feature -- SEC points make_sec_t113r1 do create x.make (sec_t113r1_gx) create y.make (sec_t113r1_gy) end make_sec_t113r2 do create x.make (sec_t113r2_gx) create y.make (sec_t113r2_gy) end make_sec_t131r1 do create x.make (sec_t131r1_gx) create y.make (sec_t131r1_gy) end make_sec_t131r2 do create x.make (sec_t131r2_gx) create y.make (sec_t131r2_gy) end make_sec_t163k1 do create x.make (sec_t163k1_gx) create y.make (sec_t163k1_gy) end make_sec_t163r1 do create x.make (sec_t163r1_gx) create y.make (sec_t163r1_gy) end make_sec_t163r2 do create x.make (sec_t163r2_gx) create y.make (sec_t163r2_gy) end make_sec_t193r1 do create x.make (sec_t193r1_gx) create y.make (sec_t193r1_gy) end make_sec_t193r2 do create x.make (sec_t193r2_gx) create y.make (sec_t193r2_gy) end make_sec_t233k1 do create x.make (sec_t233k1_gx) create y.make (sec_t233k1_gy) end make_sec_t233r1 do create x.make (sec_t233r1_gx) create y.make (sec_t233r1_gy) end make_sec_t239k1 do create x.make (sec_t239k1_gx) create y.make (sec_t239k1_gy) end make_sec_t283k1 do create x.make (sec_t283k1_gx) create y.make (sec_t283k1_gy) end make_sec_t283r1 do create x.make (sec_t283r1_gx) create y.make (sec_t283r1_gy) end make_sec_t409k1 do create x.make (sec_t409k1_gx) create y.make (sec_t409k1_gy) end make_sec_t409r1 do create x.make (sec_t409r1_gx) create y.make (sec_t409r1_gy) end make_sec_t571k1 do create x.make (sec_t571k1_gx) create y.make (sec_t571k1_gy) end make_sec_t571r1 do create x.make (sec_t571r1_gx) create y.make (sec_t571r1_gy) end feature -- FIPS points make_k163 do create x.make (k163_gx) create y.make (k163_gy) end make_k233 do create x.make (k233_gx) create y.make (k233_gy) end make_k283 do create x.make (k283_gx) create y.make (k283_gy) end make_k409 do create x.make (k409_gx) create y.make (k409_gy) end make_k571 do create x.make (k571_gx) create y.make (k571_gy) end make_b163 do create x.make (b163_gx) create y.make (b163_gy) end make_b233 do create x.make (b233_gx) create y.make (b233_gy) end make_b283 do create x.make (b283_gx) create y.make (b283_gy) end make_b409 do create x.make (b409_gx) create y.make (b409_gy) end make_b571 do create x.make (b571_gx) create y.make (b571_gy) end make_curve_x_y (x_a: EC_FIELD_ELEMENT_F2M; y_a: EC_FIELD_ELEMENT_F2M) do x := x_a y := y_a end make_from_bytes (bytes: SPECIAL[NATURAL_8]; curve: EC_CURVE_F2M) do decodepoint (bytes, curve) end feature x: EC_FIELD_ELEMENT_F2M y: EC_FIELD_ELEMENT_F2M set_from_other (other: like Current) do x.copy (other.x) y.copy (other.y) end feature -- Decode/encode set_infinity do create x.make (create {INTEGER_X}.default_create) create y.make (create {INTEGER_X}.default_create) infinity := True end decodePoint (source: SPECIAL [NATURAL_8] curve: EC_CURVE_F2M) require Source_too_small: source.capacity > 0 local enc: SPECIAL [NATURAL_8] do create enc.make_filled (0, source.count - 1) enc.copy_data (source, 1, 0, enc.count) inspect source[0] when 0x02 then decodeCompressedPoint (enc, 0, curve) when 0x03 then decodeCompressedPoint (enc, 1, curve) when 0x04 then decodeUncompressedPoint (enc) end end decodeCompressedPoint (source: SPECIAL [NATURAL_8] ypBit: INTEGER curve: EC_CURVE_F2M) local xp: EC_FIELD_ELEMENT_F2M yp: EC_FIELD_ELEMENT_F2M i: INTEGER_32 beta: EC_FIELD_ELEMENT_F2M z: EC_FIELD_ELEMENT_F2M oneEC: EC_FIELD_ELEMENT_F2M zBit: INTEGER do create xp.make (create {INTEGER_X}.make_from_bytes (source, source.lower, source.upper)) if xp.x.is_zero then yp := curve.b from i := 0 until i = curve.m - 1 loop yp := yp.square_value (curve) i := i + 1 end else beta := xp.plus_value (curve.a, curve).plus_value (curve.b.product_value (xp.square_value (curve).inverse_value (curve), curve), curve) --z := solveQuadraticEquation(beta) create z.make (create {INTEGER_X}.default_create) zBit := 0 if z.x.bit_test (0) then zBit := 1 end if zBit /= ypBit then create oneEC.make (ONE) z := z.plus_value (oneEC, curve) end yp := xp.product_value (z, curve) end x := xp y := yp end decodeUncompressedPoint (source: SPECIAL [NATURAL_8]) require X_and_y_different_sizes: source.capacity \\ 2 = 0 local xEnc: SPECIAL [NATURAL_8] yEnc: SPECIAL [NATURAL_8] x_mpz: INTEGER_X y_mpz: INTEGER_X do create xEnc.make_filled (0, source.count // 2) xEnc.copy_data (source, 0, 0, xEnc.count) create yEnc.make_filled (0, source.count // 2) yEnc.copy_data (source, source.count // 2, 0, yEnc.count) check -- Field elements should be same size xEnc.capacity = yEnc.capacity end create x_mpz.make_from_bytes (xEnc, xEnc.lower, xEnc.upper) create y_mpz.make_from_bytes (yEnc, yEnc.lower, yEnc.upper) create x.make (x_mpz) create y.make (y_mpz) end to_byte_array_uncompressed (curve: EC_CURVE_F2M): SPECIAL [NATURAL_8] local byteCount: INTEGER_32 y_array: SPECIAL [NATURAL_8] x_array: SPECIAL [NATURAL_8] p0: SPECIAL [NATURAL_8] do bytecount := x.x.bytes x_array := x.x.as_bytes y_array := y.x.as_fixed_width_byte_array (byteCount) create p0.make_filled (0, byteCount + byteCount + 1) p0.put (0x04, 0) check x_array.capacity = y_array.capacity end p0.copy_data (x_array, 0, x_array.upper, 1) p0.copy_data (y_array, 0, y_array.upper, x_array.upper + 1) result := p0 end to_byte_array_compressed (curve: EC_CURVE_F2M): SPECIAL [NATURAL_8] local byteCount: INTEGER_32 x_array: SPECIAL [NATURAL_8] P0: SPECIAL [NATURAL_8] do x_array := x.x.as_bytes byteCount := x.x.bytes -- See X9.62 4.3.6 and 4.2.2 create P0.make_filled (0, byteCount + 1) p0.put (0x02, 0) -- X9.62 4.2.2 and 4.3.6: -- if x = 0 then ypTilde := 0, else ypTilde is the rightmost -- bit of y * x^(-1) -- if ypTilde = 0, then PC := 02, else PC := 03 -- Note: PC === PO[0] if (not (x.x.is_zero)) and ((y.product_value (x.inverse_value (curve), curve)).x.bit_test(0)) then -- ypTilde = 1, hence PC = 03 p0.put (0x03, 0) end p0.copy_data (x_array, 0, x_array.upper, 1) result := p0 end feature -- Implement ECPOINT plus_value (other: like Current; curve: EC_CURVE_F2M): EC_POINT_F2M do Result := Precursor (other, curve) end plus (other: like Current; curve: EC_CURVE_F2M) do if infinity then copy (other) elseif other.infinity then else add_not_infinity (other, curve) end end minus_value (other: like Current; curve: EC_CURVE_F2M): EC_POINT_F2M do Result := Precursor (other, curve) end minus (other: like Current; curve: EC_CURVE_F2M) do if other.infinity then else add_minus_b (other, curve) end end product_value (b: INTEGER_X; curve: EC_CURVE_F2M): EC_POINT_F2M do Result := Precursor (b, curve) end product (b: INTEGER_X; curve: EC_CURVE_F2M) local p: like Current q: like Current t: INTEGER_32 -- i: INTEGER_32 special: SPECIAL [NATURAL_32] limb: NATURAL_32 limb_position: INTEGER new_bit_position: INTEGER bit_position: INTEGER do p := Current create q.make_infinity t := b.bits from special := b.item limb := special [limb_position] limb_position := 0 bit_position := 0 until limb_position * 32 + bit_position >= t loop if limb.bit_test (bit_position) then q.plus (p, curve) end p.twice (curve) new_bit_position := (bit_position + 1) \\ 32 if new_bit_position < bit_position then limb_position := limb_position + 1 limb := special [limb_position] end bit_position := new_bit_position end -- p := Current -- create q.make_infinity -- t := b.bits -- from -- i := 0 -- until -- i = t -- loop -- if -- b.bit_test (i) -- then -- q.plus (p, curve) -- end -- p.twice (curve) -- i := i + 1 -- end copy (q) end twice_value (curve: EC_CURVE_F2M): EC_POINT_F2M do Result := Precursor (curve) end twice (curve: EC_CURVE_F2M) do if infinity then elseif x.x.is_zero then set_infinity else twice_not_infinity (curve) end end opposite_value (curve: EC_CURVE_F2M): EC_POINT_F2M do Result := Precursor (curve) end opposite (curve: EC_CURVE_F2M) do y.plus (x, curve) end feature -- Implementation support features twice_not_infinity (curve: EC_CURVE_F2M) local lambda: EC_FIELD_ELEMENT_F2M x3: EC_FIELD_ELEMENT_F2M y3: EC_FIELD_ELEMENT_F2M one_element: EC_FIELD_ELEMENT_F2M do create one_element.make (one) lambda := y.quotient_value (x, curve) lambda.plus (x, curve) x3 := lambda.square_value (curve) x3.plus (lambda, curve) x3.plus (curve.a, curve) y3 := x.square_value (curve) lambda.plus (one_element, curve) lambda.product (x3, curve) y3.plus (lambda, curve) x := x3 y := y3 end add_minus_b (other: like Current curve: EC_CURVE_F2M) local minusB: like Current do create minusB.make_curve_x_y (other.x, other.x.plus_value (other.y, curve)) plus (minusB, curve) end add_not_infinity (other: like Current; curve: EC_CURVE_F2M) do if x ~ other.x then if y ~ other.y then copy (twice_value (curve)) else set_infinity end else add_normal (other, curve) end end add_normal (other: like Current; curve: EC_CURVE_F2M) local lambda: EC_FIELD_ELEMENT_F2M x3: EC_FIELD_ELEMENT_F2M y3: EC_FIELD_ELEMENT_F2M do lambda := (y.plus_value (other.y, curve)).quotient_value (x.plus_value (other.x, curve), curve) x3 := lambda.square_value (curve) x3 := x3.plus_value (lambda, curve).plus_value (x, curve).plus_value (other.x, curve).plus_value (curve.a, curve) y3 := ((lambda.product_value (x.plus_value (x3, curve), curve)).plus_value (x3, curve)).plus_value (y, curve) x := x3 y := y3 end end