commit b6e4b6fc6594ab42430accb7c253a2bba18e6da2
parent f06a3a498093255a94ffa6adefa6023ef58a66d6
Author: Tomas Hlavaty <tom@logand.com>
Date: Sat, 30 Aug 2014 14:54:03 +0200
der encoder implemented
Diffstat:
M | der.lisp | | | 152 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------- |
1 file changed, 137 insertions(+), 15 deletions(-)
diff --git a/der.lisp b/der.lisp
@@ -50,11 +50,11 @@
(defun decode (reader)
(labels ((len ()
(let ((n (rw:next-u8 reader)))
- (if (zerop (ldb (byte 8 7) n))
- n
+ (if (logbitp 7 n)
(let ((z 0))
(dotimes (i (logand #x7f n) z)
- (setq z (logior (ash z 8) (rw:next-u8 reader))))))))
+ (setq z (logior (ash z 8) (rw:next-u8 reader)))))
+ n)))
(ascii ()
(let* ((n (len))
(z (make-string n)))
@@ -73,19 +73,19 @@
(let ((n (len)))
(assert (plusp n))
(let* ((z (rw:next-u8 reader))
- (p (zerop (ldb (byte 8 7) z))))
+ (p (logbitp 7 z)))
(dotimes (i (1- n))
(setq z (logior (ash z 8) (rw:next-u8 reader))))
- (if p z (- z (expt 2 (* 8 n)))))))
- (3 ;; bit_string
+ (if p (- z (expt 2 (* 8 n))) z))))
+ (3 ;; bit-string
(let ((n (len)))
(assert (plusp n))
(let ((m (rw:next-u8 reader))
(z 0))
;; TODO as octet string?
- (dotimes (i (1- n) (cons 'bit_string (ash z (- m))))
+ (dotimes (i (1- n) (cons 'bit-string (ash z (- m))))
(setq z (logior (ash z 8) (rw:next-u8 reader)))))))
- (4 ;; octet_string
+ (4 ;; octet-string
;; TODO variant with bounds
#+nil
(let* ((n (len)) ;; TODO why like SEQ in certificates?
@@ -103,7 +103,7 @@
(setf (aref z i) (rw:next-u8 reader)))))
(5 ;; null
(assert (eql 0 (rw:next-u8 reader))))
- (6 ;; object_identifier
+ (6 ;; oid
(let (z (n (len)))
(assert (plusp n))
(multiple-value-bind (d m) (floor (rw:next-u8 reader) 40)
@@ -114,8 +114,7 @@
while (plusp n)
do (let (e (a 0))
(loop
- until (zerop (ldb (byte 8 7)
- (setq e (rw:next-u8 reader))))
+ while (logbitp 7 (setq e (rw:next-u8 reader)))
do (progn
(decf n)
(setq a (logior (ash a 7) (logand #x7f e)))))
@@ -130,7 +129,7 @@
(dotimes (i n (cons 'utf8string (octets-to-utf8-string z)))
(setf (aref z i) (rw:next-u8 reader)))))
(19 ;; printablestring
- (cons 'printable_string (ascii)))
+ (cons 'printable-string (ascii)))
#+nil
(20 ;; t61string TeletexString #x14
(let* ((n (rw:next-u8 reader))
@@ -161,7 +160,7 @@
(80
(cons '???-key-identifier
(decode (rw:shorter-reader reader (len)))))
- (160 ;; ??? crl_extensions signed certificate version #xa0
+ (160 ;; ??? crl-extensions signed certificate version #xa0
;; (int inside) 2 = signed certificate v3
(cons '???-signed-certificate-version
(decode (rw:shorter-reader reader (len)))))
@@ -174,6 +173,123 @@
(cons '???-128 (decode (rw:shorter-reader reader (len)))))
))))
+(defun encode (writer x)
+ (labels ((len (n)
+ (assert (<= 0 n))
+ (if (logbitp 7 n)
+ (let ((nn (ceiling (log n 256))))
+ (assert (<= nn #x7f))
+ (rw:write-u8 writer (logior #x80 nn))
+ (loop
+ for i from (1- nn) downto 0
+ do (rw:write-u8 writer (ldb (byte 8 (* 8 i)) n))))
+ (rw:write-u8 writer n)))
+ (ascii (x)
+ (len (length x))
+ (loop
+ for x across x
+ do (let ((c (char-code x)))
+ (assert (< 0 c #x80))
+ (rw:write-u8 writer c))))
+ (seq (x)
+ (let* ((b (make-array 42 :fill-pointer 0 :adjustable t))
+ (w (rw:writer b)))
+ (dolist (x x)
+ (encode w x))
+ (len (length b))
+ (loop
+ for x across b
+ do (rw:write-u8 writer x)))))
+ (etypecase x
+ (null
+ (rw:write-u8 writer 5)
+ (rw:write-u8 writer 0))
+ (integer
+ (rw:write-u8 writer 2)
+ (cond
+ ((zerop x)
+ (rw:write-u8 writer 1)
+ (rw:write-u8 writer 0))
+ ((plusp x)
+ (let* ((nbits (floor (+ 2 (log x 2))))
+ (nbytes (ceiling nbits 8)))
+ (len nbytes)
+ (loop
+ for i from (1- nbytes) downto 0
+ do (rw:write-u8 writer (ldb (byte 8 (* 8 i)) x)))))
+ (t ;; minusp
+ (let* ((y (- x))
+ (nbits (ceiling (+ 1 (log y 2))))
+ (nbytes (ceiling nbits 8)))
+ (len nbytes)
+ (loop
+ for i from (1- nbytes) downto 0
+ do (rw:write-u8 writer (ldb (byte 8 (* 8 i)) x)))))))
+ (vector ;; octet-string
+ (rw:write-u8 writer 4)
+ (len (length x))
+ (loop
+ for x across x
+ do (rw:write-u8 writer x)))
+ (cons
+ (case (car x)
+ (boolean
+ (rw:write-u8 writer 1)
+ (rw:write-u8 writer 1)
+ (rw:write-u8 writer (if (cdr x) 255 0)))
+ ;;(bit-string 3)
+ (oid
+ (rw:write-u8 writer 6)
+ (let* ((b (make-array 42 :fill-pointer 0 :adjustable t))
+ (w (rw:writer b)))
+ (let ((x (cdr x)))
+ (rw:write-u8 w (+ (* 40 (pop x)) (pop x)))
+ (dolist (x x)
+ (let (z)
+ (do ((x x (ash x -7)))
+ ((< x #x80)
+ (push x z))
+ (push (logand #x7f x) z))
+ (do ()
+ ((not (cdr z))
+ (rw:write-u8 w (car z)))
+ (rw:write-u8 w (logior #x80 (pop z)))))))
+ (len (length b))
+ (loop
+ for x across b
+ do (rw:write-u8 writer x))))
+ (utf8string
+ (rw:write-u8 writer 12)
+ (let ((x (utf8-string-to-octets (cdr x))))
+ (len (length x))
+ (loop
+ for x across x
+ do (rw:write-u8 writer x))))
+ ;;(sequence 16)
+ ;;(set 17)
+ (printable-string
+ (rw:write-u8 writer 19)
+ (ascii (cdr x)))
+ ;;(t61string 20)
+ (ia5string
+ (rw:write-u8 writer 22)
+ (ascii (cdr x)))
+ (utctime
+ (rw:write-u8 writer 23)
+ (ascii (cdr x)))
+ (set
+ (rw:write-u8 writer 49)
+ (let* ((b (make-array 42 :fill-pointer 0 :adjustable t))
+ (w (rw:writer b)))
+ (encode w (cdr x))
+ (len (length b))
+ (loop
+ for x across b
+ do (rw:write-u8 writer x))))
+ (t ;; sequence
+ (rw:write-u8 writer 48)
+ (seq x)))))))
+
(let ((tests
'((nil (5 0))
(0 (2 1 0))
@@ -201,7 +317,7 @@
(6 9 #x2b 6 1 4 1 #x82 #x37 #x15 #x14))
((oid 1 2 840 113549 1 1 1)
(6 9 #x2a #x86 #x48 #x86 #xf7 #x0d 1 1 1))
- ((printable_string . "TestCN")
+ ((printable-string . "TestCN")
(#x13 6 #x54 #x65 #x73 #x74 #x43 #x4e))
((utf8string . "certreq")
(#x0c 7 #x63 #x65 #x72 #x74 #x72 #x65 #x71))
@@ -211,7 +327,13 @@
(49 16 48 14 2 1 #x80 6 9 #x2b 6 1 4 1 #x82 #x37 #x15 #x14))
)))
(dolist (test tests t)
- (assert (equalp (car test) (decode (rw:reader (cadr test)))))))
+ ;; (print (list :@@@ test))
+ ;; (finish-output)
+ (assert (equalp (car test) (decode (rw:reader (cadr test)))))
+ (assert (equalp (cadr test)
+ (let ((b (make-array 42 :fill-pointer 0 :adjustable t)))
+ (encode (rw:writer b) (car test))
+ (coerce b 'list))))))
;;(decode (rw:reader '(6 6 #x2a #x86 #x48 #x86 #xf7 #x0d)))
;;(decode (rw:reader '(3 4 6 #x6e #x5d #xc0))) ; '(:bit-string "011011100101110111")