merge hmac package
authorokada <okada>
Thu, 18 Nov 1999 19:53:56 +0000 (19:53 +0000)
committerokada <okada>
Thu, 18 Nov 1999 19:53:56 +0000 (19:53 +0000)
12 files changed:
ChangeLog
FLIM-ELS
hmac-def.el [new file with mode: 0644]
hmac-md5.el [new file with mode: 0644]
hmac-sha1.el [new file with mode: 0644]
hmac-util.el [new file with mode: 0644]
md5-dl.el [new file with mode: 0644]
md5-el.el [new file with mode: 0644]
md5.el [new file with mode: 0644]
sha1-dl.el [new file with mode: 0644]
sha1-el.el [new file with mode: 0644]
sha1.el [new file with mode: 0644]

index fbf4381..eb6e74c 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,18 @@
 1999-10-19  Kenichi OKADA <okada@opaopa.org>
 
+       * md5.el: New file. (import from hmac package)
+       * md5-el.el: New file. (import from hmac package)
+       * md5-dl.el: New file. (import from hmac package)
+       * sha1.el: New file. (import from hmac package)
+       * sha1-el.el: New file. (import from hmac package)
+       * sha1-dl.el: New file. (import from hmac package)
+       * hmac-def.el: New file. (import from hmac package)
+       * hmac-util.el: New file. (import from hmac package)
+       * hmac-md5.el: New file. (import from hmac package)
+       * hmac-sha1.el: New file. (import from hmac package)
+
+1999-10-19  Kenichi OKADA <okada@opaopa.org>
+
        * SLIM-VERSION: New file.
        * sasl.el: Add keyword.
 
index 23bc7b9..dbe4721 100644 (file)
--- a/FLIM-ELS
+++ b/FLIM-ELS
                     eword-decode eword-encode
                     mime mime-parse mmbuffer mmcooked mmdbuffer
                     mailcap
