-
Notifications
You must be signed in to change notification settings - Fork 14
/
ec-crypto.sml
executable file
·143 lines (118 loc) · 4.12 KB
/
ec-crypto.sml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
functor EllipticCurveCryptoFun (structure EllipticCurve : ELLIPTIC_CURVE
structure SecureRandom : RANDOM)
:>
ELLIPTIC_CURVE_CRYPTO
where type EC.Field.index = EllipticCurve.Field.index
where type EC.Field.elem = EllipticCurve.Field.elem
=
struct
structure EC = EllipticCurve
structure R = RandFromRandom (structure Random = SecureRandom)
open IntInf
fun mult (curve, n, pt) =
let
(* returns mX + acc *)
fun loop m X acc =
if m = 0 then
acc
else if andb (m, 1) = 0 then
loop (~>> (m, 0w1)) (EC.double (curve, X)) acc
else
loop (~>> (m, 0w1)) (EC.double (curve, X)) (EC.plus (curve, acc, X))
in
loop n pt EC.infinity
end
type param = { curve : EC.curve,
base : EC.point,
order : IntInf.int,
cofactor : IntInf.int }
type privkey = IntInf.int
type pubkey = EC.point
(* From "The Elliptic Curve Digital Signature Algorithm (ECDSA)" (Johnson, et al.), pp 23-24 *)
fun validParam ({curve, base, order, cofactor}:param) =
EC.validCurve curve
andalso
not (EC.eq (base, EC.infinity))
andalso
EC.validPoint (curve, base)
andalso
Arith.isprime order
andalso
Int.> (IntInf.log2 (order-1), 160)
andalso
let
val q = EC.Field.size (#index curve)
in
(* order > 4 sqrt(q) *)
order * order > 16 * q
andalso
EC.eq (mult (curve, order, base), EC.infinity)
andalso
let
val z = q + Arith.sqrt (<< (q, 0w2)) + 1 - order * cofactor
fun loop i =
Int.> (i, 20)
orelse
((IntInf.pow (q, i) - 1) mod order <> 0
andalso loop (Int.+ (i, 1)))
in
(* Check that floor( (sqrt(q) + 1)^2 / order ) = cofactor.
let order=n, cofactor=h
floor( (sqrt(q) + 1)^2 / n ) = h
iff
(sqrt(q) + 1)^2 / n - 1 < h <= (sqrt(q) + 1)^2 / n
iff
(sqrt(q) + 1)^2 - n < nh <= (sqrt(q) + 1)^2
nh <= (sqrt(q) + 1)^2
= q + 2 sqrt(q) + 1
= q + sqrt(4q) + 1
iff
q + sqrt(4q) + 1 - nh >= 0
iff
q + floor(sqrt(4q)) + 1 - nh >= 0 (since q and nh are integers)
nh > (sqrt(q) + 1)^2 - n
iff
nh + n > (sqrt(q) + 1)^2
= q + 2 sqrt(q) + 1
= q + sqrt(4q) + 1
iff
q + sqrt(4q) + 1 - nh < n
iff
q + floor(sqrt(4q)) + 1 - nh < n (since q and nh are integers)
*)
z >= 0
andalso
z < order
andalso
loop 1
andalso
order <> q
end
end
fun validPubkey ({curve, base, order, ...}:param, pt) =
EC.validPoint (curve, pt)
andalso
not (EC.eq (pt, EC.infinity))
andalso
EC.eq (mult (curve, order, pt), EC.infinity)
fun validPrivkey ({order, ...}:param, d) =
d > 0
andalso
d < order
fun newkey ({curve, base, order, ...}:param) =
let
val d = R.randIntInf (order-1) + 1
in
(mult (curve, d, base), d)
end
fun privkeyToPubkey ({curve, base, ...}:param, privkey) =
mult (curve, privkey, base)
end
structure EllipticCurveCryptoFp =
EllipticCurveCryptoFun
(structure EllipticCurve = EllipticCurveFp
structure SecureRandom = AESFortuna)
structure EllipticCurveCryptoF2m =
EllipticCurveCryptoFun
(structure EllipticCurve = EllipticCurveF2m
structure SecureRandom = AESFortuna)