comparison lisp/gnus/md5.el @ 114:8619ce7e4c50 r20-1b9

Import from CVS: tag r20-1b9
author cvs
date Mon, 13 Aug 2007 09:21:54 +0200
parents 1a767b41a199
children
comparison
equal deleted inserted replaced
113:2ec2fe4a4c89 114:8619ce7e4c50
9 ;;; Details: ------------------------------------------------------------------ 9 ;;; Details: ------------------------------------------------------------------
10 10
11 ;; This is a direct translation into Emacs LISP of the reference C 11 ;; This is a direct translation into Emacs LISP of the reference C
12 ;; implementation of the MD5 Message-Digest Algorithm written by RSA 12 ;; implementation of the MD5 Message-Digest Algorithm written by RSA
13 ;; Data Security, Inc. 13 ;; Data Security, Inc.
14 ;; 14 ;;
15 ;; The algorithm takes a message (that is, a string of bytes) and 15 ;; The algorithm takes a message (that is, a string of bytes) and
16 ;; computes a 16-byte checksum or "digest" for the message. This digest 16 ;; computes a 16-byte checksum or "digest" for the message. This digest
17 ;; is supposed to be cryptographically strong in the sense that if you 17 ;; is supposed to be cryptographically strong in the sense that if you
18 ;; are given a 16-byte digest D, then there is no easier way to 18 ;; are given a 16-byte digest D, then there is no easier way to
19 ;; construct a message whose digest is D than to exhaustively search the 19 ;; construct a message whose digest is D than to exhaustively search the
20 ;; space of messages. However, the robustness of the algorithm has not 20 ;; space of messages. However, the robustness of the algorithm has not
21 ;; been proven, and a similar algorithm (MD4) was shown to be unsound, 21 ;; been proven, and a similar algorithm (MD4) was shown to be unsound,
22 ;; so treat with caution! 22 ;; so treat with caution!
23 ;; 23 ;;
24 ;; The C algorithm uses 32-bit integers; because GNU Emacs 24 ;; The C algorithm uses 32-bit integers; because GNU Emacs
25 ;; implementations provide 28-bit integers (with 24-bit integers on 25 ;; implementations provide 28-bit integers (with 24-bit integers on
26 ;; versions prior to 19.29), the code represents a 32-bit integer as the 26 ;; versions prior to 19.29), the code represents a 32-bit integer as the
27 ;; cons of two 16-bit integers. The most significant word is stored in 27 ;; cons of two 16-bit integers. The most significant word is stored in
28 ;; the car and the least significant in the cdr. The algorithm requires 28 ;; the car and the least significant in the cdr. The algorithm requires
31 31
32 ;;; Usage: -------------------------------------------------------------------- 32 ;;; Usage: --------------------------------------------------------------------
33 33
34 ;; To compute the MD5 Message Digest for a message M (represented as a 34 ;; To compute the MD5 Message Digest for a message M (represented as a
35 ;; string or as a vector of bytes), call 35 ;; string or as a vector of bytes), call
36 ;; 36 ;;
37 ;; (md5-encode M) 37 ;; (md5-encode M)
38 ;; 38 ;;
39 ;; which returns the message digest as a vector of 16 bytes. If you 39 ;; which returns the message digest as a vector of 16 bytes. If you
40 ;; need to supply the message in pieces M1, M2, ... Mn, then call 40 ;; need to supply the message in pieces M1, M2, ... Mn, then call
41 ;; 41 ;;
42 ;; (md5-init) 42 ;; (md5-init)
43 ;; (md5-update M1) 43 ;; (md5-update M1)
44 ;; (md5-update M2) 44 ;; (md5-update M2)
45 ;; ... 45 ;; ...
46 ;; (md5-update Mn) 46 ;; (md5-update Mn)
48 48
49 ;;; Copyright and licence: ---------------------------------------------------- 49 ;;; Copyright and licence: ----------------------------------------------------
50 50
51 ;; Copyright (C) 1995 by Gareth Rees 51 ;; Copyright (C) 1995 by Gareth Rees
52 ;; Derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm 52 ;; Derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm
53 ;; 53 ;;
54 ;; md5.el is free software; you can redistribute it and/or modify it 54 ;; md5.el is free software; you can redistribute it and/or modify it
55 ;; under the terms of the GNU General Public License as published by the 55 ;; under the terms of the GNU General Public License as published by the
56 ;; Free Software Foundation; either version 2, or (at your option) any 56 ;; Free Software Foundation; either version 2, or (at your option) any
57 ;; later version. 57 ;; later version.
58 ;; 58 ;;
59 ;; md5.el is distributed in the hope that it will be useful, but WITHOUT 59 ;; md5.el is distributed in the hope that it will be useful, but WITHOUT
60 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 60 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
61 ;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 61 ;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
62 ;; for more details. 62 ;; for more details.
63 ;; 63 ;;
64 ;; The original copyright notice is given below, as required by the 64 ;; The original copyright notice is given below, as required by the
65 ;; licence for the original code. This code is distributed under *both* 65 ;; licence for the original code. This code is distributed under *both*
66 ;; RSA's original licence and the GNU General Public Licence. (There 66 ;; RSA's original licence and the GNU General Public Licence. (There
67 ;; should be no problems, as the former is more liberal than the 67 ;; should be no problems, as the former is more liberal than the
68 ;; latter). 68 ;; latter).
153 153
154 ;; FF, GG, HH and II are basic MD5 functions, providing transformations 154 ;; FF, GG, HH and II are basic MD5 functions, providing transformations
155 ;; for rounds 1, 2, 3 and 4 respectively. Each function follows this 155 ;; for rounds 1, 2, 3 and 4 respectively. Each function follows this
156 ;; pattern of computation (where ROTATE(x,y) means rotate 32-bit value x 156 ;; pattern of computation (where ROTATE(x,y) means rotate 32-bit value x
157 ;; by y bits to the left): 157 ;; by y bits to the left):
158 ;; 158 ;;
159 ;; FF(a,b,c,d,x,s,ac) = ROTATE(a + F(b,c,d) + x + ac,s) + b 159 ;; FF(a,b,c,d,x,s,ac) = ROTATE(a + F(b,c,d) + x + ac,s) + b
160 ;; 160 ;;
161 ;; so we use the macro `md5-make-step' to construct each one. The 161 ;; so we use the macro `md5-make-step' to construct each one. The
162 ;; helper functions F, G, H and I operate on 16-bit numbers; the full 162 ;; helper functions F, G, H and I operate on 16-bit numbers; the full
163 ;; operation splits its inputs, operates on the halves separately and 163 ;; operation splits its inputs, operates on the halves separately and
164 ;; then puts the results together. 164 ;; then puts the results together.
165 165
188 (md5-make-step md5-GG md5-G) 188 (md5-make-step md5-GG md5-G)
189 (md5-make-step md5-HH md5-H) 189 (md5-make-step md5-HH md5-H)
190 (md5-make-step md5-II md5-I) 190 (md5-make-step md5-II md5-I)
191 191
192 (defun md5-init () 192 (defun md5-init ()
193 "Initialize the state of the message-digest routines." 193 "Initialise the state of the message-digest routines."
194 (aset md5-bits 0 0) 194 (aset md5-bits 0 0)
195 (aset md5-bits 1 0) 195 (aset md5-bits 1 0)
196 (aset md5-bits 2 0) 196 (aset md5-bits 2 0)
197 (aset md5-bits 3 0) 197 (aset md5-bits 3 0)
198 (aset md5-buffer 0 '(26437 . 8961)) 198 (aset md5-buffer 0 '(26437 . 8961))
358 a (md5-II a b c d (aref in 4) 6 '(63315 . 32386)) 358 a (md5-II a b c d (aref in 4) 6 '(63315 . 32386))
359 d (md5-II d a b c (aref in 11) 10 '(48442 . 62005)) 359 d (md5-II d a b c (aref in 11) 10 '(48442 . 62005))
360 c (md5-II c d a b (aref in 2) 15 '(10967 . 53947)) 360 c (md5-II c d a b (aref in 2) 15 '(10967 . 53947))
361 b (md5-II b c d a (aref in 9) 21 '(60294 . 54161))) 361 b (md5-II b c d a (aref in 9) 21 '(60294 . 54161)))
362 362
363 (aset md5-buffer 0 (md5-add (aref md5-buffer 0) a)) 363 (aset md5-buffer 0 (md5-add (aref md5-buffer 0) a))
364 (aset md5-buffer 1 (md5-add (aref md5-buffer 1) b)) 364 (aset md5-buffer 1 (md5-add (aref md5-buffer 1) b))
365 (aset md5-buffer 2 (md5-add (aref md5-buffer 2) c)) 365 (aset md5-buffer 2 (md5-add (aref md5-buffer 2) c))
366 (aset md5-buffer 3 (md5-add (aref md5-buffer 3) d)))) 366 (aset md5-buffer 3 (md5-add (aref md5-buffer 3) d))))
367 367
368 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 368 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
369 ;;; Here begins the merger with the XEmacs API and the md5.el from the URL 369 ;;; Here begins the merger with the XEmacs API and the md5.el from the URL
370 ;;; package. Courtesy wmperry@spry.com 370 ;;; package. Courtesy wmperry@spry.com
371 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 371 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
372 (eval-and-compile 372 (defun md5 (object &optional start end)
373 (unless (fboundp 'md5) 373 "Return the MD5 (a secure message digest algorithm) of an object.
374 (defun md5 (object &optional start end)
375 "Return the MD5 (a secure message digest algorithm) of an object.
376 OBJECT is either a string or a buffer. 374 OBJECT is either a string or a buffer.
377 Optional arguments START and END denote buffer positions for computing the 375 Optional arguments START and END denote buffer positions for computing the
378 hash of a portion of OBJECT." 376 hash of a portion of OBJECT."
379 (let ((buffer nil)) 377 (let ((buffer nil))
380 (unwind-protect 378 (unwind-protect
381 (save-excursion 379 (save-excursion
382 (setq buffer (generate-new-buffer " *md5-work*")) 380 (setq buffer (generate-new-buffer " *md5-work*"))
383 (set-buffer buffer) 381 (set-buffer buffer)
384 (cond 382 (cond
385 ((bufferp object) 383 ((bufferp object)
386 (insert-buffer-substring object start end)) 384 (insert-buffer-substring object start end))
387 ((stringp object) 385 ((stringp object)
388 (insert (if (or start end) 386 (insert (if (or start end)
389 (substring object start end) 387 (substring object start end)
390 object))) 388 object)))
391 (t nil)) 389 (t nil))
392 (prog1 390 (prog1
393 (if (<= (point-max) md5-maximum-internal-length) 391 (if (<= (point-max) md5-maximum-internal-length)
394 (mapconcat 392 (mapconcat
395 (function (lambda (node) (format "%02x" node))) 393 (function (lambda (node) (format "%02x" node)))
396 (md5-encode (buffer-string)) 394 (md5-encode (buffer-string))
397 "") 395 "")
398 (call-process-region (point-min) (point-max) 396 (call-process-region (point-min) (point-max)
399 (or shell-file-name "/bin/sh") 397 (or shell-file-name "/bin/sh")
400 t buffer nil 398 t buffer nil
401 "-c" md5-program) 399 "-c" md5-program)
402 ;; MD5 digest is 32 chars long 400 ;; MD5 digest is 32 chars long
403 ;; mddriver adds a newline to make neaten output for tty 401 ;; mddriver adds a newline to make neaten output for tty
404 ;; viewing, make sure we leave it behind. 402 ;; viewing, make sure we leave it behind.
405 (buffer-substring (point-min) (+ (point-min) 32))) 403 (buffer-substring (point-min) (+ (point-min) 32)))
406 (kill-buffer buffer))) 404 (kill-buffer buffer)))
407 (and buffer (kill-buffer buffer) nil)))))) 405 (and buffer (kill-buffer buffer) nil))))
408 406
409 (provide 'md5) 407 (provide 'md5)
410 408
411 ;;; md5.el ends here ---------------------------------------------------------- 409 ;;; md5.el ends here ----------------------------------------------------------