1 ;;; rander.el -- possibly better random numbers, using rc16 as a RNG
3 ;; Copyright (C) 1998 Ray Jones
5 ;; Author: Ray Jones, rjones@pobox.com
6 ;; Keywords: RNG, rc4, rc16, stream cipher
9 ;; This program is free software; you can redistribute it and/or modify
10 ;; it under the terms of the GNU General Public License as published by
11 ;; the Free Software Foundation; either version 2, or (at your option)
14 ;; This program is distributed in the hope that it will be useful,
15 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 ;; GNU General Public License for more details.
19 ;; You should have received a copy of the GNU General Public License
20 ;; along with this program; if not, you can either send email to this
21 ;; program's maintainer or write to: The Free Software Foundation,
22 ;; Inc.; 675 Massachusetts Avenue; Cambridge, MA 02139, USA.
28 (defvar *rander-file* (expand-file-name "~/.emacs.rander"))
29 (defvar *rander-file-length* 512)
31 ;;; Initialization of the random state
33 ;; generate a string with random information in it
34 (defun rander-noise-string ()
36 ;; randomness from before
37 (if (file-readable-p *rander-file*)
41 (setq buf (generate-new-buffer "randerdata"))
44 (insert-file-contents-literally *rander-file*)
47 (let ((kill-buffer-hook nil))
48 (kill-buffer buf))))))
50 ;; allocation randomness
51 (if (boundp 'cons-cells-consed)
53 (mapcar 'int-to-string
54 (list cons-cells-consed
60 vector-cells-consed)))
64 (apply 'concat (mapcar 'int-to-string (current-time)))
67 (int-to-string (emacs-pid))))
70 ;;; Mixin keypress randomness, on the fly
72 ;; don't use this if your (current-time) is not fine grained in the
73 ;; microseconds. or if your computer is particularly slow, and the
74 ;; pre-command-hook stuff slows it down (unlikely).
75 (defvar *rander-use-keypress* t)
76 ;; this number shouldn't be too high, as a call to (rander16) will
77 ;; have to mixin up to this many values before actually returning
78 (defvar *rander-keypress-count* 128)
79 (defvar *rander-keypress-timings*
80 (and *rander-use-keypress*
81 (make-vector *rander-keypress-count* 0)))
82 (defvar *rander-keypress-have* 0)
84 (defun rander-store-key-time ()
85 "store keypress timings until we have filled the keypress timings buffer"
86 (when (< *rander-keypress-have* *rander-keypress-count*)
87 (aset *rander-keypress-timings*
88 *rander-keypress-have*
89 (nth 2 (current-time)))
90 (incf *rander-keypress-have*)))
92 (if *rander-use-keypress*
93 (add-hook 'pre-command-hook 'rander-store-key-time))
95 ;;; main source of randomness, the rc16 generator
96 (defvar *rander-initialized* nil)
97 (defvar *rander-rc16-context* nil)
100 (setq *rander-rc16-context* (rc16-create-context))
101 (rc16-set-key *rander-rc16-context* (rander-noise-string))
102 (add-hook 'kill-emacs-hook 'rander-write-file)
103 (setq *rander-initialized* t))
106 (if (not *rander-initialized*)
108 (when (and *rander-use-keypress*
109 (not (zerop *rander-keypress-have*)))
110 ;; mixin all the keypresses we have stored to this point
111 (dotimes (idx *rander-keypress-have*)
112 (rc16-mixin *rander-rc16-context*
113 (aref *rander-keypress-timings* idx)))
115 (setq *rander-keypress-have* 0))
117 ;; return a random value
118 (rc16-short *rander-rc16-context*))
120 (defun rander-write-file ()
121 "write out a seed file for the next time rander is used. called at
126 (setq buf (generate-new-buffer "randerdata"))
129 (dotimes (count *rander-file-length*)
130 (insert (logand ?\xff (rander16))))
131 (let ((backup-inhibited t))
132 (write-file *rander-file*))))
134 (let ((kill-buffer-hook nil))
135 (kill-buffer buf))))))