Coverage report: /home/ellis/comp/ext/ironclad/src/public-key/elgamal.lisp
Kind | Covered | All | % |
expression | 0 | 688 | 0.0 |
branch | 0 | 34 | 0.0 |
Key
Not instrumented
Conditionalized out
Executed
Not executed
Both branches taken
One branch taken
Neither branch taken
1
;;;; elgamal.lisp -- implementation of the ElGamal encryption and signature scheme
5
(defclass elgamal-key ()
6
((group :initarg :group :reader group)))
8
(defclass elgamal-public-key (elgamal-key)
9
((y :initarg :y :reader elgamal-key-y :type integer)))
11
(defclass elgamal-private-key (elgamal-key)
12
((y :initarg :y :reader elgamal-key-y :type integer)
13
(x :initarg :x :reader elgamal-key-x :type integer)))
15
(defun elgamal-key-p (elgamal-key)
16
(group-pval (group elgamal-key)))
18
(defun elgamal-key-g (elgamal-key)
19
(group-gval (group elgamal-key)))
21
;;; function definitions
22
(defmethod make-public-key ((kind (eql :elgamal))
23
&key p g y &allow-other-keys)
25
(error 'missing-key-parameter
28
:description "modulus"))
30
(error 'missing-key-parameter
33
:description "generator"))
35
(error 'missing-key-parameter
38
:description "public key"))
39
(let ((group (make-instance 'discrete-logarithm-group :p p :g g)))
40
(make-instance 'elgamal-public-key :group group :y y)))
42
(defmethod destructure-public-key ((public-key elgamal-public-key))
43
(list :p (elgamal-key-p public-key)
44
:g (elgamal-key-g public-key)
45
:y (elgamal-key-y public-key)))
47
(defmethod make-private-key ((kind (eql :elgamal))
48
&key p g y x &allow-other-keys)
50
(error 'missing-key-parameter
53
:description "modulus"))
55
(error 'missing-key-parameter
58
:description "generator"))
60
(error 'missing-key-parameter
63
:description "private key"))
64
(let ((group (make-instance 'discrete-logarithm-group :p p :g g)))
65
(make-instance 'elgamal-private-key :group group :x x :y (or y (expt-mod g x p)))))
67
(defmethod destructure-private-key ((private-key elgamal-private-key))
68
(list :p (elgamal-key-p private-key)
69
:g (elgamal-key-g private-key)
70
:x (elgamal-key-x private-key)
71
:y (elgamal-key-y private-key)))
73
(defmethod generate-key-pair ((kind (eql :elgamal)) &key num-bits compatible-with-key &allow-other-keys)
74
(if compatible-with-key
75
(let* ((p (elgamal-key-p compatible-with-key))
76
(g (elgamal-key-g compatible-with-key))
77
(x (+ 2 (strong-random (- p 3))))
79
(values (make-private-key :elgamal :p p :g g :y y :x x)
80
(make-public-key :elgamal :p p :g g :y y)))
83
(error 'missing-key-parameter
86
:description "modulus size"))
87
(let* ((n (if (< num-bits 512)
88
(error 'ironclad-error
89
:format-control "NUM-BITS is too small for an Elgamal key.")
91
(q (generate-prime n))
92
(p (loop for z = (logior (ash 1 (- num-bits n 1))
93
(dpb 0 (byte 1 0) (random-bits (- num-bits n))))
95
until (and (= num-bits (integer-length p))
98
(g (find-subgroup-generator p q))
99
(x (+ 2 (strong-random (- p 3))))
100
(y (expt-mod g x p)))
101
(values (make-private-key :elgamal :p p :g g :y y :x x)
102
(make-public-key :elgamal :p p :g g :y y))))))
104
(defmethod generate-signature-nonce ((key elgamal-private-key) message &optional p)
105
(declare (ignore key message))
106
(or *signature-nonce-for-test*
108
for k = (+ 1 (strong-random (- p 2)))
109
until (= 1 (gcd k (- p 1)))
110
finally (return k))))
111
(defmethod generate-signature-nonce ((key elgamal-public-key) message &optional p)
112
;; The name 'generate-signature-nonce' is not really adapted here as it is
113
;; used for encryption. But is it worth adding a new generic function just
115
(declare (ignore key message))
116
(or *signature-nonce-for-test*
118
for k = (+ 1 (strong-random (- p 2)))
119
until (= 1 (gcd k (- p 1)))
120
finally (return k))))
122
(defmethod make-message ((kind (eql :elgamal)) &key c1 c2 n-bits &allow-other-keys)
124
(error 'missing-message-parameter
127
:description "first ciphertext element"))
129
(error 'missing-message-parameter
132
:description "second ciphertext element"))
134
(error 'missing-message-parameter
137
:description "modulus size"))
138
(concatenate '(simple-array (unsigned-byte 8) (*))
139
(integer-to-octets c1 :n-bits n-bits)
140
(integer-to-octets c2 :n-bits n-bits)))
142
(defmethod destructure-message ((kind (eql :elgamal)) message)
143
(let ((length (length message)))
145
(error 'invalid-message-length :kind 'elgamal)
146
(let* ((middle (/ length 2))
147
(n-bits (* middle 8))
148
(c1 (octets-to-integer message :start 0 :end middle))
149
(c2 (octets-to-integer message :start middle)))
150
(list :c1 c1 :c2 c2 :n-bits n-bits)))))
152
(defmethod encrypt-message ((key elgamal-public-key) msg &key (start 0) end oaep &allow-other-keys)
153
(let* ((p (elgamal-key-p key))
154
(pbits (integer-length p))
155
(g (elgamal-key-g key))
156
(y (elgamal-key-y key))
158
(octets-to-integer (oaep-encode oaep (subseq msg start end) (/ pbits 8)))
159
(octets-to-integer msg :start start :end end)))
160
(k (generate-signature-nonce key msg p))
161
(c1 (expt-mod g k p))
162
(c2 (mod (* m (expt-mod y k p)) p)))
164
(error 'invalid-message-length :kind 'elgamal))
165
(make-message :elgamal :c1 c1 :c2 c2 :n-bits pbits)))
167
(defmethod decrypt-message ((key elgamal-private-key) msg &key (start 0) end n-bits oaep &allow-other-keys)
168
(let* ((p (elgamal-key-p key))
169
(pbits (integer-length p))
170
(end (or end (length msg))))
171
(unless (= (* 4 (- end start)) pbits)
172
(error 'invalid-message-length :kind 'elgamal))
173
(let* ((x (elgamal-key-x key))
174
(message-elements (destructure-message :elgamal (subseq msg start end)))
175
(c1 (getf message-elements :c1))
176
(c2 (getf message-elements :c2))
177
(m (mod (* c2 (modular-inverse-with-blinding (expt-mod c1 x p) p)) p)))
179
(oaep-decode oaep (integer-to-octets m :n-bits pbits))
180
(integer-to-octets m :n-bits n-bits)))))
182
(defmethod make-signature ((kind (eql :elgamal)) &key r s n-bits &allow-other-keys)
184
(error 'missing-signature-parameter
187
:description "first signature element"))
189
(error 'missing-signature-parameter
192
:description "second signature element"))
194
(error 'missing-signature-parameter
197
:description "modulus size"))
198
(concatenate '(simple-array (unsigned-byte 8) (*))
199
(integer-to-octets r :n-bits n-bits)
200
(integer-to-octets s :n-bits n-bits)))
202
(defmethod destructure-signature ((kind (eql :elgamal)) signature)
203
(let ((length (length signature)))
205
(error 'invalid-signature-length :kind 'elgamal)
206
(let* ((middle (/ length 2))
207
(n-bits (* middle 8))
208
(r (octets-to-integer signature :start 0 :end middle))
209
(s (octets-to-integer signature :start middle)))
210
(list :r r :s s :n-bits n-bits)))))
212
(defmethod sign-message ((key elgamal-private-key) msg &key (start 0) end &allow-other-keys)
213
(let* ((m (octets-to-integer msg :start start :end end))
214
(p (elgamal-key-p key))
215
(pbits (integer-length p)))
216
(unless (< m (- p 1))
217
(error 'invalid-message-length :kind 'elgamal))
218
(let* ((g (elgamal-key-g key))
219
(x (elgamal-key-x key))
220
(k (generate-signature-nonce key msg p))
222
(s (mod (* (- m (* r x)) (modular-inverse-with-blinding k (- p 1))) (- p 1))))
224
(make-signature :elgamal :r r :s s :n-bits pbits)
225
(sign-message key msg :start start :end end)))))
227
(defmethod verify-signature ((key elgamal-public-key) msg signature &key (start 0) end &allow-other-keys)
228
(let* ((m (octets-to-integer msg :start start :end end))
229
(p (elgamal-key-p key))
230
(pbits (integer-length p)))
231
(unless (= (* 4 (length signature)) pbits)
232
(error 'invalid-signature-length :kind 'elgamal))
233
(unless (< m (- p 1))
234
(error 'invalid-message-length :kind 'elgamal))
235
(let* ((g (elgamal-key-g key))
236
(y (elgamal-key-y key))
237
(signature-elements (destructure-signature :elgamal signature))
238
(r (getf signature-elements :r))
239
(s (getf signature-elements :s)))
243
(mod (* (expt-mod y r p) (expt-mod r s p)) p))))))
245
(defmethod diffie-hellman ((private-key elgamal-private-key) (public-key elgamal-public-key))
246
(let ((p (elgamal-key-p private-key))
247
(p1 (elgamal-key-p public-key))
248
(g (elgamal-key-g private-key))
249
(g1 (elgamal-key-g public-key)))
250
(unless (and (= p p1) (= g g1))
251
(error 'incompatible-keys :kind 'elgamal))
252
(let ((pbits (integer-length p))
253
(x (elgamal-key-x private-key))
254
(y (elgamal-key-y public-key)))
255
(integer-to-octets (expt-mod y x p) :n-bits pbits))))