commit dd8ce8d50c2042bf76dc54e4c66529c27c1c47e6
parent b6e4b6fc6594ab42430accb7c253a2bba18e6da2
Author: Tomas Hlavaty <tom@logand.com>
Date:   Sat, 30 Aug 2014 16:23:58 +0200
read pem files added
Diffstat:
| M | base64.lisp |  |  | 45 | +++++++++++++++++++++++++-------------------- | 
| M | der.lisp |  |  | 43 | +++++++++++++++++++++++++++++++++++++++++++ | 
| M | rw.lisp |  |  | 7 | +++++++ | 
3 files changed, 75 insertions(+), 20 deletions(-)
diff --git a/base64.lisp b/base64.lisp
@@ -27,7 +27,7 @@
 
 (in-package :rw.base64)
 
-(defun encode-reader (reader &optional table wrap) ;; TODO wrap 76
+(defun encode-reader (reader &key table wrap) ;; TODO wrap 76
   (let (pending
         (table (or table
                    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/")))
@@ -39,7 +39,8 @@
          (flet ((%next ()
                   (let ((x (rw:next reader)))
                     (when x
-                      (logand #xff (if (characterp x) (char-code x) x)))))
+                      (assert (<= 0 x #xff))
+                      x)))
                 (%map (x n)
                   (char table (ldb (byte 6 n) x))))
            (let* ((a (%next))
@@ -51,7 +52,7 @@
              (push (%map x 12) pending)
              (%map x 18))))))))
 
-(defun decode-reader (reader &optional table) ;; TODO skip newlines?
+(defun decode-reader (reader &key table) ;; TODO skip newlines?
   (let (pending
         (table (or table
                    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/")))
@@ -60,21 +61,25 @@
         (pending (pop pending))
         ((not (rw:peek reader)) nil)
         (t
-         (flet ((%next ()
-                  (let ((x (rw:next reader)))
-                    (unless (eql #\= x)
-                      (position x table))))
-                (%map (x n)
-                  (code-char (ldb (byte 8 n) x))))
-           (let* ((a (%next))
-                  (b (%next))
-                  (c (%next))
-                  (d (%next))
-                  (x (+ (ash a 18) (ash b 12) (ash (or c 0) 6) (or d 0))))
-             (when d (push (%map x 0) pending))
-             (when c (push (%map x 8) pending))
-             (%map x 16))))))))
+         (rw:skip reader)
+         (let ((x (rw:peek reader)))
+           (when (and x (position x table))
+             (flet ((%next ()
+                      (let ((x (rw:next reader)))
+                        (unless (eql #\= x)
+                          (position x table))))
+                    (%map (x n)
+                      (ldb (byte 8 n) x)))
+               (let* ((a (%next))
+                      (b (%next))
+                      (c (%next))
+                      (d (%next))
+                      (x (+ (ash a 18) (ash b 12) (ash (or c 0) 6) (or d 0))))
+                 (when d (push (%map x 0) pending))
+                 (when c (push (%map x 8) pending))
+                 (%map x 16))))))))))
 
-;;(rw:till (rw:peek-reader (decode-reader (rw:peek-reader (encode-reader (rw:peek-reader (rw:reader "any carnal pleasure.")))))))
-;;(rw:till (rw:peek-reader (encode-reader (rw:peek-reader (rw:reader "any carnal pleasure.")))))
-;;(rw:till (rw:peek-reader (decode-reader (rw:peek-reader (rw:reader "YW55IGNhcm5hbCBwbGVhc3VyZS4=")))))
+;;(rw:till (rw:peek-reader (decode-reader (rw:peek-reader (encode-reader (rw:peek-reader (rw:reader #(1 2 3 4 32))))))))
+;;(rw:till (rw:peek-reader (encode-reader (rw:peek-reader (rw:wrap-reader (rw:reader "any carnal pleasure.") #'char-code)))))
+;;(rw:till (rw:peek-reader (rw:wrap-reader (decode-reader (rw:peek-reader (encode-reader (rw:peek-reader (rw:wrap-reader (rw:reader "any carnal pleasure.") #'char-code))))) #'code-char)))
+;;(rw:till (rw:peek-reader (rw:wrap-reader (decode-reader (rw:peek-reader (rw:reader "YW55IGNhcm5hbCBwbGVhc3VyZS4="))) #'code-char)))
diff --git a/der.lisp b/der.lisp
@@ -338,3 +338,46 @@
 ;;(decode (rw:reader '(6 6 #x2a #x86 #x48 #x86 #xf7 #x0d)))
 ;;(decode (rw:reader '(3 4 6 #x6e #x5d #xc0))) ; '(:bit-string "011011100101110111")
 ;;(encode w '(:bit-string "011011100101110111")) ;; '(3 4 6 #x6e #x5d #xc0)
+(defun read-pem-key (reader)
+  (let ((x (rw:till reader '(#\return #\newline))))
+    (rw:skip reader)
+    (cond
+      ;; -----BEGIN PRIVATE KEY-----
+      ((equal x
+              '(#\- #\- #\- #\- #\-
+                #\B #\E #\G #\I #\N #\space
+                #\P #\R #\I #\V #\A #\T #\E #\space
+                #\K #\E #\Y
+                #\- #\- #\- #\- #\-))
+       (prog1 (decode (rw.base64:decode-reader reader))
+         (rw:skip reader)
+         (assert
+          (equal '(#\- #\- #\- #\- #\-
+                   #\E #\N #\D #\space
+                   #\P #\R #\I #\V #\A #\T #\E #\space
+                   #\K #\E #\Y
+                   #\- #\- #\- #\- #\-)
+                 (rw:till reader '(#\return #\newline))))))
+      ;; -----BEGIN CERTIFICATE-----
+      ((equal x
+              '(#\- #\- #\- #\- #\-
+                #\B #\E #\G #\I #\N #\space
+                #\C #\E #\R #\T #\I #\F #\I #\C #\A #\T #\E
+                #\- #\- #\- #\- #\-))
+       (prog1 (decode (rw.base64:decode-reader reader))
+         (rw:skip reader)
+         (assert
+          (equal '(#\- #\- #\- #\- #\-
+                   #\E #\N #\D #\space
+                   #\C #\E #\R #\T #\I #\F #\I #\C #\A #\T #\E
+                   #\- #\- #\- #\- #\-)
+                 (rw:till reader '(#\return #\newline))))))
+      (t
+       (error "unexpected pem delimiter ~{~a~}" x)))))
+
+(defun read-pem-file (pathname)
+  (with-open-file (s pathname)
+    (let ((r (rw:peek-reader (rw:char-reader s))))
+      (loop
+         while (progn (rw:skip r) (rw:peek r))
+         collect (read-pem-key r)))))
diff --git a/rw.lisp b/rw.lisp
@@ -45,6 +45,7 @@
            :skip
            :slurp
            :till
+           :wrap-reader
            :write-octets
            :write-u16
            :write-u32
@@ -342,3 +343,9 @@
             (incf offset)
             (funcall reader))))
       reader))
+
+(defun wrap-reader (reader fn)
+  (lambda ()
+    (let ((z (rw:next reader)))
+      (when z
+        (funcall fn z)))))