Initial Commit
[packages] / xemacs-packages / ecrypto / rander.el
1 ;;;  rander.el -- possibly better random numbers, using rc16 as a RNG
2
3 ;; Copyright (C) 1998 Ray Jones
4
5 ;; Author: Ray Jones, rjones@pobox.com
6 ;; Keywords: RNG, rc4, rc16, stream cipher
7 ;; Created: 1998-04-14
8
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)
12 ;; any later version.
13 ;;
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.
18 ;;
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.
23
24
25 (require 'cl)
26 (require 'rc16)
27
28 (defvar *rander-file* (expand-file-name "~/.emacs.rander"))
29 (defvar *rander-file-length* 512)
30
31 ;;; Initialization of the random state
32
33 ;; generate a string with random information in it
34 (defun rander-noise-string ()
35   (concat
36    ;; randomness from before
37    (if (file-readable-p *rander-file*)
38        (let ((buf nil))
39          (unwind-protect
40              (progn
41                (setq buf (generate-new-buffer "randerdata"))
42                (save-excursion
43                  (set-buffer buf)
44                  (insert-file-contents-literally *rander-file*)
45                  (buffer-string)))
46            (if buf
47                (let ((kill-buffer-hook nil))
48                  (kill-buffer buf))))))
49
50    ;; allocation randomness
51    (if (boundp 'cons-cells-consed)
52        (apply 'concat 
53               (mapcar 'int-to-string 
54                       (list cons-cells-consed
55                             floats-consed
56                             intervals-consed
57                             misc-objects-consed
58                             string-chars-consed
59                             symbols-consed
60                             vector-cells-consed)))
61        "")
62    
63    ;; time randomness
64    (apply 'concat (mapcar 'int-to-string (current-time)))
65    
66    ;; process randomness
67    (int-to-string (emacs-pid))))
68
69
70 ;;; Mixin keypress randomness, on the fly
71
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)
83
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*)))
91
92 (if *rander-use-keypress*
93     (add-hook 'pre-command-hook 'rander-store-key-time))
94
95 ;;; main source of randomness, the rc16 generator
96 (defvar *rander-initialized* nil)
97 (defvar *rander-rc16-context* nil)
98
99 (defun rander-init ()
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))
104
105 (defun rander16 ()
106   (if (not *rander-initialized*)
107       (rander-init))
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)))
114     ;; reset the buffer
115     (setq *rander-keypress-have* 0))
116
117   ;; return a random value
118   (rc16-short *rander-rc16-context*))
119
120 (defun rander-write-file ()
121   "write out a seed file for the next time rander is used.  called at
122 the exit of emacs."  
123   (let ((buf nil))
124     (unwind-protect
125         (progn
126           (setq buf (generate-new-buffer "randerdata"))
127           (save-excursion
128             (set-buffer buf)
129             (dotimes (count *rander-file-length*)
130               (insert (logand ?\xff (rander16))))
131             (let ((backup-inhibited t))
132               (write-file *rander-file*))))
133       (if buf
134           (let ((kill-buffer-hook nil))
135             (kill-buffer buf))))))
136
137 (provide 'rander)