Skip to content

Commit 5b00b44

Browse files
committed
Prototype RFC 9180 DHKEM (#80) (WIP)
1 parent 6dd6288 commit 5b00b44

File tree

2 files changed

+61
-37
lines changed

2 files changed

+61
-37
lines changed

prototype.demo.lisp

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
;; Create a key handle and issue a first batch of PID
1616
(defvar *kh*)
1717
(defvar *pid*)
18-
(multiple-value-bind (salt kh) (KEM-Encaps *pk-kem* *ID*)
18+
(multiple-value-bind (salt kh) (KEM-Encap *pk-kem*)
1919
(setf *kh* kh)
2020
(setf *pid* (loop for i in '(0 1 2 3)
2121
collect (make-document *evidence* salt i))))

prototype.lisp

+60-36
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
(defpackage #:prototype
2-
(:export #:KEM-Encaps
3-
#:HDK #:*ID*
2+
(:export #:KEM-Encap
3+
#:HDK
44
#:make-unit #:activate #:prove-possession #:request #:accept
55
#:make-reader #:pk #:verify
66
#:make-document)
@@ -66,29 +66,55 @@
6666
do (loop for j across ti do (vector-push j tb))
6767
finally (return (coerce tb '(vector (unsigned-byte 8))))))
6868

69-
(defun ECP2OS (point)
70-
(|| (I2OSP (getf (crypto:ec-destructure-point point) :x) 32)
71-
(I2OSP (getf (crypto:ec-destructure-point point) :y) 32)))
72-
(defun OS2ECP (b)
73-
(crypto:ec-make-point
74-
*EC* :x (OS2IP (subseq b 0 32)) :y (OS2IP (subseq b 32))))
75-
76-
(defun KEM-Derive-Key-Pair (msg ctx) ; TODO #80
77-
(let* ((*DST* (|| *ID* '(#x01) ctx))
78-
(*q* (EC-Order))
79-
(sk (hash_to_field msg)))
80-
(values (EC-Scalar-Base-Mult sk) sk)))
81-
(defun KEM-Encaps (pk ctx)
82-
(let* ((sk-prime (EC-Random))
83-
(pk-prime (EC-Scalar-Base-Mult sk-prime))
84-
(k-prime (ECDH-Create-Shared-Secret sk-prime pk))
85-
(prk (HKDF-Extract (I2OSP 0 32) k-prime)))
86-
(values (HKDF-Expand prk (|| (ASCII "TMPKEM") ctx) 32) (ECP2OS pk-prime))))
87-
(defun KEM-Decaps (sk c ctx)
88-
(let* ((pk-prime (OS2ECP c))
89-
(k-prime (ECDH-Create-Shared-Secret sk pk-prime))
90-
(prk (HKDF-Extract (I2OSP 0 32) k-prime)))
91-
(HKDF-Expand prk (|| (ASCII "TMPKEM") ctx) 32)))
69+
;; RFC 9180
70+
(defparameter *Nsecret* 32)
71+
(defparameter *Nsk* 32)
72+
(defparameter *suite_id* (I2OSP #x0010 2)) ;; DHKEM(P-256, HKDF-SHA256)
73+
(defparameter *bitmask* #xff)
74+
(labels ((LabeledExtract (salt label ikm)
75+
(HKDF-Extract salt (|| (ASCII "HPKE-v1") *suite_id* label ikm)))
76+
(LabeledExpand (prk label info L)
77+
(HKDF-Expand
78+
prk (|| (I2OSP L 2) (ASCII "HPKE-v1") *suite_id* label info)
79+
L))
80+
(ExtractAndExpand (dh kem_context)
81+
(let* ((eae_prk (LabeledExtract (ASCII "") (ASCII "eae_prk") dh))
82+
(shared_secret
83+
(LabeledExpand
84+
eae_prk (ASCII "shared_secret") kem_context *Nsecret*)))
85+
shared_secret))
86+
(GenerateKeyPair ()
87+
(let ((sk (EC-Random))) (values sk (EC-Scalar-Base-Mult sk))))
88+
(SerializePublicKey (pk)
89+
(|| (I2OSP (getf (crypto:ec-destructure-point pk) :x) 32)
90+
(I2OSP (getf (crypto:ec-destructure-point pk) :y) 32)))
91+
(DeserializePublicKey (b)
92+
(crypto:ec-make-point
93+
*EC* :x (OS2IP (subseq b 0 32)) :y (OS2IP (subseq b 32)))))
94+
(defun KEM-Derive-Key-Pair (ikm) ;; todo test vectors
95+
(loop with dkp_prk = (LabeledExtract (ASCII "") (ASCII "dkp_prk") ikm)
96+
for counter from 0 upto 254
97+
for bytes = (LabeledExpand dkp_prk (ASCII "candidate")
98+
(I2OSP counter 1) *Nsk*)
99+
for sk = (progn
100+
(setf (aref bytes 0) (logand (aref bytes 0) *bitmask*))
101+
(OS2IP bytes))
102+
when (not (= sk 0)) return (values sk (EC-Scalar-Base-Mult sk))))
103+
(defun KEM-Encap (pkR)
104+
(multiple-value-bind (skE pkE) (GenerateKeyPair)
105+
(let* ((dh (ECDH-Create-Shared-Secret skE pkR))
106+
(enc (SerializePublicKey pkE))
107+
(pkRm (SerializePublicKey pkR))
108+
(kem_context (|| enc pkRm))
109+
(shared_secret (ExtractAndExpand dh kem_context)))
110+
(values shared_secret enc))))
111+
(defun KEM-Decap (enc skR)
112+
(let* ((pkE (DeserializePublicKey enc))
113+
(dh (ECDH-Create-Shared-Secret skR pkE))
114+
(pkRm (SerializePublicKey (EC-Scalar-Base-Mult skR)))
115+
(kem_context (|| enc pkRm))
116+
(shared_secret (ExtractAndExpand dh kem_context)))
117+
shared_secret)))
92118

93119
(defun Authenticate (sk_device reader_data bf)
94120
(ECDH-Create-Shared-Secret sk_device (EC-Scalar-Mult reader_data bf)))
@@ -106,9 +132,9 @@
106132
(if (null bf) (fold salt (cdr path) bf-prime)
107133
(fold salt (cdr path)
108134
(BL-Combine-Blinding-Factors bf bf-prime)))))
109-
(t (multiple-value-bind (pk sk) (KEM-Derive-Key-Pair salt *ID*)
135+
(t (multiple-value-bind (pk sk) (KEM-Derive-Key-Pair salt)
110136
(declare (ignore pk))
111-
(fold (KEM-Decaps sk (car path) *ID*) (cdr path) bf)))))
137+
(fold (KEM-Decap (car path) sk) (cdr path) bf)))))
112138

113139
(defclass document () ((pk :reader pk :initarg :pk)))
114140
(defun make-document (doc salt index)
@@ -127,11 +153,11 @@
127153
(defun create-shared-secret (app hdk reader-pk)
128154
(Authenticate (cadr (device app)) reader-pk (fold (seed app) hdk)))
129155
(defun delegate-key-creation (app hdk)
130-
(KEM-Derive-Key-Pair (nth-value 1 (fold (seed app) hdk)) *ID*))
156+
(KEM-Derive-Key-Pair (nth-value 1 (fold (seed app) hdk))))
131157
(defun accept-key (app hdk kh index pk-expected)
132158
(multiple-value-bind (pk sk) (delegate-key-creation app hdk)
133159
(declare (ignore pk))
134-
(let ((salt (KEM-Decaps sk kh *ID*))
160+
(let ((salt (KEM-Decap kh sk))
135161
(pk-bl (get-key-info app hdk)))
136162
(assert (EC-Point-Equal
137163
pk-expected
@@ -200,16 +226,14 @@
200226
"3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34"
201227
"007208d5b887185865")))))
202228

203-
(assert (multiple-value-bind (pk sk) (KEM-Derive-Key-Pair
204-
(I2OSP #x01 4)
205-
(I2OSP #x02 4))
206-
(multiple-value-bind (k c) (KEM-Encaps pk (ASCII "info"))
207-
(= (OS2IP k) (OS2IP (KEM-Decaps sk c (ASCII "info")))))))
229+
(assert (multiple-value-bind (sk pk) (KEM-Derive-Key-Pair (I2OSP #x01 4))
230+
(multiple-value-bind (k c) (KEM-Encap pk)
231+
(= (OS2IP k) (OS2IP (KEM-Decap c sk))))))
208232

209233
(let* ((app (make-app))
210234
(pk-bl (get-key-info app +hdk-root+))
211235
(pk-kem (delegate-key-creation app +hdk-root+)))
212-
(multiple-value-bind (salt kh) (KEM-Encaps pk-kem *ID*)
236+
(multiple-value-bind (salt kh) (KEM-Encap pk-kem)
213237
(let ((pk-expected (BL-Blind-Public-Key pk-bl (HDK salt 0))))
214238
(accept-key app +hdk-root+ kh 0 pk-expected))))
215239

@@ -219,7 +243,7 @@
219243
(device-data (prove-possession unit doc (pk reader))))
220244
(assert (verify reader doc device-data)))
221245
(let ((pk-kem (request unit doc)))
222-
(multiple-value-bind (salt kh) (KEM-Encaps pk-kem *ID*)
246+
(multiple-value-bind (salt kh) (KEM-Encap pk-kem)
223247
(let* ((range '(0 1 2 3 4 5 6 7 8))
224248
(docs (loop for i in range collect (make-document doc salt i))))
225249
(loop for i in range for d in docs do (accept unit doc kh i d))

0 commit comments

Comments
 (0)