├── LICENSE ├── README ├── package.lisp ├── secure-random.asd └── secure-random.lisp /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2011 by Anton Vodonosov (avodonosov@yandex.ru). 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Overview. 2 | ~~~~~~~~~ 3 | 4 | secure-random provides a cryptographically secure pseudo-random 5 | number generator (CSPRNG) for Common Lisp. 6 | 7 | Example: (SECURE-RANDOM:NUMBER 10) => 9 8 | 9 | We define an abstract interface for CSPRNG and provide a default 10 | implementation of that interface. 11 | 12 | The library API. 13 | ~~~~~~~~~~~~~~~~ 14 | 15 | Class SECURE-RANDOM:GENERATOR. 16 | The base class for all the possible implementations 17 | of a secure random number generator. 18 | 19 | Special variable SECURE-RANDOM:*GENERATOR*. 20 | Current value of the random number generator. Used as 21 | the default value for the library functions parameter GENERATOR. 22 | 23 | Generic function BYTES (COUNT GENERATOR) => random bytes. 24 | The only generic function which needs to be implemented 25 | by a subclass of SECURE-RANDOM:GENERATOR. Generates COUNT 26 | cryptographically strong pseudo-random bytes using the random 27 | number generator GENERATOR. Returns the bytes as a SIMPLE-ARRAY 28 | with ELEMENT-TYPE '(UNSIGNED-BYTE 8). Signals an ERROR in case 29 | of problems (for example when the random number generator 30 | failed to initialize itself with enough entrophy). 31 | 32 | Function NUMBER (LIMIT &optional (GENERATOR *GENERATOR*)) => random number. 33 | Returns a cryptographically strong pseudo-random number that 34 | is a non-negative number less than LIMIT and of the same 35 | type as LIMIT (in the current implementation, only INTEGER 36 | type is supporeted). LIMIT is a positive number. GENERATOR is an 37 | instance of a subclass of the SECURE-RANDOM:GENERATOR. Signals 38 | an ERROR in case of problems (for example when the random 39 | number generator failed to initialize itself with enough entrophy). 40 | 41 | Implementation notes. 42 | ~~~~~~~~~~~~~~~~~~~~~ 43 | 44 | The default implementation uses OpenSSL random number generator (via cl+ssl 45 | library). We started from the OpenSSL usage because it's the simplest way. 46 | 47 | Implementation of a pure Common Lisp CSPRNG is desirable, but it would 48 | require to write much more code. The problem is not in the CSPRNG algorithms 49 | themself, which are relatively simple (just read for example the Wikipedia article, 50 | and use Ironclad for the required building blocks). But the problem is in 51 | initialization of CSPRNG. Any CSPRNG needs to be initialized by some unguessable 52 | value. OpenSSL can gather the initial value from a platform specific service 53 | (/dev/random on Unix'es where it present, Windows Crypto API, 54 | Entropy Gathering Daemon, etc.). The pure Lisp CSPRNG library would need to 55 | re-implement all this code for gathering a truly unguessable initial value. 56 | 57 | Contact. 58 | ~~~~~~~~ 59 | 60 | Send questions or comments to avodonosov@yandex.ru 61 | -------------------------------------------------------------------------------- /package.lisp: -------------------------------------------------------------------------------- 1 | ;;; -*- Mode: LISP; Syntax: COMMON-LISP; indent-tabs-mode: nil; coding: utf-8; -*- 2 | ;;; 3 | ;;; Copyright (C) 2011 Anton Vodonosov (avodonosov@yandex.ru) 4 | ;;; 5 | ;;; See LICENSE for details. 6 | 7 | (defpackage #:secure-random 8 | (:use #:cl) 9 | (:export #:generator #:*generator* #:bytes #:number) 10 | (:shadow #:number)) 11 | 12 | -------------------------------------------------------------------------------- /secure-random.asd: -------------------------------------------------------------------------------- 1 | ;;; -*- Mode: LISP; Syntax: COMMON-LISP; indent-tabs-mode: nil; coding: utf-8; -*- 2 | ;;; 3 | ;;; Copyright (C) 2011 Anton Vodonosov (avodonosov@yandex.ru) 4 | ;;; 5 | ;;; See LICENSE for details. 6 | 7 | (asdf:defsystem #:secure-random 8 | :description "Cryptographically secure pseudo-random number generator for Common Lisp" 9 | :author "Anton Vodonosov " 10 | :license "MIT" 11 | :serial t 12 | :version "0.1.0" 13 | :depends-on (#:cl+ssl) 14 | :components ((:file "package") 15 | (:file "secure-random"))) 16 | 17 | -------------------------------------------------------------------------------- /secure-random.lisp: -------------------------------------------------------------------------------- 1 | ;;; -*- Mode: LISP; Syntax: COMMON-LISP; indent-tabs-mode: nil; coding: utf-8; -*- 2 | ;;; 3 | ;;; Copyright (C) 2011 Anton Vodonosov (avodonosov@yandex.ru) 4 | ;;; 5 | ;;; See LICENSE for details. 6 | 7 | (in-package #:secure-random) 8 | 9 | ;; ************* The libray public interface ************** 10 | 11 | (defclass generator () () 12 | (:documentation "The base class for all the possible implementations of 13 | secure random number generator.")) 14 | 15 | (defvar *generator* 16 | "Current value of the random number generator. Used as the 17 | default value for the library functions parameter GENERATOR.") 18 | 19 | (defgeneric bytes (count generator) 20 | (:documentation "The only generic function which needs to be implemented by a subclass 21 | of SECURE-RANDOM:GENERATOR. Generates COUNT cryptographically strong pseudo-random 22 | bytes using the random number generator GENERATOR. Returns the bytes as a 23 | SIMPLE-ARRAY with ELEMENT-TYPE '(UNSIGNED-BYTE 8). Signals 24 | an ERROR in case of problems (for example when the random number 25 | generator has not been initialized with enough entrophy).")) 26 | 27 | (defun number (limit &optional (generator *generator*)) 28 | "Returns a cryptographically strong pseudo-random number that is a 29 | non-negative number less than LIMIT and of the same type as LIMIT 30 | (in the current implementation, only INTEGER type is supporeted). 31 | LIMIT is a positive number. GENERATOR is an instance of a 32 | subclass of the SECURE-RANDOM:GENERATOR. Signals an ERROR in case 33 | of problems (for example when the random number generator has not been 34 | initialized with enough entrophy)." 35 | (let ((bytes-needed (1+ (truncate (/ (log limit 2) 36 | 8))))) 37 | (mod (octets-to-integer (bytes bytes-needed generator)) 38 | limit))) 39 | 40 | ;; ***************** Utils ********************* 41 | 42 | (defun octets-to-integer (octets-vec) 43 | (declare (type (array (unsigned-byte 8) (*)) octets-vec)) 44 | (loop with sum = 0 45 | for octet across octets-vec 46 | do (setf sum (+ octet (ash sum 8))) 47 | finally (return sum))) 48 | 49 | ;; ********* The implementation of the public interface ******** 50 | 51 | ;; The GENERATOR implementation which uses OpenSSL 52 | ;; random number generator 53 | (defclass open-ssl-generator (generator) ()) 54 | 55 | (defmethod bytes (count (generator open-ssl-generator)) 56 | (cl+ssl:random-bytes count)) 57 | 58 | ;; Use the OpenSSL RNG as the default implementation 59 | (setf *generator* (make-instance 'open-ssl-generator)) 60 | --------------------------------------------------------------------------------