diff options
Diffstat (limited to 'prototypes/c3b2/hmac.scm')
-rw-r--r-- | prototypes/c3b2/hmac.scm | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/prototypes/c3b2/hmac.scm b/prototypes/c3b2/hmac.scm new file mode 100644 index 0000000..2a3fa02 --- /dev/null +++ b/prototypes/c3b2/hmac.scm | |||
@@ -0,0 +1,54 @@ | |||
1 | ;; -*- mode: scheme; coding: utf-8 -*- | ||
2 | ;; Copyright © 2009, 2012 Göran Weinholt <goran@weinholt.se> | ||
3 | |||
4 | ;; Permission is hereby granted, free of charge, to any person obtaining a | ||
5 | ;; copy of this software and associated documentation files (the "Software"), | ||
6 | ;; to deal in the Software without restriction, including without limitation | ||
7 | ;; the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
8 | ;; and/or sell copies of the Software, and to permit persons to whom the | ||
9 | ;; Software is furnished to do so, subject to the following conditions: | ||
10 | |||
11 | ;; The above copyright notice and this permission notice shall be included in | ||
12 | ;; all copies or substantial portions of the Software. | ||
13 | |||
14 | ;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
15 | ;; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
16 | ;; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
17 | ;; THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
18 | ;; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
19 | ;; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
20 | ;; DEALINGS IN THE SOFTWARE. | ||
21 | #!r6rs | ||
22 | |||
23 | ;; RFC 2104, FIPS-198-1. | ||
24 | |||
25 | (library (hmac) | ||
26 | (export make-hmac) | ||
27 | (import (rnrs)) | ||
28 | |||
29 | ;; Returns a procedure that calculates the HMAC given a secret and | ||
30 | ;; data (both of which are bytevectors). | ||
31 | (define (make-hmac block-length hash ->bytevector make-hash update! finish! clear!) | ||
32 | (lambda (secret . data) | ||
33 | (let lp ((secret secret)) | ||
34 | (if (> (bytevector-length secret) block-length) | ||
35 | (lp (->bytevector (hash secret))) | ||
36 | (let ((k-ipad (make-bytevector block-length 0)) | ||
37 | (k-opad (make-bytevector block-length 0))) | ||
38 | (bytevector-copy! secret 0 k-ipad 0 (bytevector-length secret)) | ||
39 | (bytevector-copy! secret 0 k-opad 0 (bytevector-length secret)) | ||
40 | (do ((i 0 (fx+ i 1))) | ||
41 | ((fx=? i block-length)) | ||
42 | (bytevector-u8-set! k-ipad i (fxxor #x36 (bytevector-u8-ref k-ipad i))) | ||
43 | (bytevector-u8-set! k-opad i (fxxor #x5c (bytevector-u8-ref k-opad i)))) | ||
44 | (let ((state (make-hash))) | ||
45 | (update! state k-ipad) | ||
46 | (for-each (lambda (d) (update! state d)) data) | ||
47 | (finish! state) | ||
48 | (let ((digest (->bytevector state))) | ||
49 | (clear! state) | ||
50 | (update! state k-opad) | ||
51 | (update! state digest) | ||
52 | (finish! state) | ||
53 | state))))))) | ||
54 | ) | ||