I changed from one OS to another and I was missing a simple feature:
automatic password generation. To fill the gap with a Scheme I
implemented such a generator as a command line tool respectively /crypto
sweet/.
After having read /SRFI 27: Sources of Random Bits/ I decided to
implement my algorithm natively with /Guile 1.8/ and /Racket 6.1/. There
is some portability of simple RnRS System Scheme programs: right now it
seems that the "heritage" of the Scheme Shell (/scsh/) grants
portability across UNIX/POSIX/SUS systems.
Even when it comes to true randomness as perhaps generated by the noise
in the low order magnitudes/bits of hardware sensors which is enhanced
and accessible with the file system device entry "/dev/urandom" this
simple System Scheme Script remains portable. Accessing entropy pools on
other systems should be as easy - perhaps with the foreign function
interface.
With real entropy pools the need for the interface described by SRFI 27
vanishes almost completely. It's still a good idea to seed some
randomizing function with real entropy before using it but randomizing
functions do IMHO not constitute a domain of their own whereas SRFI 27
declares them to be.
--
You received this message because you are subscribed to the Google Groups "Racket
Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
#lang racket
;;
;; mti's Crypto Sweet: Human Typable Shared Secret (System Scheme)
;; (make-passwd.scm)
;;
;; Functional Programming seemed to be orthogonal to system
;; programming where data is passed in /pipelines/ and similar
;; concepts.
;;
;; This software is in the Public Domain as granted by the original
;; author.
;;
;; This implementation creates a human typable shared secret
;; especially for protecting online accounts and it should be in
;; conjunction with keychains or password managers. It is defined to
;; not use certain special characters which are known to be difficult
;; to find if the keyboard layout in software doesn't match the actual
;; inscriptions on the keys. It is designed to be usable with
;; secondary backups. Its shared secrets have the property of being
;; hard (but not impossible) to communicate by oral speech. They are
;; also hard to memorize especially when you can look at them only for
;; a short time. There might be other algorithms based on the
;; knowledge of the syllable structure of common western (and perhaps
;; other) languages that could produce secure /master passwords/ not
;; be held within keychains and password managers.
;;
;; The magnitude of the space of distinct shared secrets is high
;; enough to be considered secure with current authentication routines
;; in use on the Internet. For the original implementation with 65
;; characters and 12 positions it should be: (expt 65 12) which is
;; greater than
;;
;; (expt 64 12) => (expt (expt 2 6) 12) => (expt 2 72)
;;
;; You can improve it by adding your own preferred special
;; characters. TODO: It should take a command line argument
;; representing the length of the desired shared secret.
;;
;; Please consider changing the shared secrets (Soup of Letters) to
;; your needs: sometimes they force you to use special characters in
;; passwords although real randomness - as employed by this
;; implementation - allows shared secrets without them. Do not change
;; this implementation but add the needed characters to the final
;; shared secret yourself at some random position. A further useful
;; adaption would be insert spaces but beware that they might be
;; difficult to read on secondary backups.
;;
;; No abbreviations here: I want to see the characters.
(define *characters*
(append (string->list "ABCDEFGHIJKLMNOPQRSTUVWXYZ")
(string->list "abcdefghijklmnopqrstuvwxyz")
(string->list "1234567890")
(string->list "!,.")))
(define *number-of-characters* (length *characters*))
(define *length-of-password* 12)
(display "make-passwd: number-of-characters: ")
(display *number-of-characters*)
(display "; shared secret size: ")
(display *length-of-password*)
(newline)
(define (throw-dices randomness-port)
(let throw-dices ((n *length-of-password*))
(if (<= n 0)
'()
(cons (read-char randomness-port)
(throw-dices (- n 1))) )))
;(define dices->seed list->string)
;; XXXrnrs-port: racket algorithm/datagraph artifact
(define dices->seed (lambda (dices) (map char->integer dices)))
(display "make-passwd: Throwing Dices")
(define randomness-device "/dev/urandom") ; should be non-blocking pool access
;; /call-with-input-file/ opens the input device in text mode but see
;; the description of binary mode: no difference on UNIX systems. If
;; this changes perhaps due to Unicode system libraries we might get a
;; bias into our random data but as we use the dices only as the seed
;; for the randomizer we might get away with it. Please check your
;; system's source code for further information.
(define my-dices (call-with-input-file randomness-device
throw-dices))
(display " => the seeds have been thrown: #")
(display (length my-dices))
(newline)
(define (get-new-state)
(if (null? my-dices)
(display "make-passwd: Oh dear, we failed! --")
(let ((dice (car my-dices)))
(set! my-dices (cdr my-dices))
(dices->seed (list dice)) )))
(define (x n)
"This procedure is undocumented."
(if (<= n 0)
'()
(begin
(random-seed (car (get-new-state)))
(cons (random *number-of-characters*)
(x (- n 1)))) ))
(define (soup n)
(map (lambda (index)
(list-ref *characters* index))
(x n)))
(define (make-passwd)
(display "Soup of Letters: ")
(display (list->string (soup 12)))
(newline))
(make-passwd)
#!/usr/bin/guile -s
!#
;;
;; mti's Crypto Sweet: Human Typable Shared Secret (System Scheme)
;; (make-passwd.scm)
;;
;; Functional Programming seemed to be orthogonal to system
;; programming where data is passed in /pipelines/ and similar
;; concepts.
;;
;; This software is in the Public Domain as granted by the original
;; author.
;;
;; This implementation creates a human typable shared secret
;; especially for protecting online accounts and it should be in
;; conjunction with keychains or password managers. It is defined to
;; not use certain special characters which are known to be difficult
;; to find if the keyboard layout in software doesn't match the actual
;; inscriptions on the keys. It is designed to be usable with
;; secondary backups. Its shared secrets have the property of being
;; hard (but not impossible) to communicate by oral speech. They are
;; also hard to memorize especially when you can look at them only for
;; a short time. There might be other algorithms based on the
;; knowledge of the syllable structure of common western (and perhaps
;; other) languages that could produce secure /master passwords/ not
;; be held within keychains and password managers.
;;
;; The magnitude of the space of distinct shared secrets is high
;; enough to be considered secure with current authentication routines
;; in use on the Internet. For the original implementation with 65
;; characters and 12 positions it should be: (expt 65 12) which is
;; greater than
;;
;; (expt 64 12) => (expt (expt 2 6) 12) => (expt 2 72)
;;
;; You can improve it by adding your own preferred special
;; characters. TODO: It should take a command line argument
;; representing the length of the desired shared secret.
;;
;; Please consider changing the shared secrets (Soup of Letters) to
;; your needs: sometimes they force you to use special characters in
;; passwords although real randomness - as employed by this
;; implementation - allows shared secrets without them. Do not change
;; this implementation but add the needed characters to the final
;; shared secret yourself at some random position. A further useful
;; adaption would be insert spaces but beware that they might be
;; difficult to read on secondary backups.
;;
;; No abbreviations here: I want to see the characters.
(define *characters*
(append (string->list "ABCDEFGHIJKLMNOPQRSTUVWXYZ")
(string->list "abcdefghijklmnopqrstuvwxyz")
(string->list "1234567890")
(string->list "!,.")))
(define *number-of-characters* (length *characters*))
(define *length-of-password* 12)
(display "make-passwd: number-of-characters: ")
(display *number-of-characters*)
(display "; shared secret size: ")
(display *length-of-password*)
(newline)
(define (throw-dices randomness-port)
(let throw-dices ((n *length-of-password*))
(if (<= n 0)
'()
(cons (read-char randomness-port)
(throw-dices (- n 1))) )))
(define dices->seed list->string)
(display "make-passwd: Throwing Dices")
(define randomness-device "/dev/urandom") ; should be non-blocking pool access
;; /call-with-input-file/ opens the input device in text mode but see
;; the description of binary mode: no difference on UNIX systems. If
;; this changes perhaps due to Unicode system libraries we might get a
;; bias into our random data but as we use the dices only as the seed
;; for the randomizer we might get away with it. Please check your
;; system's source code for further information.
(define my-dices (call-with-input-file randomness-device
throw-dices))
(display " => the seeds have been thrown: #")
(display (length my-dices))
(newline)
(define (get-new-state)
(if (null? my-dices)
(display "make-passwd: Oh dear, we failed! --")
(let ((dice (car my-dices)))
(set! my-dices (cdr my-dices))
(seed->random-state (dices->seed (list dice))) )))
(define (x n)
"This procedure is undocumented."
(if (<= n 0)
'()
(cons (random *number-of-characters* (get-new-state))
(x (- n 1))) ))
(define (soup n)
(map (lambda (index)
(list-ref *characters* index))
(x n)))
(define (make-passwd)
(display "Soup of Letters: ")
(display (list->string (soup 12)))
(newline))
(make-passwd)