3 This program is free software
; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation
; either version 2 of the License, or
6 (at your option
) any later version.
8 This program is distributed in the hope that it will be useful
,
9 but WITHOUT ANY WARRANTY
; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
13 You should have received a copy of the GNU General Public License
14 along with this program
; if not, write to the Free Software
15 Foundation
, Inc.
, 51 Franklin Street
, Fifth Floor
, Boston
,
19 **** tools for cryptography
****************************************************
21 Copyright Volker van Nek
, 2015
23 1. string_to_octets
(string [,encoding
]) and octets_to_string
(octets [,encoding
]).
24 The default encoding depends on the underlying Lisp
, the platform and the
25 application. The following example shows Maxima
/GCL in a GNU
/Linux terminal.
26 GCL uses no format definition and simply passes through the utf-8-octets encoded
29 (%i1
) octets
: string_to_octets
("abc");
31 (%i2
) octets_to_string
(octets);
33 (%i3
) ibase
: obase
: 16.$
34 (%i4
) string
: unicode
(3bb);
36 (%i5
) octets
: string_to_octets
(string);
38 (%i6
) octets_to_string
(octets);
40 (%i7
) utf8_to_unicode
(octets);
43 Maxima
/SBCL in a GNU
/Linux terminal using the optional encoding argument.
45 (%i1
) ibase
: obase
: 16.$
46 (%i2
) string
: simplode
(map(unicode, [3b1
,3b2
,3b3
]));
48 (%i3
) octets
: string_to_octets
(string, "ucs-2be");
49 (%o3
) [3, 0B1
, 3, 0B2
, 3, 0B3
]
50 (%i4
) octets_to_string
(octets, "ucs-2be");
52 (%i5
) octets
: string_to_octets
(string, "iso-8859-7");
54 (%i6
) octets_to_string
(octets, "iso-8859-7");
57 Examples of supported encodings
:
58 CCL
,CLISP
,SBCL
: utf-8
, ucs-2be
, iso-8859-1
, cp1252
, cp850
59 CMUCL
: utf-8
, utf-16-be
, iso8859-1
, cp1252
60 ECL
: utf-8
, ucs-2be
, iso-8859-1
, windows-cp1252
, dos-cp850
62 2. number_to_octets
(number) and octets_to_number
(octets).
64 (%i1
) ibase
: obase
: 16.$
65 (%i2
) octets
: [0ca
,0fe
,0ba
,0be
]$
66 (%i3
) number
: octets_to_number
(octets);
68 (%i4
) number_to_octets
(number);
69 (%o4
) [0CA
, 0FE
, 0BA
, 0BE
]
72 3. octets_to_oid
(octets) and oid_to_octets
(string) compute object identifiers
73 (OIDs) from lists of octets and convert OIDs back to octets.
75 (%i1
) ibase
: obase
: 16.$
76 (%i2
) oid
: octets_to_oid
([2A
,86,48,86,0F7
,0D
,1,1,1]);
77 (%o2
) 1.2.840.113549.1.1.1
78 (%i3
) oid_to_octets
(oid);
79 (%o3
) [2A
, 86, 48, 86, 0F7
, 0D
, 1, 1, 1]
82 4. crc24sum
(octets) returns the crc24 checksum of an octet-list. The returned
83 value is a string
(default), a number or a list of octets.
85 Example
: OpenPGP uses crc24
87 -----BEGIN PGP SIGNATURE-----
88 Version
: GnuPG v2.0
.22 (GNU/Linux
)
90 iQEcBAEBAgAGBQJVdCTzAAoJEG
/1Mgf2DWAqCSYH
/AhVFwhu1D89C3
/QFcgVvZTM
91 wnOYzBUURJAL
/cT
+IngkLEpp3hEbREcugWp
+Tm6aw3R4CdJ7G3FLxExBH
/5KnDHi
92 rBQu
+I7
+3ySK2hpryQ6Wx5J9uZSa4YmfsNteR8up0zGkaulJeWkS4pjiRM
+auWVe
93 vajlKZCIK52P080DG7Q2dpshh4fgTeNwqCuCiBhQ73t8g1IaLdhDN6EzJVjGIzam
94 /spqT
/sTo6sw8yDOJjvU
+Qvn6
/mSMjC
/YxjhRMaQt9EMrR1AZ4ukBF5uG1S7mXOH
95 WdiwkSPZ3gnIBhM9SuC076gLWZUNs6NqTeE3UzMjDAFhH3jYk1T7mysCvdtIkms
=
97 -----END PGP SIGNATURE-----
99 (%i1
) ibase
: obase
: 16.$
100 (%i2
) sig64
: sconcat
(
101 "iQEcBAEBAgAGBQJVdCTzAAoJEG/1Mgf2DWAqCSYH/AhVFwhu1D89C3/QFcgVvZTM",
102 "wnOYzBUURJAL/cT+IngkLEpp3hEbREcugWp+Tm6aw3R4CdJ7G3FLxExBH/5KnDHi",
103 "rBQu+I7+3ySK2hpryQ6Wx5J9uZSa4YmfsNteR8up0zGkaulJeWkS4pjiRM+auWVe",
104 "vajlKZCIK52P080DG7Q2dpshh4fgTeNwqCuCiBhQ73t8g1IaLdhDN6EzJVjGIzam",
105 "/spqT/sTo6sw8yDOJjvU+Qvn6/mSMjC/YxjhRMaQt9EMrR1AZ4ukBF5uG1S7mXOH",
106 "WdiwkSPZ3gnIBhM9SuC076gLWZUNs6NqTeE3UzMjDAFhH3jYk1T7mysCvdtIkms=" )$
107 (%i3
) octets
: base64_decode
(sig64, 'list
)$
108 (%i4
) crc24
: crc24sum
(octets, 'list
);
118 (:compile-toplevel
:execute
)
119 (defvar old-ibase-cryptools
*read-base
*)
120 (setq *read-base
* 10.
) )
123 ;; -- string-octet-conversions: --------------------------------------------- ;;
125 (defun $string_to_octets
(str &optional enc
)
126 (unless (stringp str
)
127 (gf-merror (intl:gettext
"`string_to_octets': argument must be a string.")) )
128 (cons '(mlist simp
) (string-to-octets str enc
)) )
130 (defun string-to-octets (str &optional enc
)
131 (setq enc
(get-encoding enc
"string_to_octets"))
132 (let ((ov #+ccl
(ccl:encode-string-to-octets str
:external-format enc
) ;; maybe these (CCL, ECL) ..
133 #+clisp
(ext:convert-string-to-bytes str enc
)
134 #+ecl
(ecl-string-to-octets str enc
) ;; .. could move to intl.lisp
135 #-
(or ccl clisp ecl
) (intl::string-to-octets str enc
) )) ;; GCL ignores enc
139 (defun ecl-string-to-octets (str enc
)
141 (ceiling (* 1.2 (length str
))) ;; initially add 20 % for non-ascii chars
142 :element-type
'(unsigned-byte 8)
146 (stream (ext:make-sequence-output-stream a
:external-format enc
))
151 (defun $octets_to_string
(ol &optional enc
)
153 (gf-merror (intl:gettext
154 "`octets_to_string': argument must be a list of octets." )))
155 (octets-to-string (cdr ol
) enc
) )
157 (defun octets-to-string (ol &optional enc
)
158 (setq enc
(get-encoding enc
"octets_to_string"))
160 (make-array (length ol
) :element-type
'(unsigned-byte 8))
163 #+ccl
(ccl:decode-string-from-octets ov
:external-format enc
)
164 #+clisp
(ext:convert-string-from-bytes ov enc
)
165 #+ecl
(ecl-octets-to-string ov enc
)
166 #-
(or ccl clisp ecl
) (intl::octets-to-string ov enc
) ))
169 (defun ecl-octets-to-string (ov enc
)
171 (stream (ext:make-sequence-input-stream ov
:external-format enc
))
172 (read-line stream
) ))
175 ;; -- number-octet-conversions: --------------------------------------------- ;;
177 (defun word-to-octets (n) ;; assume that n fits into a word
178 (do ((k 4 (1- k
)) octs
)
180 (push (logand n
#xff
) octs
)
181 (setq n
(ash n -
8.
)) ))
183 (defun number-to-octets (n)
185 (push (logand n
#xff
) octs
)
187 (when (= n
0) (return octs
)) ))
189 (defun octets-to-number (octs)
190 (reduce #'(lambda (x y
) (logior (ash x
8.
) y
)) octs
) )
192 (defmfun $number_to_octets
(n)
193 (unless (and (integerp n
) (>= n
0))
194 (gf-merror (intl:gettext
195 "`number_to_octets': Argument must be a non-negative integer." )))
196 (cons '(mlist simp
) (number-to-octets n
)) )
198 (defmfun $octets_to_number
(octs)
199 (unless ($listp octs
)
200 (gf-merror (intl:gettext
201 "`octets_to_number': Argument must be a list of octets." )))
202 (octets-to-number (cdr octs
)) )
205 ;; -- object identifiers (OID): --------------------------------------------- ;;
209 ;; 1.2.840.113549.1.1.1 - RSA encryption
210 ;; 1.3.14.3.2.26 - SHA-1 hash algorithm
211 ;; 2.16.840.1.101.3.4.2.1 - SHA-256 hash algorithm
212 ;; 1.3.132.0.6 - secp112r1 - SEC 2 recommended elliptic curve
215 (defun oid-number-to-7bit (n)
218 (setq lst
(cons (logand n
127.
) lst
)
220 (when (= n
0) (return)) )
221 (setq lst
(nreverse lst
)
222 res
(list (car lst
)) )
223 (dolist (bit7 (cdr lst
) res
)
224 (setq res
(cons (logior bit7
128.
) res
)) )))
226 (defun oid-to-octets (str)
227 (let* ((*read-base
* 10.
)
228 (lst (mapcar #'(lambda (s) (with-input-from-string (a s
) (read a
)))
229 (split str
".") )) ;; stringproc.lisp/split
231 (when (< (length lst
) 2)
232 (gf-merror (intl:gettext
"No valid OID: ~m") str
) )
233 (setq oct
(+ (* 40.
(car lst
)) (cadr lst
))
235 (dolist (n (cddr lst
) octs
)
236 (setq octs
(append octs
(oid-number-to-7bit n
))) )))
238 (defmfun $oid_to_octets
(str)
239 (cons '(mlist simp
) (oid-to-octets str
)) )
243 (defun oid-split (lst)
248 (when (or (null lst
) (not (logbitp 7 n
)))
249 (return (values (nreverse res
) lst
)) )))
251 (defun octets-to-oid-1 (lst)
254 (setq res
(logior (logand n
127.
) res
))
255 (unless (logbitp 7 n
) (return res
))
256 (setq res
(ash res
7)) )))
258 (defun octets-to-oid (lst)
259 (if (= (length lst
) 0)
261 (let (str (tmp (car lst
)) (*print-base
* 10.
))
263 (multiple-value-bind (q r
) (truncate tmp
40.
)
264 (setq str
($sconcat q
"." r
))
265 (do () ((null lst
) str
)
266 (multiple-value-setq (tmp lst
) (oid-split lst
))
267 (setq str
($sconcat str
"." (octets-to-oid-1 tmp
))) )))))
269 (defmfun $octets_to_oid
(octets)
270 (octets-to-oid (cdr octets
)) )
273 ;; -- CRC24 checksum: ------------------------------------------------------- ;;
275 (defun crc24sum (lst)
279 (setq r
(logxor r
(ash oct
16.
)))
282 (when (logbitp 24. r
) (setq r
(logxor r poly
))) ))))
284 (defmfun $crc24sum
(octets &optional
(rtype '$string
))
286 (let ((crc24 (crc24sum (cdr octets
))))
288 ((equal rtype
'$list
)
289 (cons '(mlist simp
) (number-to-octets crc24
)) )
290 ((equal rtype
'$number
)
292 ((equal rtype
'$string
)
293 (nstring-downcase (format nil
"~6,'0x" crc24
)) )
295 (gf-merror (intl:gettext
296 "`crc24sum': Optional argument must be 'list, 'number or 'string." )))))
297 (gf-merror (intl:gettext
298 "`crc24sum': Argument must be a list of octets." ))))
302 (:compile-toplevel
:execute
)
303 (setq *read-base
* old-ibase-cryptools
) )