-                    smtp smtpmail sasl))
+                    smtp smtpmail sasl
+                    md5 md5-el md5-dl
+                    sha1 sha1-el sha1-dl
+                    hmac-def hmac-util hmac-md5 hmac-sha1))
 
 (unless (and (fboundp 'base64-encode-string)
             (subrp (symbol-function 'base64-encode-string)))
diff --git a/hmac-def.el b/hmac-def.el
new file mode 100644 (file)
index 0000000..cc59fef
--- /dev/null
@@ -0,0 +1,92 @@
+;;; hmac-def.el --- Functions/macros for defining HMAC functions.
+
+;; Copyright (C) 1999 Shuhei KOBAYASHI
+
+;; Author: Shuhei KOBAYASHI <shuhei@aqua.ocn.ne.jp>
+;; Keywords: HMAC, RFC 2104
+
+;; This program is free software; you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation; either version 2, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program; see the file COPYING.  If not, write to
+;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; See RFC 2104, "HMAC: Keyed-Hashing for Message Authentication"
+;; for definition of HMAC.
+
+;;; Code:
+
+(require 'hmac-util)
+
+(defmacro hmac-unhex-string-macro (string length)
+  (let* ((len (eval length))
+         (dst (make-string (/ len 2) 0)))
+    `(let ((str ,string)
+           (dst ,dst)
+           (idx 0)(pos 0))
+       (while (< pos ,len)
+        (aset dst idx (+ (* (hmac-hex-to-int (aref str pos)) 16)
+                         (hmac-hex-to-int (aref str (1+ pos)))))
+        (setq idx (1+ idx)
+              pos (+ 2 pos)))
+       dst)))
+
+;; Note that H, B, and L will be evaluated multiple times.  They are
+;; usually constants, so I don't want to bother to bind them locally.
+(defmacro define-hmac-function (name H B L &optional bit)
+  "Define a function NAME which computes HMAC with hash function H.
+
+HMAC function is H\(KEY XOR opad, H\(KEY XOR ipad, TEXT\)\):
+
+H is a cryptographic hash function, such as SHA1 and MD5, which takes
+a string and return a digest of it \(in hexadecimal form\).
+B is a byte-length of a block size of H. \(B=64 for both SHA1 and MD5.\)
+L is a byte-length of hash outputs. \(L=16 for MD5, L=20 for SHA1.\)
+If BIT is non-nil, truncate output to specified bits."
+  `(defun ,name (text key)
+     ,(concat "Compute " (upcase (symbol-name name)) " over TEXT with KEY.")
+     (let ((key-xor-ipad (make-string ,B ?\x36))
+           (key-xor-opad (make-string ,B ?\x5C))
+           (len (length key))
+           (pos 0))
+       (when (> len ,B)
+         (setq key (hmac-unhex-string-macro (,H key) ,(* L 2)))
+        (setq len ,L))
+       (while (< pos len)
+         (aset key-xor-ipad pos (logxor (aref key pos) ?\x36))
+         (aset key-xor-opad pos (logxor (aref key pos) ?\x5C))
+         (setq pos (1+ pos)))
+       ;; If outer `hmac-unhex-string-macro' is removed, return value
+       ;; will be in hexadecimal form.  It is useful for test.
+       ,(if (and bit (< (/ bit 8) L))
+           `(substring
+             (hmac-unhex-string-macro
+              (,H
+               (concat key-xor-opad
+                       (hmac-unhex-string-macro
+                        (,H (concat key-xor-ipad text))
+                        ,(* L 2))))
+              ,(* L 2))
+             0 ,(/ bit 8))
+         `(hmac-unhex-string-macro
+           (,H
+            (concat key-xor-opad
+                    (hmac-unhex-string-macro
+                     (,H (concat key-xor-ipad text))
+                     ,(* L 2))))
+           ,(* L 2))))))
+
+(provide 'hmac-def)
+
+;;; hmac-def.el ends here.
diff --git a/hmac-md5.el b/hmac-md5.el
new file mode 100644 (file)
index 0000000..e1b37aa
--- /dev/null
@@ -0,0 +1,72 @@
+;;; hmac-md5.el --- Compute HMAC-MD5.
+
+;; Copyright (C) 1999 Shuhei KOBAYASHI
+
+;; Author: Shuhei KOBAYASHI <shuhei@aqua.ocn.ne.jp>
+;; Keywords: HMAC, RFC 2104, HMAC-MD5, MD5, KEYED-MD5, CRAM-MD5
+
+;; This program is free software; you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation; either version 2, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program; see the file COPYING.  If not, write to
+;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; Test cases from RFC 2202, "Test Cases for HMAC-MD5 and HMAC-SHA-1".
+;;
+;; (hmac-hex-string (hmac-md5 "Hi There" (make-string 16 ?\x0b)))
+;;  => "9294727a3638bb1c13f48ef8158bfc9d"
+;;
+;; (hmac-hex-string (hmac-md5 "what do ya want for nothing?" "Jefe"))
+;;  => "750c783e6ab0b503eaa86e310a5db738"
+;;
+;; (hmac-hex-string (hmac-md5 (make-string 50 ?\xdd) (make-string 16 ?\xaa)))
+;;  => "56be34521d144c88dbb8c733f0e8b3f6"
+;;
+;; (hmac-hex-string
+;;  (hmac-md5
+;;   (make-string 50 ?\xcd)
+;;   (hmac-unhex-string "0102030405060708090a0b0c0d0e0f10111213141516171819")))
+;;  => "697eaf0aca3a3aea3a75164746ffaa79"
+;;
+;; (hmac-hex-string
+;;  (hmac-md5 "Test With Truncation" (make-string 16 ?\x0c)))
+;;  => "56461ef2342edc00f9bab995690efd4c"
+;; (hmac-hex-string
+;;  (hmac-md5-96 "Test With Truncation" (make-string 16 ?\x0c)))
+;;  => "56461ef2342edc00f9bab995"
+;;
+;; (hmac-hex-string
+;;  (hmac-md5
+;;   "Test Using Larger Than Block-Size Key - Hash Key First"
+;;   (make-string 80 ?\xaa)))
+;;  => "6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd"
+;;
+;; (hmac-hex-string
+;;  (hmac-md5
+;;   "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"
+;;   (make-string 80 ?\xaa)))
+;;  => "6f630fad67cda0ee1fb1f562db3aa53e"
+
+;;; Code:
+
+(eval-when-compile (require 'hmac-def))
+(require 'md5)                         ; expects (md5 STRING)
+
+(define-hmac-function hmac-md5 md5 64 16) ; => (hmac-md5 TEXT KEY)
+;; (define-hmac-function hmac-md5-96 md5 64 16 96)
+;;  => (hmac-md5-96 TEXT KEY)
+
+(provide 'hmac-md5)
+
+;;; hmac-md5.el ends here.
diff --git a/hmac-sha1.el b/hmac-sha1.el
new file mode 100644 (file)
index 0000000..58696a3
--- /dev/null
@@ -0,0 +1,72 @@
+;;; hmac-sha1.el --- Compute HMAC-SHA1.
+
+;; Copyright (C) 1999 Shuhei KOBAYASHI
+
+;; Author: Shuhei KOBAYASHI <shuhei@aqua.ocn.ne.jp>
+;; Keywords: HMAC, RFC 2104, HMAC-SHA1, SHA1, Cancel-Lock
+
+;; This program is free software; you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation; either version 2, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program; see the file COPYING.  If not, write to
+;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; Test cases from RFC 2202, "Test Cases for HMAC-MD5 and HMAC-SHA-1".
+;;
+;; (hmac-hex-string (hmac-sha1 "Hi There" (make-string 20 ?\x0b)))
+;;  => "b617318655057264e28bc0b6fb378c8ef146be00"
+;;
+;; (hmac-hex-string (hmac-sha1 "what do ya want for nothing?" "Jefe"))
+;;  => "effcdf6ae5eb2fa2d27416d5f184df9c259a7c79"
+;;
+;; (hmac-hex-string (hmac-sha1 (make-string 50 ?\xdd) (make-string 20 ?\xaa)))
+;;  => "125d7342b9ac11cd91a39af48aa17b4f63f175d3"
+;;
+;; (hmac-hex-string
+;;  (hmac-sha1
+;;   (make-string 50 ?\xcd)
+;;   (hmac-unhex-string "0102030405060708090a0b0c0d0e0f10111213141516171819")))
+;;  => "4c9007f4026250c6bc8414f9bf50c86c2d7235da"
+;;
+;; (hmac-hex-string
+;;  (hmac-sha1 "Test With Truncation" (make-string 20 ?\x0c)))
+;;  => "4c1a03424b55e07fe7f27be1d58bb9324a9a5a04"
+;; (hmac-hex-string
+;;  (hmac-sha1-96 "Test With Truncation" (make-string 20 ?\x0c)))
+;;  => "4c1a03424b55e07fe7f27be1"
+;;
+;; (hmac-hex-string
+;;  (hmac-sha1
+;;   "Test Using Larger Than Block-Size Key - Hash Key First"
+;;   (make-string 80 ?\xaa)))
+;;  => "aa4ae5e15272d00e95705637ce8a3b55ed402112"
+;;
+;; (hmac-hex-string
+;;  (hmac-sha1
+;;   "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"
+;;   (make-string 80 ?\xaa)))
+;;  => "e8e99d0f45237d786d6bbaa7965c7808bbff1a91"
+
+;;; Code:
+
+(eval-when-compile (require 'hmac-def))
+(require 'sha1)                                ; expects (sha1 STRING)
+
+(define-hmac-function hmac-sha1 sha1 64 20) ; => (hmac-sha1 TEXT KEY)
+;; (define-hmac-function hmac-sha1-96 sha1 64 20 96)
+;;  => (hmac-sha1-96 TEXT KEY)
+
+(provide 'hmac-sha1)
+
+;;; hmac-sha1.el ends here.
diff --git a/hmac-util.el b/hmac-util.el
new file mode 100644 (file)
index 0000000..61b36f3
--- /dev/null
@@ -0,0 +1,60 @@
+;;; hmac-util.el --- Utilities for HMAC functions.
+
+;; Copyright (C) 1999 Shuhei KOBAYASHI
+
+;; Author: Shuhei KOBAYASHI <shuhei@aqua.ocn.ne.jp>
+;; Keywords: HMAC, RFC 2104
+
+;; This program is free software; you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation; either version 2, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program; see the file COPYING.  If not, write to
+;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;;; Code:
+
+(defsubst hmac-hex-to-int (chr)
+  (cond ((<= ?a chr) (+ (- chr ?a) 10))
+       ((<= ?A chr) (+ (- chr ?A) 10))
+       ((<= ?0 chr) (- chr ?0))))
+
+(defsubst hmac-int-to-hex (num)
+  (aref "0123456789abcdef" num))
+
+(defun hmac-unhex-string (str)
+  (let* ((len (length str))
+        (dst (make-string (/ len 2) 0))
+        (idx 0)(pos 0))
+    (while (< pos len)
+      (aset dst idx (logior (lsh (hmac-hex-to-int (aref str pos)) 4)
+                           (hmac-hex-to-int (aref str (1+ pos)))))
+      (setq idx (1+ idx)
+            pos (+ 2 pos)))
+    dst))
+
+(defun hmac-hex-string (str)
+  (let* ((len (length str))
+        (dst (make-string (* len 2) 0))
+        (idx 0)(pos 0))
+    (while (< pos len)
+      (aset dst idx (hmac-int-to-hex (logand (lsh (aref str pos) -4) 15)))
+      (setq idx (1+ idx))
+      (aset dst idx (hmac-int-to-hex (logand (aref str pos) 15)))
+      (setq idx (1+ idx)
+            pos (1+ pos)))
+    dst))
+
+(provide 'hmac-util)
+
+;;; hmac-util.el ends here.
diff --git a/md5-dl.el b/md5-dl.el
new file mode 100644 (file)
index 0000000..659856c
--- /dev/null
+++ b/md5-dl.el
@@ -0,0 +1,64 @@
+;;; md5-dl.el --- MD5 Message Digest Algorithm using DL module.
+
+;; Copyright (C) 1999 Shuhei KOBAYASHI
+
+;; Author: Shuhei KOBAYASHI <shuhei@aqua.ocn.ne.jp>
+;; Keywords: MD5, RFC 1321
+
+;; This program is free software; you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation; either version 2, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program; see the file COPYING.  If not, write to
+;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;;; Code:
+
+(defvar md5-dl-module
+  (if (and (fboundp 'md5-string)
+          (subrp (symbol-function 'md5-string)))
+      nil
+    (if (fboundp 'dynamic-link)
+       (let ((path (expand-file-name "md5.so" exec-directory)))
+         (and (file-exists-p path)
+              path)))))
+
+(defvar md5-dl-handle
+  (and (stringp md5-dl-module)
+       (file-exists-p md5-dl-module)
+       (dynamic-link md5-dl-module)))
+
+;;; md5-dl-module provides `md5-string'.
+(dynamic-call "emacs_md5_init" md5-dl-handle)
+
+(defun md5-region (beg end)
+  (interactive "r")
+  (md5-string (buffer-substring-no-properties beg end)))
+
+;;; Note that XEmacs built-in version takes two more args: CODING and NOERROR.
+;;;###autoload
+(defun md5 (object &optional beg end)
+  "Return the MD5 (a secure message digest algorithm) of an object.
+OBJECT is either a string or a buffer.
+Optional arguments BEG and END denote buffer positions for computing the
+hash of a portion of OBJECT."
+  (if (stringp object)
+      (md5-string object)
+    (save-excursion
+      (set-buffer object)
+      (md5-region (or beg (point-min)) (or end (point-max))))))
+
+(provide 'md5-dl)
+(provide 'md5)
+
+;;; md5-dl.el ends here.
diff --git a/md5-el.el b/md5-el.el
new file mode 100644 (file)
index 0000000..b4a64e9
--- /dev/null
+++ b/md5-el.el
@@ -0,0 +1,406 @@
+;;; md5.el -- MD5 Message Digest Algorithm
+;;; Gareth Rees <gdr11@cl.cam.ac.uk>
+
+;; LCD Archive Entry:
+;; md5|Gareth Rees|gdr11@cl.cam.ac.uk|
+;; MD5 cryptographic message digest algorithm|
+;; 13-Nov-95|1.0|~/misc/md5.el.Z|
+
+;;; Details: ------------------------------------------------------------------
+
+;; This is a direct translation into Emacs LISP of the reference C
+;; implementation of the MD5 Message-Digest Algorithm written by RSA
+;; Data Security, Inc.
+;; 
+;; The algorithm takes a message (that is, a string of bytes) and
+;; computes a 16-byte checksum or "digest" for the message.  This digest
+;; is supposed to be cryptographically strong in the sense that if you
+;; are given a 16-byte digest D, then there is no easier way to
+;; construct a message whose digest is D than to exhaustively search the
+;; space of messages.  However, the robustness of the algorithm has not
+;; been proven, and a similar algorithm (MD4) was shown to be unsound,
+;; so treat with caution!
+;; 
+;; The C algorithm uses 32-bit integers; because GNU Emacs
+;; implementations provide 28-bit integers (with 24-bit integers on
+;; versions prior to 19.29), the code represents a 32-bit integer as the
+;; cons of two 16-bit integers.  The most significant word is stored in
+;; the car and the least significant in the cdr.  The algorithm requires
+;; at least 17 bits of integer representation in order to represent the
+;; carry from a 16-bit addition.
+
+;;; Usage: --------------------------------------------------------------------
+
+;; To compute the MD5 Message Digest for a message M (represented as a
+;; string or as a vector of bytes), call
+;; 
+;;   (md5-encode M)
+;; 
+;; which returns the message digest as a vector of 16 bytes.  If you
+;; need to supply the message in pieces M1, M2, ... Mn, then call
+;; 
+;;   (md5-init)
+;;   (md5-update M1)
+;;   (md5-update M2)
+;;   ...
+;;   (md5-update Mn)
+;;   (md5-final)
+
+;;; Copyright and licence: ----------------------------------------------------
+
+;; Copyright (C) 1995, 1996, 1997 by Gareth Rees
+;; Derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm
+;; 
+;; md5.el is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published by the
+;; Free Software Foundation; either version 2, or (at your option) any
+;; later version.
+;; 
+;; md5.el is distributed in the hope that it will be useful, but WITHOUT
+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+;; FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+;; for more details.
+;; 
+;; The original copyright notice is given below, as required by the
+;; licence for the original code.  This code is distributed under *both*
+;; RSA's original licence and the GNU General Public Licence.  (There
+;; should be no problems, as the former is more liberal than the
+;; latter).
+
+;;; Original copyright notice: ------------------------------------------------
+
+;; Copyright (C) 1990, RSA Data Security, Inc. All rights reserved.
+;;
+;; License to copy and use this software is granted provided that it is
+;; identified as the "RSA Data Security, Inc. MD5 Message- Digest
+;; Algorithm" in all material mentioning or referencing this software or
+;; this function.
+;;
+;; License is also granted to make and use derivative works provided
+;; that such works are identified as "derived from the RSA Data
+;; Security, Inc. MD5 Message-Digest Algorithm" in all material
+;; mentioning or referencing the derived work.
+;;
+;; RSA Data Security, Inc. makes no representations concerning either
+;; the merchantability of this software or the suitability of this
+;; software for any particular purpose.  It is provided "as is" without
+;; express or implied warranty of any kind.
+;;
+;; These notices must be retained in any copies of any part of this
+;; documentation and/or software.
+
+;;; Code: ---------------------------------------------------------------------
+
+(defvar md5-program "md5"
+  "*Program that reads a message on its standard input and writes an
+MD5 digest on its output.")
+
+(defvar md5-maximum-internal-length 4096
+  "*The maximum size of a piece of data that should use the MD5 routines
+written in lisp.  If a message exceeds this, it will be run through an
+external filter for processing.  Also see the `md5-program' variable.
+This variable has no effect if you call the md5-init|update|final
+functions - only used by the `md5' function's simpler interface.")
+
+(defvar md5-bits (make-vector 4 0)
+  "Number of bits handled, modulo 2^64.
+Represented as four 16-bit numbers, least significant first.")
+(defvar md5-buffer (make-vector 4 '(0 . 0))
+  "Scratch buffer (four 32-bit integers).")
+(defvar md5-input (make-vector 64 0)
+  "Input buffer (64 bytes).")
+
+(defun md5-unhex (x)
+  (if (> x ?9)
+      (if (>= x ?a)
+         (+ 10 (- x ?a))
+       (+ 10 (- x ?A)))
+    (- x ?0)))
+
+(defun md5-encode (message)
+  "Encodes MESSAGE using the MD5 message digest algorithm.
+MESSAGE must be a string or an array of bytes.
+Returns a vector of 16 bytes containing the message digest."
+  (if (<= (length message) md5-maximum-internal-length)
+      (progn
+       (md5-init)
+       (md5-update message)
+       (md5-final))
+    (save-excursion
+      (set-buffer (get-buffer-create " *md5-work*"))
+      (erase-buffer)
+      (insert message)
+      (call-process-region (point-min) (point-max)
+                          md5-program
+                          t (current-buffer))
+      ;; MD5 digest is 32 chars long
+      ;; mddriver adds a newline to make neaten output for tty
+      ;; viewing, make sure we leave it behind.
+      (let ((data (buffer-substring (point-min) (+ (point-min) 32)))
+           (vec (make-vector 16 0))
+           (ctr 0))
+       (while (< ctr 16)
+         (aset vec ctr (+ (* 16 (md5-unhex (aref data (* ctr 2))))
+                          (md5-unhex (aref data (1+ (* ctr 2))))))
+         (setq ctr (1+ ctr)))))))
+
+(defsubst md5-add (x y)
+  "Return 32-bit sum of 32-bit integers X and Y."
+  (let ((m (+ (car x) (car y)))
+        (l (+ (cdr x) (cdr y))))
+    (cons (logand 65535 (+ m (lsh l -16))) (logand l 65535))))
+
+;; FF, GG, HH and II are basic MD5 functions, providing transformations
+;; for rounds 1, 2, 3 and 4 respectively.  Each function follows this
+;; pattern of computation (where ROTATE(x,y) means rotate 32-bit value x
+;; by y bits to the left):
+;; 
+;;   FF(a,b,c,d,x,s,ac) = ROTATE(a + F(b,c,d) + x + ac,s) + b
+;; 
+;; so we use the macro `md5-make-step' to construct each one.  The
+;; helper functions F, G, H and I operate on 16-bit numbers; the full
+;; operation splits its inputs, operates on the halves separately and
+;; then puts the results together.
+
+(defsubst md5-F (x y z) (logior (logand x y) (logand (lognot x) z)))
+(defsubst md5-G (x y z) (logior (logand x z) (logand y (lognot z))))
+(defsubst md5-H (x y z) (logxor x y z))
+(defsubst md5-I (x y z) (logxor y (logior x (logand 65535 (lognot z)))))
+
+(defmacro md5-make-step (name func)
+  (`
+   (defun (, name) (a b c d x s ac)
+     (let*
+         ((m1 (+ (car a) ((, func) (car b) (car c) (car d)) (car x) (car ac)))
+          (l1 (+ (cdr a) ((, func) (cdr b) (cdr c) (cdr d)) (cdr x) (cdr ac)))
+          (m2 (logand 65535 (+ m1 (lsh l1 -16))))
+          (l2 (logand 65535 l1))
+          (m3 (logand 65535 (if (> s 15)
+                                (+ (lsh m2 (- s 32)) (lsh l2 (- s 16)))
+                              (+ (lsh m2 s) (lsh l2 (- s 16))))))
+          (l3 (logand 65535 (if (> s 15)
+                                (+ (lsh l2 (- s 32)) (lsh m2 (- s 16)))
+                              (+ (lsh l2 s) (lsh m2 (- s 16)))))))
+       (md5-add (cons m3 l3) b)))))
+
+(md5-make-step md5-FF md5-F)
+(md5-make-step md5-GG md5-G)
+(md5-make-step md5-HH md5-H)
+(md5-make-step md5-II md5-I)
+
+(defun md5-init ()
+  "Initialise the state of the message-digest routines."
+  (aset md5-bits 0 0)
+  (aset md5-bits 1 0)
+  (aset md5-bits 2 0)
+  (aset md5-bits 3 0)
+  (aset md5-buffer 0 '(26437 .  8961))
+  (aset md5-buffer 1 '(61389 . 43913))
+  (aset md5-buffer 2 '(39098 . 56574))
+  (aset md5-buffer 3 '( 4146 . 21622)))
+
+(defun md5-update (string)
+  "Update the current MD5 state with STRING (an array of bytes)."
+  (let ((len (length string))
+        (i 0)
+        (j 0))
+    (while (< i len)
+      ;; Compute number of bytes modulo 64
+      (setq j (% (/ (aref md5-bits 0) 8) 64))
+
+      ;; Store this byte (truncating to 8 bits to be sure)
+      (aset md5-input j (logand 255 (aref string i)))
+
+      ;; Update number of bits by 8 (modulo 2^64)
+      (let ((c 8) (k 0))
+        (while (and (> c 0) (< k 4))
+          (let ((b (aref md5-bits k)))
+            (aset md5-bits k (logand 65535 (+ b c)))
+            (setq c (if (> b (- 65535 c)) 1 0)
+                  k (1+ k)))))
+
+      ;; Increment number of bytes processed
+      (setq i (1+ i))
+
+      ;; When 64 bytes accumulated, pack them into sixteen 32-bit
+      ;; integers in the array `in' and then tranform them.
+      (if (= j 63)
+          (let ((in (make-vector 16 (cons 0 0)))
+                (k 0)
+                (kk 0))
+            (while (< k 16)
+              (aset in k (md5-pack md5-input kk))
+              (setq k (+ k 1) kk (+ kk 4)))
+            (md5-transform in))))))
+
+(defun md5-pack (array i)
+  "Pack the four bytes at ARRAY reference I to I+3 into a 32-bit integer."
+  (cons (+ (lsh (aref array (+ i 3)) 8) (aref array (+ i 2)))
+        (+ (lsh (aref array (+ i 1)) 8) (aref array (+ i 0)))))
+
+(defun md5-byte (array n b)
+  "Unpack byte B (0 to 3) from Nth member of ARRAY of 32-bit integers."
+  (let ((e (aref array n)))
+    (cond ((eq b 0) (logand 255 (cdr e)))
+          ((eq b 1) (lsh (cdr e) -8))
+          ((eq b 2) (logand 255 (car e)))
+          ((eq b 3) (lsh (car e) -8)))))
+
+(defun md5-final ()
+  (let ((in (make-vector 16 (cons 0 0)))
+        (j 0)
+        (digest (make-vector 16 0))
+        (padding))
+
+    ;; Save the number of bits in the message
+    (aset in 14 (cons (aref md5-bits 1) (aref md5-bits 0)))
+    (aset in 15 (cons (aref md5-bits 3) (aref md5-bits 2)))
+
+    ;; Compute number of bytes modulo 64
+    (setq j (% (/ (aref md5-bits 0) 8) 64))
+
+    ;; Pad out computation to 56 bytes modulo 64
+    (setq padding (make-vector (if (< j 56) (- 56 j) (- 120 j)) 0))
+    (aset padding 0 128)
+    (md5-update padding)
+
+    ;; Append length in bits and transform
+    (let ((k 0) (kk 0))
+      (while (< k 14)
+        (aset in k (md5-pack md5-input kk))
+        (setq k (+ k 1) kk (+ kk 4))))
+    (md5-transform in)
+
+    ;; Store the results in the digest
+    (let ((k 0) (kk 0))
+      (while (< k 4)
+        (aset digest (+ kk 0) (md5-byte md5-buffer k 0))
+        (aset digest (+ kk 1) (md5-byte md5-buffer k 1))
+        (aset digest (+ kk 2) (md5-byte md5-buffer k 2))
+        (aset digest (+ kk 3) (md5-byte md5-buffer k 3))
+        (setq k (+ k 1) kk (+ kk 4))))
+
+    ;; Return digest
+    digest))
+
+;; It says in the RSA source, "Note that if the Mysterious Constants are
+;; arranged backwards in little-endian order and decrypted with the DES
+;; they produce OCCULT MESSAGES!"  Security through obscurity?
+
+(defun md5-transform (in)
+  "Basic MD5 step. Transform md5-buffer based on array IN."
+  (let ((a (aref md5-buffer 0))
+        (b (aref md5-buffer 1))
+        (c (aref md5-buffer 2))
+        (d (aref md5-buffer 3)))
+    (setq
+     a (md5-FF a b c d (aref in  0)  7 '(55146 . 42104))
+     d (md5-FF d a b c (aref in  1) 12 '(59591 . 46934))
+     c (md5-FF c d a b (aref in  2) 17 '( 9248 . 28891))
+     b (md5-FF b c d a (aref in  3) 22 '(49597 . 52974))
+     a (md5-FF a b c d (aref in  4)  7 '(62844 .  4015))
+     d (md5-FF d a b c (aref in  5) 12 '(18311 . 50730))
+     c (md5-FF c d a b (aref in  6) 17 '(43056 . 17939))
+     b (md5-FF b c d a (aref in  7) 22 '(64838 . 38145))
+     a (md5-FF a b c d (aref in  8)  7 '(27008 . 39128))
+     d (md5-FF d a b c (aref in  9) 12 '(35652 . 63407))
+     c (md5-FF c d a b (aref in 10) 17 '(65535 . 23473))
+     b (md5-FF b c d a (aref in 11) 22 '(35164 . 55230))
+     a (md5-FF a b c d (aref in 12)  7 '(27536 .  4386))
+     d (md5-FF d a b c (aref in 13) 12 '(64920 . 29075))
+     c (md5-FF c d a b (aref in 14) 17 '(42617 . 17294))
+     b (md5-FF b c d a (aref in 15) 22 '(18868 .  2081))
+     a (md5-GG a b c d (aref in  1)  5 '(63006 .  9570))
+     d (md5-GG d a b c (aref in  6)  9 '(49216 . 45888))
+     c (md5-GG c d a b (aref in 11) 14 '( 9822 . 23121))
+     b (md5-GG b c d a (aref in  0) 20 '(59830 . 51114))
+     a (md5-GG a b c d (aref in  5)  5 '(54831 .  4189))
+     d (md5-GG d a b c (aref in 10)  9 '(  580 .  5203))
+     c (md5-GG c d a b (aref in 15) 14 '(55457 . 59009))
+     b (md5-GG b c d a (aref in  4) 20 '(59347 . 64456))
+     a (md5-GG a b c d (aref in  9)  5 '( 8673 . 52710))
+     d (md5-GG d a b c (aref in 14)  9 '(49975 .  2006))
+     c (md5-GG c d a b (aref in  3) 14 '(62677 .  3463))
+     b (md5-GG b c d a (aref in  8) 20 '(17754 .  5357))
+     a (md5-GG a b c d (aref in 13)  5 '(43491 . 59653))
+     d (md5-GG d a b c (aref in  2)  9 '(64751 . 41976))
+     c (md5-GG c d a b (aref in  7) 14 '(26479 .   729))
+     b (md5-GG b c d a (aref in 12) 20 '(36138 . 19594))
+     a (md5-HH a b c d (aref in  5)  4 '(65530 . 14658))
+     d (md5-HH d a b c (aref in  8) 11 '(34673 . 63105))
+     c (md5-HH c d a b (aref in 11) 16 '(28061 . 24866))
+     b (md5-HH b c d a (aref in 14) 23 '(64997 . 14348))
+     a (md5-HH a b c d (aref in  1)  4 '(42174 . 59972))
+     d (md5-HH d a b c (aref in  4) 11 '(19422 . 53161))
+     c (md5-HH c d a b (aref in  7) 16 '(63163 . 19296))
+     b (md5-HH b c d a (aref in 10) 23 '(48831 . 48240))
+     a (md5-HH a b c d (aref in 13)  4 '(10395 . 32454))
+     d (md5-HH d a b c (aref in  0) 11 '(60065 . 10234))
+     c (md5-HH c d a b (aref in  3) 16 '(54511 . 12421))
+     b (md5-HH b c d a (aref in  6) 23 '( 1160 .  7429))
+     a (md5-HH a b c d (aref in  9)  4 '(55764 . 53305))
+     d (md5-HH d a b c (aref in 12) 11 '(59099 . 39397))
+     c (md5-HH c d a b (aref in 15) 16 '( 8098 . 31992))
+     b (md5-HH b c d a (aref in  2) 23 '(50348 . 22117))
+     a (md5-II a b c d (aref in  0)  6 '(62505 .  8772))
+     d (md5-II d a b c (aref in  7) 10 '(17194 . 65431))
+     c (md5-II c d a b (aref in 14) 15 '(43924 .  9127))
+     b (md5-II b c d a (aref in  5) 21 '(64659 . 41017))
+     a (md5-II a b c d (aref in 12)  6 '(25947 . 22979))
+     d (md5-II d a b c (aref in  3) 10 '(36620 . 52370))
+     c (md5-II c d a b (aref in 10) 15 '(65519 . 62589))
+     b (md5-II b c d a (aref in  1) 21 '(34180 . 24017))
+     a (md5-II a b c d (aref in  8)  6 '(28584 . 32335))
+     d (md5-II d a b c (aref in 15) 10 '(65068 . 59104))
+     c (md5-II c d a b (aref in  6) 15 '(41729 . 17172))
+     b (md5-II b c d a (aref in 13) 21 '(19976 .  4513))
+     a (md5-II a b c d (aref in  4)  6 '(63315 . 32386))
+     d (md5-II d a b c (aref in 11) 10 '(48442 . 62005))
+     c (md5-II c d a b (aref in  2) 15 '(10967 . 53947))
+     b (md5-II b c d a (aref in  9) 21 '(60294 . 54161)))
+
+     (aset md5-buffer 0 (md5-add (aref md5-buffer 0) a))
+     (aset md5-buffer 1 (md5-add (aref md5-buffer 1) b))
+     (aset md5-buffer 2 (md5-add (aref md5-buffer 2) c))
+     (aset md5-buffer 3 (md5-add (aref md5-buffer 3) d))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Here begins the merger with the XEmacs API and the md5.el from the URL
+;;; package.  Courtesy wmperry@cs.indiana.edu
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+(defun md5 (object &optional start end)
+  "Return the MD5 (a secure message digest algorithm) of an object.
+OBJECT is either a string or a buffer.
+Optional arguments START and END denote buffer positions for computing the
+hash of a portion of OBJECT."
+ (let ((buffer nil))
+    (unwind-protect
+       (save-excursion
+         (setq buffer (generate-new-buffer " *md5-work*"))
+         (set-buffer buffer)
+         (cond
+          ((bufferp object)
+           (insert-buffer-substring object start end))
+          ((stringp object)
+           (insert (if (or start end)
+                       (substring object start end)
+                     object)))
+          (t nil))
+         (prog1
+             (if (<= (point-max) md5-maximum-internal-length)
+                 (mapconcat
+                  (function (lambda (node) (format "%02x" node)))
+                  (md5-encode (buffer-string))
+                  "")
+               (call-process-region (point-min) (point-max)
+                                    shell-file-name
+                                    t buffer nil
+                                    shell-command-switch md5-program)
+               ;; MD5 digest is 32 chars long
+               ;; mddriver adds a newline to make neaten output for tty
+               ;; viewing, make sure we leave it behind.
+               (buffer-substring (point-min) (+ (point-min) 32)))
+           (kill-buffer buffer)))
+      (and buffer (buffer-name buffer) (kill-buffer buffer) nil))))
+
+(provide 'md5)
diff --git a/md5.el b/md5.el
new file mode 100644 (file)
index 0000000..3548b99
--- /dev/null
+++ b/md5.el
@@ -0,0 +1,63 @@
+;;; md5.el --- MD5 Message Digest Algorithm.
+
+;; Copyright (C) 1999 Shuhei KOBAYASHI
+
+;; Author: Shuhei KOBAYASHI <shuhei@aqua.ocn.ne.jp>
+;; Keywords: MD5, RFC 1321
+
+;; This program is free software; you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation; either version 2, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program; see the file COPYING.  If not, write to
+;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; Examples from RFC 1321.
+;;
+;; (md5 "")
+;; => d41d8cd98f00b204e9800998ecf8427e
+;;
+;; (md5 "a")
+;; => 0cc175b9c0f1b6a831c399e269772661
+;;
+;; (md5 "abc")
+;; => 900150983cd24fb0d6963f7d28e17f72
+;;
+;; (md5 "message digest")
+;; => f96b697d7cb7938d525a2f31aaf161d0
+;;
+;; (md5 "abcdefghijklmnopqrstuvwxyz")
+;; => c3fcd3d76192e4007dfb496cca67e13b
+;;
+;; (md5 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")
+;; => d174ab98d277d9f5a5611c2c9f419d9f
+;;
+;; (md5 "12345678901234567890123456789012345678901234567890123456789012345678901234567890")
+;; => 57edf4a22be3c955ac49da2e2107b67a
+
+;;; Code:
+
+(cond
+ ((and (fboundp 'md5)
+       (subrp (symbol-function 'md5)))
+  ;; recent XEmacs has `md5' as a built-in function.
+  ;; (and 'md5 is already provided.)
+  )
+ ((and (fboundp 'dynamic-link)
+       (file-exists-p (expand-file-name "md5.so" exec-directory)))
+  ;; Emacs with DL patch.
+  (require 'md5 "md5-dl"))
+ (t
+  (require 'md5 "md5-el")))
+
+;;; md5.el ends here.
diff --git a/sha1-dl.el b/sha1-dl.el
new file mode 100644 (file)
index 0000000..8708c01
--- /dev/null
@@ -0,0 +1,63 @@
+;;; sha1-dl.el --- SHA1 Secure Hash Algorithm using DL module.
+
+;; Copyright (C) 1999 Shuhei KOBAYASHI
+
+;; Author: Shuhei KOBAYASHI <shuhei@aqua.ocn.ne.jp>
+;; Keywords: SHA1, FIPS 180-1
+
+;; This program is free software; you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation; either version 2, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program; see the file COPYING.  If not, write to
+;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;;; Code:
+
+(defvar sha1-dl-module
+  (if (and (fboundp 'sha1-string)
+          (subrp (symbol-function 'sha1-string)))
+      nil
+    (if (fboundp 'dynamic-link)
+       (let ((path (expand-file-name "sha1.so" exec-directory)))
+         (and (file-exists-p path)
+              path)))))
+
+(defvar sha1-dl-handle
+  (and (stringp sha1-dl-module)
+       (file-exists-p sha1-dl-module)
+       (dynamic-link sha1-dl-module)))
+
+;;; sha1-dl-module provides `sha1-string'.
+(dynamic-call "emacs_sha1_init" sha1-dl-handle)
+
+(defun sha1-region (beg end)
+  (interactive "r")
+  (sha1-string (buffer-substring-no-properties beg end)))
+
+;;;###autoload
+(defun sha1 (object &optional beg end)
+  "Return the SHA1 (Secure Hash Algorithm) of an object.
+OBJECT is either a string or a buffer.
+Optional arguments BEG and END denote buffer positions for computing the
+hash of a portion of OBJECT."
+  (if (stringp object)
+      (sha1-string object)
+    (save-excursion
+      (set-buffer object)
+      (sha1-region (or beg (point-min)) (or end (point-max))))))
+
+(provide 'sha1-dl)
+(provide 'sha1)
+
+;;; sha1-dl.el ends here.
diff --git a/sha1-el.el b/sha1-el.el
new file mode 100644 (file)
index 0000000..f4706b8
--- /dev/null
@@ -0,0 +1,397 @@
+;;; sha1.el --- SHA1 Message Digest Algorithm.
+;; Copyright (C) 1998,1999 Keiichi Suzuki.
+
+;; Author: Keiichi Suzuki <kei-suzu@mail.wbs.ne.jp>
+;; Author: Katsumi Yamaoka <yamaoka@jpl.org>
+;; Created: 1998-12-25
+;; Revised: 1999-01-13
+;; Keywords: sha1, news, cancel-lock, hmac, rfc2104
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
+;; GNU General Public License for more details.
+
+;;; A copy of the GNU General Public License can be obtained from this
+;;; program's author (send electronic mail to kyle@uunet.uu.net) or from
+;;; the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA
+;;; 02139, USA.
+
+;;; Commentary:
+
+;; This is a direct translation into Emacs LISP of the reference C
+;; implementation of the SHA1 message digest algorithm.
+
+;;; Usage:
+
+;; To compute the SHA1 message digest for a message M (represented as
+;; a string), call
+;; 
+;;   (sha1-encode M)
+;;
+;; which returns the message digest as a hexadecimal string of 20 bytes.
+;; If you need to supply the message in pieces M1, M2, ... Mn, then call
+;; 
+;;   (sha1-init)
+;;   (sha1-update M1)
+;;   (sha1-update M2)
+;;   ...
+;;   (sha1-update Mn)
+;;   (sha1-final)
+
+;;; Notes:
+
+;; The C algorithm uses 32-bit integers; because GNU Emacs
+;; implementations provide 28-bit integers (with 24-bit integers on
+;; versions prior to 19.29), the code represents a 32-bit integer as the
+;; cons of two 16-bit integers.  The most significant word is stored in
+;; the car and the least significant in the cdr.  The algorithm requires
+;; at least 19 bits of integer representation in order to represent the
+;; carry from a 16-bit addition. (see sha1-add())
+
+;;; Code:
+
+(defmacro sha1-f1 (x y z)
+  `(cons
+    (logior (logand (car ,x) (car ,y)) (logand (lognot (car ,x)) (car ,z)))
+    (logior (logand (cdr ,x) (cdr ,y)) (logand (lognot (cdr ,x)) (cdr ,z)))
+    ))
+
+(defmacro sha1-f2 (x y z)
+  `(cons
+    (logxor (car ,x) (car ,y) (car ,z))
+    (logxor (cdr ,x) (cdr ,y) (cdr ,z))
+    ))
+
+(defmacro sha1-f3 (x y z)
+  `(cons
+    (logior (logand (car ,x) (car ,y)) (logand (car ,x) (car ,z))
+           (logand (car ,y) (car ,z)))
+    (logior (logand (cdr ,x) (cdr ,y)) (logand (cdr ,x) (cdr ,z))
+           (logand (cdr ,y) (cdr ,z)))
+    ))
+
+(defmacro sha1-f4 (x y z)
+  `(cons
+    (logxor (car ,x) (car ,y) (car ,z))
+    (logxor (cdr ,x) (cdr ,y) (cdr ,z))
+    ))
+
+(defconst sha1-const1 '(23170 . 31129)
+  "SHA constants 1 \(0x5a827999\)")
+(defconst sha1-const2 '(28377 . 60321)
+  "SHA constants 2 \(0x6ed9eba1\)")
+(defconst sha1-const3 '(36635 . 48348)
+  "SHA constants 3 \(0x8f1bbcdc\)")
+(defconst sha1-const4 '(51810 . 49622)
+  "SHA constants 4 \(0xca62c1d6\)")
+
+(defvar sha1-digest (make-vector 5 nil))
+(defvar sha1-count-lo nil)
+(defvar sha1-count-hi nil)
+(defvar sha1-data nil)
+(defvar sha1-local nil)
+(defconst SHA1-BLOCKSIZE 64)
+
+(defun sha1-init ()
+  "Initialize the state of the SHA1 message digest routines."
+  (aset sha1-digest 0 (cons 26437 8961))
+  (aset sha1-digest 1 (cons 61389 43913))
+  (aset sha1-digest 2 (cons 39098 56574))
+  (aset sha1-digest 3 (cons  4146 21622))
+  (aset sha1-digest 4 (cons 50130 57840))
+  (setq sha1-count-lo (cons 0 0)
+       sha1-count-hi (cons 0 0)
+       sha1-local 0
+       sha1-data nil)
+  )
+
+(defmacro sha1-32-make (v)
+  "Return 32bits internal value from normal integer."
+  `(cons (lsh ,v -16) (logand 65535 ,v)))
+
+(defun sha1-add (to &rest vals)
+  "Set sum of all the arguments to the first one."
+  (let (val)
+    (while (setq val (car vals))
+      (setcar to (+ (car to) (car val)))
+      (setcdr to (+ (cdr to) (cdr val)))
+      (setq vals (cdr vals))
+      )
+    (setcar to (logand 65535 (+ (car to) (lsh (cdr to) -16))))
+    (setcdr to (logand 65535 (cdr to)))
+    to
+    ))
+
+(defun sha1-xor (to &rest vals)
+  "Set bitwise-exclusive-or of all the arguments to the first one."
+  (let (val)
+    (while (setq val (car vals))
+      (setcar to (logxor (car to) (car val)))
+      (setcdr to (logxor (cdr to) (cdr val)))
+      (setq vals (cdr vals)))
+    ))
+
+(defmacro sha1-rot (val c1 c2)
+  "Internal macro for sha1-rot-*."
+  `(cons
+    (logand 65535 (logior (lsh (car ,val) ,c1) (lsh (cdr ,val) ,c2)))
+    (logand 65535 (logior (lsh (cdr ,val) ,c1) (lsh (car ,val) ,c2)))
+    ))
+
+(defmacro sha1-rot-1 (val)
+  "Return VAL with its bits rotated left by 1."
+  `(sha1-rot ,val 1 -15)
+  )
+
+(defmacro sha1-rot-5 (val)
+  "Return VAL with its bits rotated left by 5."
+  `(sha1-rot ,val 5 -11)
+  )
+
+(defmacro sha1-rot-30 (val)
+  "Return VAL with its bits rotated left by 30."
+  `(sha1-rot ,val -2 14)
+  )
+
+(defun sha1-inc (to)
+  "Set TO pulus one to TO."
+  (setcdr to (1+ (cdr to)))
+  (when (> (cdr to) 65535)
+    (setcdr to (logand 65535 (cdr to)))
+    (setcar to (logand 65535 (1+ (car to))))))
+
+(defun sha1-lsh (to v count)
+  "Set TO with its bits shifted left by COUNT to TO."
+  (setcar to (logand 65535
+                    (logior (lsh (car v) count) (lsh (cdr v) (- count 16)))))
+  (setcdr to (logand 65535 (lsh (cdr v) count)))
+  to
+  )
+
+(defun sha1-rsh (to v count)
+  "Set TO with its bits shifted right by COUNT to TO."
+  (setq count (- 0 count))
+  (setcdr to (logand 65535
+                    (logior (lsh (cdr v) count) (lsh (car v) (- count 16)))))
+  (setcar to (logand 65535 (lsh (car v) count)))
+  to
+  )
+
+(defun sha1-< (v1 v2)
+  "Return t if firast argment is less then second argument."
+  (or (< (car v1) (car v2))
+      (and (eq (car v1) (car v2))
+          (< (cdr v1) (cdr v2))))
+  )
+
+(unless (fboundp 'string-as-unibyte)
+  (defsubst string-as-unibyte (string)
+    string)
+  )
+
+(defun sha1-update (bytes)
+  "Update the current SHA1 state with BYTES (an string of uni-bytes)."
+  (setq bytes (string-as-unibyte bytes))
+  (let* ((len (length bytes))
+        (len32 (sha1-32-make len))
+        (tmp32 (cons 0 0))
+        (top 0)
+        (clo (cons 0 0))
+        i done)
+    (sha1-add clo sha1-count-lo (sha1-lsh tmp32 len32 3))
+    (when (sha1-< clo sha1-count-lo)
+      (sha1-inc sha1-count-hi))
+    (setq sha1-count-lo clo)
+    (sha1-add sha1-count-hi (sha1-rsh tmp32 len32 29))
+    (when (> (length sha1-data) 0)
+      (setq i (- SHA1-BLOCKSIZE (length sha1-data)))
+      (when (> i len)
+       (setq i len))
+      (setq sha1-data (concat sha1-data (substring bytes 0 i)))
+      (setq len (- len i)
+           top i)
+      (if (eq (length sha1-data) SHA1-BLOCKSIZE)
+         (sha1-transform)
+       (setq done t)))
+    (when (not done)
+      (while (and (not done)
+                 (>= len SHA1-BLOCKSIZE))
+       (setq sha1-data (substring bytes top (+ top SHA1-BLOCKSIZE))
+             top (+ top SHA1-BLOCKSIZE)
+             len (- len SHA1-BLOCKSIZE))
+       (sha1-transform))
+      (setq sha1-data (substring bytes top (+ top len))))
+    ))
+
+(defmacro sha1-FA (n)
+  (let ((func (intern (format "sha1-f%d" n)))
+       (const (intern (format "sha1-const%d" n))))
+    `(setq T (sha1-add (cons 0 0) (sha1-rot-5 A) (,func B C D) E (aref W WIDX)
+                      ,const)
+          WIDX (1+ WIDX)
+          B (sha1-rot-30 B))))
+
+(defmacro sha1-FB (n)
+  (let ((func (intern (format "sha1-f%d" n)))
+       (const (intern (format "sha1-const%d" n))))
+    `(setq E (sha1-add (cons 0 0) (sha1-rot-5 T) (,func A B C) D (aref W WIDX)
+                      ,const)
+          WIDX (1+ WIDX)
+          A (sha1-rot-30 A))))
+
+(defmacro sha1-FC (n)
+  (let ((func (intern (format "sha1-f%d" n)))
+       (const (intern (format "sha1-const%d" n))))
+    `(setq D (sha1-add (cons 0 0) (sha1-rot-5 E) (,func T A B) C (aref W WIDX)
+                      ,const)
+          WIDX (1+ WIDX)
+          T (sha1-rot-30 T))))
+
+(defmacro sha1-FD (n)
+  (let ((func (intern (format "sha1-f%d" n)))
+       (const (intern (format "sha1-const%d" n))))
+    `(setq C (sha1-add (cons 0 0) (sha1-rot-5 D) (,func E T A) B (aref W WIDX)
+                      ,const)
+          WIDX (1+ WIDX)
+          E (sha1-rot-30 E))))
+
+(defmacro sha1-FE (n)
+  (let ((func (intern (format "sha1-f%d" n)))
+       (const (intern (format "sha1-const%d" n))))
+    `(setq B (sha1-add (cons 0 0) (sha1-rot-5 C) (,func D E T) A (aref W WIDX)
+                      ,const)
+          WIDX (1+ WIDX)
+          D (sha1-rot-30 D))))
+
+(defmacro sha1-FT (n)
+  (let ((func (intern (format "sha1-f%d" n)))
+       (const (intern (format "sha1-const%d" n))))
+    `(setq A (sha1-add (cons 0 0) (sha1-rot-5 B) (,func C D E) T (aref W WIDX)
+                      ,const)
+          WIDX (1+ WIDX)
+          C (sha1-rot-30 C))))
+
+(defun sha1-transform ()
+  "Basic SHA1 step. Transform sha1-digest based on sha1-data."
+  (let ((W (make-vector 80 nil))
+       (WIDX 0)
+       (bidx 0)
+       T A B C D E)
+    (while (< WIDX 16)
+      (aset W WIDX
+           (cons (logior (lsh (aref sha1-data bidx) 8)
+                         (aref sha1-data (setq bidx (1+ bidx))))
+                 (logior (lsh (aref sha1-data (setq bidx (1+ bidx))) 8)
+                         (aref sha1-data (setq bidx (1+ bidx))))))
+      (setq bidx (1+ bidx)
+           WIDX (1+ WIDX)))
+    (while (< WIDX 80)
+      (aset W WIDX (cons 0 0))
+      (sha1-xor (aref W WIDX)
+                  (aref W (- WIDX 3)) (aref W (- WIDX 8))
+                  (aref W (- WIDX 14)) (aref W (- WIDX 16)))
+      (aset W WIDX (sha1-rot-1 (aref W WIDX)))
+      (setq WIDX (1+ WIDX)))
+    (setq A (cons (car (aref sha1-digest 0)) (cdr (aref sha1-digest 0)))
+         B (cons (car (aref sha1-digest 1)) (cdr (aref sha1-digest 1)))
+         C (cons (car (aref sha1-digest 2)) (cdr (aref sha1-digest 2)))
+         D (cons (car (aref sha1-digest 3)) (cdr (aref sha1-digest 3)))
+         E (cons (car (aref sha1-digest 4)) (cdr (aref sha1-digest 4)))
+         WIDX 0)
+
+    (sha1-FA 1) (sha1-FB 1) (sha1-FC 1) (sha1-FD 1) (sha1-FE 1) (sha1-FT 1)
+    (sha1-FA 1) (sha1-FB 1) (sha1-FC 1) (sha1-FD 1) (sha1-FE 1) (sha1-FT 1)
+    (sha1-FA 1) (sha1-FB 1) (sha1-FC 1) (sha1-FD 1) (sha1-FE 1) (sha1-FT 1)
+    (sha1-FA 1) (sha1-FB 1) (sha1-FC 2) (sha1-FD 2) (sha1-FE 2) (sha1-FT 2)
+    (sha1-FA 2) (sha1-FB 2) (sha1-FC 2) (sha1-FD 2) (sha1-FE 2) (sha1-FT 2)
+    (sha1-FA 2) (sha1-FB 2) (sha1-FC 2) (sha1-FD 2) (sha1-FE 2) (sha1-FT 2)
+    (sha1-FA 2) (sha1-FB 2) (sha1-FC 2) (sha1-FD 2) (sha1-FE 3) (sha1-FT 3)
+    (sha1-FA 3) (sha1-FB 3) (sha1-FC 3) (sha1-FD 3) (sha1-FE 3) (sha1-FT 3)
+    (sha1-FA 3) (sha1-FB 3) (sha1-FC 3) (sha1-FD 3) (sha1-FE 3) (sha1-FT 3)
+    (sha1-FA 3) (sha1-FB 3) (sha1-FC 3) (sha1-FD 3) (sha1-FE 3) (sha1-FT 3)
+    (sha1-FA 4) (sha1-FB 4) (sha1-FC 4) (sha1-FD 4) (sha1-FE 4) (sha1-FT 4)
+    (sha1-FA 4) (sha1-FB 4) (sha1-FC 4) (sha1-FD 4) (sha1-FE 4) (sha1-FT 4)
+    (sha1-FA 4) (sha1-FB 4) (sha1-FC 4) (sha1-FD 4) (sha1-FE 4) (sha1-FT 4)
+    (sha1-FA 4) (sha1-FB 4)
+
+    (sha1-add (aref sha1-digest 0) E)
+    (sha1-add (aref sha1-digest 1) T)
+    (sha1-add (aref sha1-digest 2) A)
+    (sha1-add (aref sha1-digest 3) B)
+    (sha1-add (aref sha1-digest 4) C)
+    ))
+
+(defun sha1-final (&optional binary)
+  "Transform buffered sha1-data and return SHA1 message digest.
+If optional argument BINARY is non-nil, then return binary formed 
+string of message digest."
+  (let ((count (logand (lsh (cdr sha1-count-lo) -3) 63)))
+    (when (< (length sha1-data) SHA1-BLOCKSIZE)
+      (setq sha1-data
+           (concat sha1-data
+                   (make-string (- SHA1-BLOCKSIZE (length sha1-data)) 0))))
+    (aset sha1-data count 128)
+    (setq count (1+ count))
+    (if (> count (- SHA1-BLOCKSIZE 8))
+       (progn
+         (setq sha1-data (concat (substring sha1-data 0 count)
+                                 (make-string (- SHA1-BLOCKSIZE count) 0)))
+         (sha1-transform)
+         (setq sha1-data (concat (make-string (- SHA1-BLOCKSIZE 8) 0)
+                                 (substring sha1-data -8))))
+      (setq sha1-data (concat (substring sha1-data 0 count)
+                             (make-string (- SHA1-BLOCKSIZE 8 count) 0)
+                             (substring sha1-data -8))))
+    (aset sha1-data 56 (lsh (car sha1-count-hi) -8))
+    (aset sha1-data 57 (logand 255 (car sha1-count-hi)))
+    (aset sha1-data 58 (lsh (cdr sha1-count-hi) -8))
+    (aset sha1-data 59 (logand 255 (cdr sha1-count-hi)))
+    (aset sha1-data 60 (lsh (car sha1-count-lo) -8))
+    (aset sha1-data 61 (logand 255 (car sha1-count-lo)))
+    (aset sha1-data 62 (lsh (cdr sha1-count-lo) -8))
+    (aset sha1-data 63 (logand 255 (cdr sha1-count-lo)))
+    (sha1-transform)
+    (if binary
+       (mapconcat
+        (lambda (elem)
+          (concat (char-to-string (/ (car elem) 256))
+                  (char-to-string (% (car elem) 256))
+                  (char-to-string (/ (cdr elem) 256))
+                  (char-to-string (% (cdr elem) 256))))
+        (list (aref sha1-digest 0) (aref sha1-digest 1) (aref sha1-digest 2)
+              (aref sha1-digest 3) (aref sha1-digest 4))
+        "")
+      (format "%04x%04x%04x%04x%04x%04x%04x%04x%04x%04x"
+             (car (aref sha1-digest 0)) (cdr (aref sha1-digest 0))
+             (car (aref sha1-digest 1)) (cdr (aref sha1-digest 1))
+             (car (aref sha1-digest 2)) (cdr (aref sha1-digest 2))
+             (car (aref sha1-digest 3)) (cdr (aref sha1-digest 3))
+             (car (aref sha1-digest 4)) (cdr (aref sha1-digest 4)))
+      )))
+
+(defun sha1-encode (message &optional binary)
+  "Encodes MESSAGE using the SHA1 message digest algorithm.
+MESSAGE must be a unibyte-string.
+By default, return a string which formed hex-decimal charcters
+from message digest.
+If optional argument BINARY is non-nil, then return binary formed
+string of message digest."
+  (sha1-init)
+  (sha1-update message)
+  (sha1-final binary))
+
+(defun sha1-encode-binary (message)
+  "Encodes MESSAGE using the SHA1 message digest algorithm.
+MESSAGE must be a unibyte-string.
+Return binary formed string of message digest."
+  (sha1-encode message 'binary))
+
+(provide 'sha1)
+
+;;; sha1.el ends here
diff --git a/sha1.el b/sha1.el
new file mode 100644 (file)
index 0000000..55a8981
--- /dev/null
+++ b/sha1.el
@@ -0,0 +1,60 @@
+;;; sha1.el --- SHA1 Secure Hash Algorithm.
+
+;; Copyright (C) 1999 Shuhei KOBAYASHI
+
+;; Author: Shuhei KOBAYASHI <shuhei@aqua.ocn.ne.jp>
+;; Keywords: SHA1, FIPS 180-1
+
+;; This program is free software; you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation; either version 2, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program; see the file COPYING.  If not, write to
+;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; Examples from FIPS PUB 180-1.
+;; <URL:http://www.itl.nist.gov/div897/pubs/fip180-1.htm>
+;;
+;; (sha1 "abc")
+;; => a9993e364706816aba3e25717850c26c9cd0d89d
+;;
+;; (sha1 "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq")
+;; => 84983e441c3bd26ebaae4aa1f95129e5e54670f1
+;;
+;; (sha1 (make-string 1000000 ?a))
+;; => 34aa973cd4c4daa4f61eeb2bdbad27316534016f
+
+;;; Code:
+
+(cond
+ ((and (fboundp 'dynamic-link)
+       (file-exists-p (expand-file-name "sha1.so" exec-directory)))
+  ;; Emacs with DL patch.
+  (require 'sha1 "sha1-dl"))
+ (t
+  (require 'sha1 "sha1-el")
+  (defun sha1 (object &optional beg end)
+    "Return the SHA1 (Secure Hash Algorithm) of an object.
+OBJECT is either a string or a buffer.
+Optional arguments BEG and END denote buffer positions for computing the
+hash of a portion of OBJECT."
+    (if (stringp object)
+       (sha1-encode object)
+      (save-excursion
+       (set-buffer object)
+       (sha1-encode
+        (buffer-substring-no-properties
+          (or beg (point-min)) (or end (point-max)))))))
+  ))
+
+;;; sha1.el ends here.