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)

Reply via email to