;;; cvs-scramble.el --- CVS password-scramble/descramble utilities

;; Author: Noah S. Friedman <friedman@splode.com>
;; Maintainer: friedman@splode.com
;; Keywords: CVS
;; Created: 1998-07-30
;; Public domain

;; $Id: cvs-scramble.el,v 1.2 1998/09/19 00:03:20 friedman Exp $

;;; Commentary:

;; Implements the (trivial) scramble/descrambling methods for CVS pserver
;; passwords.  Method A, the only implemented method as of 1998-07-30, is a
;; trivial substitution cipher.

;; "This is really cute, especially considering that the original
;; scrambling table was set up by an one-time elisp function."
;;   -- Karl Fogel <kfogel@red-bean.com>

;;; Code:

(defvar cvs-scramble-default-method 'cvs-scramble-A)

(defconst cvs-scramble-A-table
  [ 0   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15
   16  17  18  19  20  21  22  23  24  25  26  27  28  29  30  31
  114 120  53  79  96 109  72 108  70  64  76  67 116  74  68  87
  111  52  75 119  49  34  82  81  95  65 112  86 118 110 122 105
   41  57  83  43  46 102  40  89  38 103  45  50  42 123  91  35
  125  55  54  66 124 126  59  47  92  71 115  78  88 107 106  56
   36 121 117 104 101 100  69  73  99  63  94  93  39  37  61  48
   58 113  32  90  44  98  60  51  33  97  62  77  84  80  85 223
  225 216 187 166 229 189 222 188 141 249 148 200 184 136 248 190
  199 170 181 204 138 232 218 183 255 234 220 247 213 203 226 193
  174 172 228 252 217 201 131 230 197 211 145 238 161 179 160 212
  207 221 254 173 202 146 224 151 140 196 205 130 135 133 143 246
  192 159 244 239 185 168 215 144 139 165 180 157 147 186 214 176
  227 231 219 169 175 156 206 198 129 164 150 210 154 177 134 127
  182 128 158 208 162 132 167 209 149 241 153 251 237 236 171 195
  243 233 253 240 194 250 191 155 142 137 245 235 163 242 178 152])

;; For XEmacs 20 or later, where chars and ints are distinct types.
(defalias 'cvs-scramble-i2c
  (if (fboundp 'int-to-char)
      'int-to-char
    'identity))

;; For XEmacs 20 or later, where chars and ints are distinct types.
(defalias 'cvs-scramble-c2i
  (if (fboundp 'char-to-int)
      'char-to-int
    'identity))

(defun cvs-scramble (s)
  (funcall cvs-scramble-default-method s))

(defun cvs-descramble (s)
  (let* ((m (aref s 0))
         (f (intern-soft (format "cvs-descramble-%c" m))))
    (if f
        (funcall f (substring s 1))
      (error "Unknown scrambling method \"%c\"" m))))

(defun cvs-scramble-A (s)
  (concat "A" (cvs-scramble/descramble-A-internal s)))

(defun cvs-descramble-A (s)
  (cvs-scramble/descramble-A-internal s))

;; This cipher is symmetric
(defun cvs-scramble/descramble-A-internal (s)
  (let ((i 0))
    (while (< i (length s))
      (aset s i
            (cvs-scramble-i2c (aref cvs-scramble-A-table
                                    (cvs-scramble-c2i (aref s i)))))
      (setq i (1+ i)))
    s))

(provide 'cvs-scramble)

;;; cvs-scramble.el ends here
