mirror of
https://github.com/odin-lang/Odin.git
synced 2026-07-20 06:31:07 +00:00
core/crypto/_edwards25519: Support crypto.COMPACT_IMPLS
This commit is contained in:
@@ -195,7 +195,6 @@ ge_generator :: proc "contextless" (ge: ^Group_Element) {
|
||||
ge_set(ge, &GE_BASEPOINT)
|
||||
}
|
||||
|
||||
@(private)
|
||||
Addend_Group_Element :: struct {
|
||||
y2_minus_x2: field.Loose_Field_Element, // t1
|
||||
y2_plus_x2: field.Loose_Field_Element, // t3
|
||||
@@ -203,7 +202,6 @@ Addend_Group_Element :: struct {
|
||||
two_times_z2: field.Loose_Field_Element, // t5
|
||||
}
|
||||
|
||||
@(private)
|
||||
ge_addend_set :: proc "contextless" (ge_a: ^Addend_Group_Element, ge: ^Group_Element) {
|
||||
field.fe_sub(&ge_a.y2_minus_x2, &ge.y, &ge.x)
|
||||
field.fe_add(&ge_a.y2_plus_x2, &ge.y, &ge.x)
|
||||
@@ -420,6 +418,6 @@ ge_in_prime_order_subgroup_vartime :: proc "contextless" (ge: ^Group_Element) ->
|
||||
// that is a ~50% speedup, and a lot of added complexity for something
|
||||
// that is better solved by "just use ristretto255".
|
||||
tmp: Group_Element = ---
|
||||
_ge_scalarmult(&tmp, ge, &SC_ELL, true)
|
||||
ge_scalarmult_raw(&tmp, ge, &SC_ELL, true)
|
||||
return ge_equal(&tmp, &GE_IDENTITY) == 1
|
||||
}
|
||||
|
||||
@@ -1,130 +1,24 @@
|
||||
package _edwards25519
|
||||
|
||||
import "core:crypto"
|
||||
import field "core:crypto/_fiat/field_scalar25519"
|
||||
import subtle "core:crypto/_subtle"
|
||||
import "core:mem"
|
||||
|
||||
// GE_BASEPOINT_TABLE is 1 * G, ... 15 * G, in precomputed format.
|
||||
//
|
||||
// Note: When generating, the values were reduced to Tight_Field_Element
|
||||
// ranges, even though that is not required.
|
||||
@(private,rodata)
|
||||
GE_BASEPOINT_TABLE := Multiply_Table {
|
||||
{
|
||||
{62697248952638, 204681361388450, 631292143396476, 338455783676468, 1213667448819585},
|
||||
{1288382639258501, 245678601348599, 269427782077623, 1462984067271730, 137412439391563},
|
||||
{301289933810280, 1259582250014073, 1422107436869536, 796239922652654, 1953934009299142},
|
||||
{2, 0, 0, 0, 0},
|
||||
},
|
||||
{
|
||||
{1519297034332653, 1098796920435767, 1823476547744119, 808144629470969, 2110930855619772},
|
||||
{338005982828284, 1667856962156925, 100399270107451, 1604566703601691, 1950338038771369},
|
||||
{1920505767731247, 1443759578976892, 1659852098357048, 1484431291070208, 275018744912646},
|
||||
{763163817085987, 2195095074806923, 2167883174351839, 1868059999999762, 911071066608705},
|
||||
},
|
||||
{
|
||||
{960627541894068, 1314966688943942, 1126875971034044, 2059608312958945, 605975666152586},
|
||||
{1714478358025626, 2209607666607510, 1600912834284834, 496072478982142, 481970031861896},
|
||||
{851735079403194, 1088965826757164, 141569479297499, 602804610059257, 2004026468601520},
|
||||
{197585529552380, 324719066578543, 564481854250498, 1173818332764578, 35452976395676},
|
||||
},
|
||||
{
|
||||
{1152980410747203, 2196804280851952, 25745194962557, 1915167295473129, 1266299690309224},
|
||||
{809905889679060, 979732230071345, 1509972345538142, 188492426534402, 818965583123815},
|
||||
{997685409185036, 1451818320876327, 2126681166774509, 2000509606057528, 235432372486854},
|
||||
{887734189279642, 1460338685162044, 877378220074262, 102436391401299, 153369156847490},
|
||||
},
|
||||
{
|
||||
{2056621900836770, 1821657694132497, 1627986892909426, 1163363868678833, 1108873376459226},
|
||||
{1187697490593623, 1066539945237335, 885654531892000, 1357534489491782, 359370291392448},
|
||||
{1509033452137525, 1305318174298508, 613642471748944, 1987256352550234, 1044283663101541},
|
||||
{220105720697037, 387661783287620, 328296827867762, 360035589590664, 795213236824054},
|
||||
},
|
||||
{
|
||||
{1820794733038396, 1612235121681074, 757405923441402, 1094031020892801, 231025333128907},
|
||||
{1639067873254194, 1484176557946322, 300800382144789, 1329915446659183, 1211704578730455},
|
||||
{641900794791527, 1711751746971612, 179044712319955, 576455585963824, 1852617592509865},
|
||||
{743549047192397, 685091042550147, 1952415336873496, 1965124675654685, 513364998442917},
|
||||
},
|
||||
{
|
||||
{1004557076870448, 1762911374844520, 1330807633622723, 384072910939787, 953849032243810},
|
||||
{2178275058221458, 257933183722891, 376684351537894, 2010189102001786, 1981824297484148},
|
||||
{1332915663881114, 1286540505502549, 1741691283561518, 977214932156314, 1764059494778091},
|
||||
{429702949064027, 1368332611650677, 2019867176450999, 2212258376161746, 526160996742554},
|
||||
},
|
||||
{
|
||||
{2098932988258576, 2203688382075948, 2120400160059479, 1748488020948146, 1203264167282624},
|
||||
{677131386735829, 1850249298025188, 672782146532031, 2144145693078904, 2088656272813787},
|
||||
{1065622343976192, 1573853211848116, 223560413590068, 333846833073379, 27832122205830},
|
||||
{1781008836504573, 917619542051793, 544322748939913, 882577394308384, 1720521246471195},
|
||||
},
|
||||
{
|
||||
{660120928379860, 2081944024858618, 1878411111349191, 424587356517195, 2111317439894005},
|
||||
{1834193977811532, 1864164086863319, 797334633289424, 150410812403062, 2085177078466389},
|
||||
{1438117271371866, 783915531014482, 388731514584658, 292113935417795, 1945855002546714},
|
||||
{1678140823166658, 679103239148744, 614102761596238, 1052962498997885, 1863983323810390},
|
||||
},
|
||||
{
|
||||
{1690309392496233, 1116333140326275, 1377242323631039, 717196888780674, 82724646713353},
|
||||
{1722370213432106, 74265192976253, 264239578448472, 1714909985012994, 2216984958602173},
|
||||
{2010482366920922, 1294036471886319, 566466395005815, 1631955803657320, 1751698647538458},
|
||||
{1073230604155753, 1159087041338551, 1664057985455483, 127472702826203, 1339591128522371},
|
||||
},
|
||||
{
|
||||
{478053307175577, 2179515791720985, 21146535423512, 1831683844029536, 462805561553981},
|
||||
{1945267486565588, 1298536818409655, 2214511796262989, 1904981051429012, 252904800782086},
|
||||
{268945954671210, 222740425595395, 1208025911856230, 1080418823003555, 75929831922483},
|
||||
{1884784014268948, 643868448202966, 978736549726821, 46385971089796, 1296884812292320},
|
||||
},
|
||||
{
|
||||
{1861159462859103, 7077532564710, 963010365896826, 1938780006785270, 766241051941647},
|
||||
{1778966986051906, 1713995999765361, 1394565822271816, 1366699246468722, 1213407027149475},
|
||||
{1978989286560907, 2135084162045594, 1951565508865477, 671788336314416, 293123929458176},
|
||||
{902608944504080, 2167765718046481, 1285718473078022, 1222562171329269, 492109027844479},
|
||||
},
|
||||
{
|
||||
{1820807832746213, 1029220580458586, 1101997555432203, 1039081975563572, 202477981158221},
|
||||
{1866134980680205, 2222325502763386, 1830284629571201, 1046966214478970, 418381946936795},
|
||||
{1783460633291322, 1719505443254998, 1810489639976220, 877049370713018, 2187801198742619},
|
||||
{197118243000763, 305493867565736, 518814410156522, 1656246186645170, 901894734874934},
|
||||
},
|
||||
{
|
||||
{225454942125915, 478410476654509, 600524586037746, 643450007230715, 1018615928259319},
|
||||
{1733330584845708, 881092297970296, 507039890129464, 496397090721598, 2230888519577628},
|
||||
{690155664737246, 1010454785646677, 753170144375012, 1651277613844874, 1622648796364156},
|
||||
{1321310321891618, 1089655277873603, 235891750867089, 815878279563688, 1709264240047556},
|
||||
},
|
||||
{
|
||||
{805027036551342, 1387174275567452, 1156538511461704, 1465897486692171, 1208567094120903},
|
||||
{2228417017817483, 202885584970535, 2182114782271881, 2077405042592934, 1029684358182774},
|
||||
{460447547653983, 627817697755692, 524899434670834, 1228019344939427, 740684787777653},
|
||||
{849757462467675, 447476306919899, 422618957298818, 302134659227815, 675831828440895},
|
||||
},
|
||||
}
|
||||
|
||||
ge_scalarmult :: proc "contextless" (ge, p: ^Group_Element, sc: ^Scalar) {
|
||||
tmp: field.Non_Montgomery_Domain_Field_Element
|
||||
field.fe_from_montgomery(&tmp, sc)
|
||||
|
||||
_ge_scalarmult(ge, p, &tmp)
|
||||
ge_scalarmult_raw(ge, p, &tmp)
|
||||
|
||||
mem.zero_explicit(&tmp, size_of(tmp))
|
||||
}
|
||||
|
||||
ge_scalarmult_basepoint :: proc "contextless" (ge: ^Group_Element, sc: ^Scalar) {
|
||||
// Something like the comb method from "Fast and compact elliptic-curve
|
||||
// cryptography" Section 3.3, would be more performant, but more
|
||||
// complex.
|
||||
//
|
||||
// - https://eprint.iacr.org/2012/309
|
||||
ge_scalarmult(ge, &GE_BASEPOINT, sc)
|
||||
}
|
||||
|
||||
ge_scalarmult_vartime :: proc "contextless" (ge, p: ^Group_Element, sc: ^Scalar) {
|
||||
tmp: field.Non_Montgomery_Domain_Field_Element
|
||||
field.fe_from_montgomery(&tmp, sc)
|
||||
|
||||
_ge_scalarmult(ge, p, &tmp, true)
|
||||
ge_scalarmult_raw(ge, p, &tmp, true)
|
||||
}
|
||||
|
||||
ge_double_scalarmult_basepoint_vartime :: proc "contextless" (
|
||||
@@ -147,6 +41,12 @@ ge_double_scalarmult_basepoint_vartime :: proc "contextless" (
|
||||
|
||||
A_tbl: Multiply_Table = ---
|
||||
mul_tbl_set(&A_tbl, A, &tmp_add)
|
||||
when crypto.COMPACT_IMPLS == true {
|
||||
G_tbl: Multiply_Table = ---
|
||||
mul_tbl_set(&G_tbl, &GE_BASEPOINT, &tmp_add)
|
||||
} else {
|
||||
tmp_bp_addend: Basepoint_Addend_Group_Element = ---
|
||||
}
|
||||
|
||||
sc_a, sc_b: field.Non_Montgomery_Domain_Field_Element
|
||||
field.fe_from_montgomery(&sc_a, a)
|
||||
@@ -170,21 +70,28 @@ ge_double_scalarmult_basepoint_vartime :: proc "contextless" (
|
||||
ge_double(&tmp, &tmp, &tmp_dbl)
|
||||
}
|
||||
mul_tbl_add(&tmp, &A_tbl, hi_a, &tmp_add, &tmp_addend, true)
|
||||
mul_tbl_add(&tmp, &GE_BASEPOINT_TABLE, hi_b, &tmp_add, &tmp_addend, true)
|
||||
when crypto.COMPACT_IMPLS == true {
|
||||
mul_tbl_add(&tmp, &G_tbl, hi_b, &tmp_add, &tmp_addend, true)
|
||||
} else {
|
||||
mul_bp_tbl_add(&tmp, GE_BASEPOINT_TABLE, hi_b, &tmp_add, &tmp_bp_addend, true)
|
||||
}
|
||||
|
||||
ge_double(&tmp, &tmp, &tmp_dbl)
|
||||
ge_double(&tmp, &tmp, &tmp_dbl)
|
||||
ge_double(&tmp, &tmp, &tmp_dbl)
|
||||
ge_double(&tmp, &tmp, &tmp_dbl)
|
||||
mul_tbl_add(&tmp, &A_tbl, lo_a, &tmp_add, &tmp_addend, true)
|
||||
mul_tbl_add(&tmp, &GE_BASEPOINT_TABLE, lo_b, &tmp_add, &tmp_addend, true)
|
||||
when crypto.COMPACT_IMPLS == true {
|
||||
mul_tbl_add(&tmp, &G_tbl, lo_b, &tmp_add, &tmp_addend, true)
|
||||
} else {
|
||||
mul_bp_tbl_add(&tmp, GE_BASEPOINT_TABLE, lo_b, &tmp_add, &tmp_bp_addend, true)
|
||||
}
|
||||
}
|
||||
|
||||
ge_set(ge, &tmp)
|
||||
}
|
||||
|
||||
@(private)
|
||||
_ge_scalarmult :: proc "contextless" (
|
||||
ge_scalarmult_raw :: proc "contextless" (
|
||||
ge, p: ^Group_Element,
|
||||
sc: ^field.Non_Montgomery_Domain_Field_Element,
|
||||
unsafe_is_vartime := false,
|
||||
|
||||
147
core/crypto/_edwards25519/edwards25519_scalar_mul_base.odin
Normal file
147
core/crypto/_edwards25519/edwards25519_scalar_mul_base.odin
Normal file
@@ -0,0 +1,147 @@
|
||||
package _edwards25519
|
||||
|
||||
import "core:crypto"
|
||||
import field "core:crypto/_fiat/field_curve25519"
|
||||
import scalar "core:crypto/_fiat/field_scalar25519"
|
||||
import subtle "core:crypto/_subtle"
|
||||
import "core:mem"
|
||||
|
||||
ge_scalarmult_basepoint :: proc "contextless" (ge: ^Group_Element, sc: ^Scalar) {
|
||||
when crypto.COMPACT_IMPLS == true {
|
||||
ge_scalarmult(ge, &GE_BASEPOINT, sc)
|
||||
} else {
|
||||
tmp_sc: scalar.Non_Montgomery_Domain_Field_Element
|
||||
scalar.fe_from_montgomery(&tmp_sc, sc)
|
||||
|
||||
tmp_add: Add_Scratch = ---
|
||||
tmp_addend: Basepoint_Addend_Group_Element = ---
|
||||
|
||||
ge_identity(ge)
|
||||
for i in 0..<32 {
|
||||
limb := i / 8
|
||||
shift := uint(i & 7) * 8
|
||||
limb_byte := tmp_sc[limb] >> shift
|
||||
|
||||
hi, lo := (limb_byte >> 4) & 0x0f, limb_byte & 0x0f
|
||||
mul_bp_tbl_add(ge, &Gen_Multiply_Table_edwards25519_lo[i], lo, &tmp_add, &tmp_addend, false)
|
||||
mul_bp_tbl_add(ge, &Gen_Multiply_Table_edwards25519_hi[i], hi, &tmp_add, &tmp_addend, false)
|
||||
}
|
||||
|
||||
mem.zero_explicit(&tmp_sc, size_of(tmp_sc))
|
||||
mem.zero_explicit(&tmp_add, size_of(Add_Scratch))
|
||||
mem.zero_explicit(&tmp_addend, size_of(Basepoint_Addend_Group_Element))
|
||||
}
|
||||
}
|
||||
|
||||
when crypto.COMPACT_IMPLS == false {
|
||||
@(private="file",rodata)
|
||||
TWO_TIMES_Z2 := field.Loose_Field_Element{2, 0, 0, 0, 0}
|
||||
|
||||
@(private)
|
||||
Basepoint_Addend_Group_Element :: struct {
|
||||
y2_minus_x2: field.Loose_Field_Element, // t1
|
||||
y2_plus_x2: field.Loose_Field_Element, // t3
|
||||
k_times_t2: field.Tight_Field_Element, // t4
|
||||
}
|
||||
|
||||
@(private)
|
||||
Basepoint_Multiply_Table :: [15]Basepoint_Addend_Group_Element
|
||||
|
||||
@(private)
|
||||
ge_bp_addend_conditional_assign :: proc "contextless" (ge_a, a: ^Basepoint_Addend_Group_Element, ctrl: int) {
|
||||
field.fe_cond_select(&ge_a.y2_minus_x2, &ge_a.y2_minus_x2, &a.y2_minus_x2, ctrl)
|
||||
field.fe_cond_select(&ge_a.y2_plus_x2, &ge_a.y2_plus_x2, &a.y2_plus_x2, ctrl)
|
||||
field.fe_cond_select(&ge_a.k_times_t2, &ge_a.k_times_t2, &a.k_times_t2, ctrl)
|
||||
}
|
||||
|
||||
@(private)
|
||||
ge_add_bp_addend :: proc "contextless" (
|
||||
ge, a: ^Group_Element,
|
||||
b: ^Basepoint_Addend_Group_Element,
|
||||
scratch: ^Add_Scratch,
|
||||
) {
|
||||
// https://www.hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html#addition-add-2008-hwcd-3
|
||||
// Assumptions: k=2*d, z = 1 (precomputation ftw)
|
||||
//
|
||||
// t0 = Y1-X1
|
||||
// t1 = Y2-X2
|
||||
// A = t0*t1
|
||||
// t2 = Y1+X1
|
||||
// t3 = Y2+X2
|
||||
// B = t2*t3
|
||||
// t4 = k*T2
|
||||
// C = T1*t4
|
||||
// t5 = 2*Z2
|
||||
// D = Z1*t5
|
||||
// E = B-A
|
||||
// F = D-C
|
||||
// G = D+C
|
||||
// H = B+A
|
||||
// X3 = E*F
|
||||
// Y3 = G*H
|
||||
// T3 = E*H
|
||||
// Z3 = F*G
|
||||
//
|
||||
// In order to make the scalar multiply faster, the addend is provided
|
||||
// as a `Addend_Group_Element` with t1, t3, t4, and t5 precomputed, as
|
||||
// it is trivially obvious that those are the only values used by the
|
||||
// formula that are directly dependent on `b`, and are only dependent
|
||||
// on `b` and constants. This saves 1 sub, 2 adds, and 1 multiply,
|
||||
// each time the intermediate representation can be reused.
|
||||
|
||||
A, B, C, D := &scratch.A, &scratch.B, &scratch.C, &scratch.D
|
||||
E, F, G, H := &scratch.E, &scratch.F, &scratch.G, &scratch.H
|
||||
t0, t2 := &scratch.t0, &scratch.t2
|
||||
|
||||
field.fe_sub(t0, &a.y, &a.x)
|
||||
t1 := &b.y2_minus_x2
|
||||
field.fe_carry_mul(A, t0, t1)
|
||||
field.fe_add(t2, &a.y, &a.x)
|
||||
t3 := &b.y2_plus_x2
|
||||
field.fe_carry_mul(B, t2, t3)
|
||||
t4 := &b.k_times_t2
|
||||
field.fe_carry_mul(C, field.fe_relax_cast(&a.t), field.fe_relax_cast(t4))
|
||||
field.fe_carry_mul(D, field.fe_relax_cast(&a.z), &TWO_TIMES_Z2)
|
||||
field.fe_sub(E, B, A)
|
||||
field.fe_sub(F, D, C)
|
||||
field.fe_add(G, D, C)
|
||||
field.fe_add(H, B, A)
|
||||
field.fe_carry_mul(&ge.x, E, F)
|
||||
field.fe_carry_mul(&ge.y, G, H)
|
||||
field.fe_carry_mul(&ge.t, E, H)
|
||||
field.fe_carry_mul(&ge.z, F, G)
|
||||
}
|
||||
|
||||
@(private)
|
||||
mul_bp_tbl_add :: proc "contextless" (
|
||||
ge: ^Group_Element,
|
||||
tbl: ^Basepoint_Multiply_Table,
|
||||
idx: u64,
|
||||
tmp_add: ^Add_Scratch,
|
||||
tmp_addend: ^Basepoint_Addend_Group_Element,
|
||||
unsafe_is_vartime: bool,
|
||||
) {
|
||||
// Variable time lookup, with the addition omitted entirely if idx == 0.
|
||||
if unsafe_is_vartime {
|
||||
// Skip adding the point at infinity.
|
||||
if idx != 0 {
|
||||
ge_add_bp_addend(ge, ge, &tbl[idx-1], tmp_add)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Constant time lookup.
|
||||
tmp_addend^ = {
|
||||
// Point at infinity (0, 1, 1, 0) in precomputed form, note
|
||||
// that the precomputed tables rescale so that `Z = 1`.
|
||||
{1, 0, 0, 0, 0}, // y - x
|
||||
{1, 0, 0, 0, 0}, // y + x
|
||||
{0, 0, 0, 0, 0}, // t * 2d
|
||||
}
|
||||
for i := u64(1); i < 16; i = i + 1 {
|
||||
ctrl := subtle.eq(i, idx)
|
||||
ge_bp_addend_conditional_assign(tmp_addend, &tbl[i - 1], int(ctrl))
|
||||
}
|
||||
ge_add_bp_addend(ge, ge, tmp_addend, tmp_add)
|
||||
}
|
||||
}
|
||||
4947
core/crypto/_edwards25519/edwards25519_table.odin
Normal file
4947
core/crypto/_edwards25519/edwards25519_table.odin
Normal file
File diff suppressed because it is too large
Load Diff
134
core/crypto/_edwards25519/tools/edwards_gen_tables.odin
Normal file
134
core/crypto/_edwards25519/tools/edwards_gen_tables.odin
Normal file
@@ -0,0 +1,134 @@
|
||||
package weistrass_tools
|
||||
|
||||
import ed "core:crypto/_edwards25519"
|
||||
import field "core:crypto/_fiat/field_curve25519"
|
||||
import scalar "core:crypto/_fiat/field_scalar25519"
|
||||
import "core:encoding/endian"
|
||||
import "core:fmt"
|
||||
import path "core:path/filepath"
|
||||
import "core:os"
|
||||
import "core:strings"
|
||||
|
||||
// Yes this leaks memory, fite me IRL.
|
||||
|
||||
GENERATED :: `/*
|
||||
------ GENERATED ------ DO NOT EDIT ------ GENERATED ------ DO NOT EDIT ------ GENERATED ------
|
||||
*/`
|
||||
|
||||
@(private, rodata)
|
||||
FE_D2 := field.Tight_Field_Element {
|
||||
1859910466990425,
|
||||
932731440258426,
|
||||
1072319116312658,
|
||||
1815898335770999,
|
||||
633789495995903,
|
||||
}
|
||||
|
||||
main :: proc() {
|
||||
Basepoint_Addend_Group_Element :: struct {
|
||||
y2_minus_x2: field.Loose_Field_Element, // t1
|
||||
y2_plus_x2: field.Loose_Field_Element, // t3
|
||||
k_times_t2: field.Tight_Field_Element, // t4
|
||||
}
|
||||
Basepoint_Multiply_Table :: [15]Basepoint_Addend_Group_Element
|
||||
|
||||
ge_bp_addend_set := proc(ge_a: ^Basepoint_Addend_Group_Element, ge: ^ed.Group_Element) {
|
||||
// We rescale so Z == 1, so T = X * Y
|
||||
x_, y_, z_inv: field.Tight_Field_Element
|
||||
field.fe_carry_inv(&z_inv, field.fe_relax_cast(&ge.z))
|
||||
field.fe_carry_mul(&x_, field.fe_relax_cast(&ge.x), field.fe_relax_cast(&z_inv))
|
||||
field.fe_carry_mul(&y_, field.fe_relax_cast(&ge.y), field.fe_relax_cast(&z_inv))
|
||||
|
||||
field.fe_sub(&ge_a.y2_minus_x2, &y_, &x_)
|
||||
field.fe_add(&ge_a.y2_plus_x2, &y_, &x_)
|
||||
field.fe_carry_mul(&ge_a.k_times_t2, field.fe_relax_cast(&x_), field.fe_relax_cast(&y_))
|
||||
field.fe_carry_mul(&ge_a.k_times_t2, field.fe_relax_cast(&ge_a.k_times_t2), field.fe_relax_cast(&FE_D2))
|
||||
}
|
||||
|
||||
Multiply_Table_hi: [32]Basepoint_Multiply_Table
|
||||
Multiply_Table_lo: [32]Basepoint_Multiply_Table
|
||||
|
||||
sc_set_unchecked := proc(sc: ^scalar.Non_Montgomery_Domain_Field_Element, b: []byte) {
|
||||
sc[0] = endian.unchecked_get_u64le(b[0:])
|
||||
sc[1] = endian.unchecked_get_u64le(b[8:])
|
||||
sc[2] = endian.unchecked_get_u64le(b[16:])
|
||||
sc[3] = endian.unchecked_get_u64le(b[24:])
|
||||
}
|
||||
|
||||
g, p: ed.Group_Element
|
||||
ed.ge_generator(&g)
|
||||
|
||||
sc: scalar.Non_Montgomery_Domain_Field_Element
|
||||
|
||||
// Precompute ([1,15] << n) * G multiples of G, LSB->MSB
|
||||
for i in 0..<32 {
|
||||
b: [32]byte
|
||||
for j in 1..<16 {
|
||||
b[i] = u8(j)
|
||||
sc_set_unchecked(&sc, b[:])
|
||||
ed.ge_scalarmult_raw(&p, &g, &sc, true)
|
||||
ge_bp_addend_set(&Multiply_Table_lo[i][j-1], &p)
|
||||
|
||||
b[i] = u8(j) << 4
|
||||
sc_set_unchecked(&sc, b[:])
|
||||
ed.ge_scalarmult_raw(&p, &g, &sc, true)
|
||||
ge_bp_addend_set(&Multiply_Table_hi[i][j-1], &p)
|
||||
|
||||
b[i] = 0
|
||||
}
|
||||
}
|
||||
|
||||
fn := path.join({ODIN_ROOT, "core", "crypto", "_edwards25519", "edwards25519_table.odin"})
|
||||
bld: strings.Builder
|
||||
w := strings.to_writer(&bld)
|
||||
|
||||
fmt.wprintln(w, "package _edwards25519")
|
||||
fmt.wprintln(w, "")
|
||||
fmt.wprintln(w, GENERATED)
|
||||
fmt.wprintln(w, "")
|
||||
fmt.wprintln(w, "import \"core:crypto\"")
|
||||
fmt.wprintln(w, "")
|
||||
fmt.wprintln(w, "when crypto.COMPACT_IMPLS == false {")
|
||||
|
||||
fmt.wprintln(w, "\t@(private,rodata)")
|
||||
fmt.wprintln(w, "\tGen_Multiply_Table_edwards25519_lo := [32]Basepoint_Multiply_Table {")
|
||||
for &v in Multiply_Table_lo {
|
||||
fmt.wprintln(w, "\t\t{")
|
||||
for &ap in v {
|
||||
fmt.wprintln(w, "\t\t\t{")
|
||||
|
||||
t1, t3, t4 := &ap.y2_minus_x2, &ap.y2_plus_x2, &ap.k_times_t2
|
||||
fmt.wprintf(w, "\t\t\t\t{{%d, %d, %d, %d, %d},\n", t1[0], t1[1], t1[2], t1[3], t1[4])
|
||||
fmt.wprintf(w, "\t\t\t\t{{%d, %d, %d, %d, %d},\n", t3[0], t3[1], t3[2], t3[3], t3[4])
|
||||
fmt.wprintf(w, "\t\t\t\t{{%d, %d, %d, %d, %d},\n", t4[0], t4[1], t4[2], t4[3], t4[4])
|
||||
|
||||
fmt.wprintln(w, "\t\t\t},")
|
||||
}
|
||||
fmt.wprintln(w, "\t\t},")
|
||||
}
|
||||
fmt.wprintln(w, "\t}\n")
|
||||
|
||||
fmt.wprintln(w, "\t@(private,rodata)")
|
||||
fmt.wprintln(w, "\tGen_Multiply_Table_edwards25519_hi := [32]Basepoint_Multiply_Table {")
|
||||
for &v in Multiply_Table_hi {
|
||||
fmt.wprintln(w, "\t\t{")
|
||||
for &ap in v {
|
||||
fmt.wprintln(w, "\t\t\t{")
|
||||
|
||||
t1, t3, t4 := &ap.y2_minus_x2, &ap.y2_plus_x2, &ap.k_times_t2
|
||||
fmt.wprintf(w, "\t\t\t\t{{%d, %d, %d, %d, %d},\n", t1[0], t1[1], t1[2], t1[3], t1[4])
|
||||
fmt.wprintf(w, "\t\t\t\t{{%d, %d, %d, %d, %d},\n", t3[0], t3[1], t3[2], t3[3], t3[4])
|
||||
fmt.wprintf(w, "\t\t\t\t{{%d, %d, %d, %d, %d},\n", t4[0], t4[1], t4[2], t4[3], t4[4])
|
||||
|
||||
fmt.wprintln(w, "\t\t\t},")
|
||||
}
|
||||
fmt.wprintln(w, "\t\t},")
|
||||
}
|
||||
fmt.wprintln(w, "\t}\n")
|
||||
|
||||
fmt.wprintln(w, "\tGE_BASEPOINT_TABLE := &Gen_Multiply_Table_edwards25519_lo[0]")
|
||||
|
||||
fmt.wprintln(w, "}")
|
||||
|
||||
_ = os.write_entire_file(fn, transmute([]byte)(strings.to_string(bld)))
|
||||
}
|
||||
@@ -6,6 +6,8 @@ See:
|
||||
*/
|
||||
package x25519
|
||||
|
||||
import "core:crypto"
|
||||
import ed "core:crypto/_edwards25519"
|
||||
import field "core:crypto/_fiat/field_curve25519"
|
||||
import "core:mem"
|
||||
|
||||
@@ -14,8 +16,10 @@ SCALAR_SIZE :: 32
|
||||
// POINT_SIZE is the size of a X25519 point (public key/shared secret) in bytes.
|
||||
POINT_SIZE :: 32
|
||||
|
||||
@(private, rodata)
|
||||
_BASE_POINT: [32]byte = {9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
when crypto.COMPACT_IMPLS == true {
|
||||
@(private,rodata)
|
||||
_BASE_POINT: [32]byte = {9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
}
|
||||
|
||||
@(private)
|
||||
_scalar_bit :: #force_inline proc "contextless" (s: ^[32]byte, i: int) -> u8 {
|
||||
@@ -111,19 +115,44 @@ scalarmult :: proc(dst, scalar, point: []byte) {
|
||||
e[31] &= 127
|
||||
e[31] |= 64
|
||||
|
||||
p: [32]byte = ---
|
||||
copy_slice(p[:], point)
|
||||
|
||||
d: [32]byte = ---
|
||||
_scalarmult(&d, &e, &p)
|
||||
copy_slice(dst, d[:])
|
||||
p := (^[32]byte)(raw_data(point))
|
||||
d := (^[32]byte)(raw_data(dst))
|
||||
_scalarmult(d, &e, p)
|
||||
|
||||
mem.zero_explicit(&e, size_of(e))
|
||||
mem.zero_explicit(&d, size_of(d))
|
||||
}
|
||||
|
||||
// scalarmult_basepoint "multiplies" the provided scalar with the X25519
|
||||
// base point and writes the resulting point to dst.
|
||||
scalarmult_basepoint :: proc(dst, scalar: []byte) {
|
||||
scalarmult(dst, scalar, _BASE_POINT[:])
|
||||
when crypto.COMPACT_IMPLS == true {
|
||||
scalarmult(dst, scalar, _BASE_POINT[:])
|
||||
} else {
|
||||
ensure(len(scalar) == SCALAR_SIZE, "crypto/x25519: invalid scalar size")
|
||||
ensure(len(dst) == POINT_SIZE, "crypto/x25519: invalid destination point size")
|
||||
|
||||
sc: ed.Scalar = ---
|
||||
ed.sc_set_bytes_rfc8032(&sc, scalar)
|
||||
|
||||
ge: ed.Group_Element = ---
|
||||
ed.ge_scalarmult_basepoint(&ge, &sc)
|
||||
|
||||
// u = (y + z)/(z - y)
|
||||
y_plus_z: field.Loose_Field_Element = ---
|
||||
z_minus_y: field.Loose_Field_Element = ---
|
||||
u: field.Tight_Field_Element = ---
|
||||
|
||||
field.fe_add(&y_plus_z, &ge.y, &ge.z)
|
||||
field.fe_sub(&z_minus_y, &ge.z, &ge.y)
|
||||
field.fe_carry_inv(&u, &z_minus_y)
|
||||
field.fe_carry_mul(&u, &y_plus_z, field.fe_relax_cast(&u))
|
||||
|
||||
dst_ := (^[32]byte)(raw_data(dst))
|
||||
field.fe_to_bytes(dst_, &u)
|
||||
|
||||
field.fe_clear_vec([]^field.Loose_Field_Element{&y_plus_z, &z_minus_y})
|
||||
field.fe_clear(&u)
|
||||
ed.sc_clear(&sc)
|
||||
ed.ge_clear(&ge)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user