a0d92e63 |
1 | #!/bin/bash |
2 | # Implement HMAC functionality on top of the OpenSSL digest functions. |
3 | # licensed under the terms of the GNU GPL v2 |
4 | # Copyright 2007 Victor Lowther <victor.lowther@gmail.com> |
5 | |
6 | die() { |
7 | echo $* |
8 | exit 1 |
9 | } |
10 | |
11 | check_deps() { |
12 | local res=0 |
13 | while [ $# -ne 0 ]; do |
14 | which "${1}" >& /dev/null || { res=1; echo "${1} not found."; } |
15 | shift |
16 | done |
17 | (( res == 0 )) || die "aborting." |
18 | } |
19 | |
20 | # write a byte (passed as hex) to stdout |
21 | write_byte() { |
22 | # $1 = byte to write |
23 | printf "\\x$(printf "%x" ${1})" |
24 | } |
25 | |
26 | # make an hmac pad out of a key. |
27 | # this is not the most secure way of doing it, but it is |
28 | # the most expedient. |
29 | make_hmac_pad() { |
30 | # using key in file $1 and byte in $2, create the appropriate hmac pad |
31 | # Pad keys out to $3 bytes |
32 | # if key is longer than $3, use hash $4 to hash the key first. |
33 | local x y a size remainder oifs |
34 | [[ -f ${1} ]] || die "${1} does not exist when making hmac pads." |
35 | (( remainder = ${3} )) |
36 | # in case someone else was messing with IFS. |
37 | for x in $(od -v -t u1 < "${1}"|cut -b 9-); |
38 | do |
39 | write_byte $((${x} ^ ${2})) |
40 | (( remainder -= 1 )) |
41 | done |
42 | for ((y=0; remainder - y ;y++)); do |
43 | write_byte $((0 ^ ${2})) |
44 | done |
45 | } |
46 | |
47 | # utility functions for making hmac pads |
48 | hmac_ipad() { |
49 | make_hmac_pad "${1}" 0x36 ${2} "${3}" |
50 | } |
51 | |
52 | hmac_opad() { |
53 | make_hmac_pad "${1}" 0x5c ${2} "${3}" |
54 | } |
55 | |
56 | # hmac something |
57 | do_hmac() { |
58 | # $1 = algo to use. Must be one that openssl knows about |
59 | # $2 = keyfile to use |
60 | # $3 = file to hash. uses stdin if none is given. |
61 | # accepts input on stdin, leaves it on stdout. |
62 | # Output is binary, if you want something else pipe it accordingly. |
63 | local blocklen keysize x |
64 | case "${1}" in |
65 | sha) blocklen=64 ;; |
66 | sha1) blocklen=64 ;; |
67 | md5) blocklen=64 ;; |
68 | md4) blocklen=64 ;; |
69 | sha256) blocklen=64 ;; |
70 | sha512) blocklen=128 ;; |
71 | *) die "Unknown hash ${1} passed to hmac!" ;; |
72 | esac |
73 | keysize="$(wc -c "${2}")" |
74 | (( ${keysize%%[!0-9 ]*} > blocklen )) && \ |
75 | die "Prehashing large-size keys not implemented yet. Sorry." |
76 | cat <(hmac_ipad ${2} ${blocklen} "${1}") "${3:--}" | openssl dgst "-${1}" -binary | \ |
77 | cat <(hmac_opad ${2} ${blocklen} "${1}") - | openssl dgst "-${1}" -binary |
78 | } |
79 | |
80 | [[ ${1} ]] || die "Must pass the name of the hash function to use to ${0}". |
81 | |
82 | [[ -f ${2} ]] || die "Must pass file containing the secret to $0" |
83 | check_deps od openssl |
84 | do_hmac "${@}" |