Software /
code /
prosody
Comparison
util-src/hashes.c @ 5537:15464633d8fb
util.hmac, util.hashes: Implement HMAC functions in C, and move to util.hashes
author | Florian Zeitz <florob@babelmonkeys.de> |
---|---|
date | Sat, 27 Apr 2013 17:01:31 +0200 |
parent | 4829:0ebc636faa59 |
child | 5538:62089c9c142d |
comparison
equal
deleted
inserted
replaced
5531:483f795f6f99 | 5537:15464633d8fb |
---|---|
18 #include "lua.h" | 18 #include "lua.h" |
19 #include "lauxlib.h" | 19 #include "lauxlib.h" |
20 #include <openssl/sha.h> | 20 #include <openssl/sha.h> |
21 #include <openssl/md5.h> | 21 #include <openssl/md5.h> |
22 | 22 |
23 const char* hex_tab = "0123456789abcdef"; | 23 #define HMAC_IPAD 0x36363636 |
24 void toHex(const char* in, int length, char* out) { | 24 #define HMAC_OPAD 0x5c5c5c5c |
25 | |
26 const char *hex_tab = "0123456789abcdef"; | |
27 void toHex(const unsigned char *in, int length, unsigned char *out) { | |
25 int i; | 28 int i; |
26 for (i = 0; i < length; i++) { | 29 for (i = 0; i < length; i++) { |
27 out[i*2] = hex_tab[(in[i] >> 4) & 0xF]; | 30 out[i*2] = hex_tab[(in[i] >> 4) & 0xF]; |
28 out[i*2+1] = hex_tab[(in[i]) & 0xF]; | 31 out[i*2+1] = hex_tab[(in[i]) & 0xF]; |
29 } | 32 } |
32 #define MAKE_HASH_FUNCTION(myFunc, func, size) \ | 35 #define MAKE_HASH_FUNCTION(myFunc, func, size) \ |
33 static int myFunc(lua_State *L) { \ | 36 static int myFunc(lua_State *L) { \ |
34 size_t len; \ | 37 size_t len; \ |
35 const char *s = luaL_checklstring(L, 1, &len); \ | 38 const char *s = luaL_checklstring(L, 1, &len); \ |
36 int hex_out = lua_toboolean(L, 2); \ | 39 int hex_out = lua_toboolean(L, 2); \ |
37 char hash[size]; \ | 40 unsigned char hash[size], result[size*2]; \ |
38 char result[size*2]; \ | 41 func((const unsigned char*)s, len, hash); \ |
39 func((const unsigned char*)s, len, (unsigned char*)hash); \ | |
40 if (hex_out) { \ | 42 if (hex_out) { \ |
41 toHex(hash, size, result); \ | 43 toHex(hash, size, result); \ |
42 lua_pushlstring(L, result, size*2); \ | 44 lua_pushlstring(L, (char*)result, size*2); \ |
43 } else { \ | 45 } else { \ |
44 lua_pushlstring(L, hash, size);\ | 46 lua_pushlstring(L, (char*)hash, size);\ |
45 } \ | 47 } \ |
46 return 1; \ | 48 return 1; \ |
47 } | 49 } |
48 | 50 |
49 MAKE_HASH_FUNCTION(Lsha1, SHA1, SHA_DIGEST_LENGTH) | 51 MAKE_HASH_FUNCTION(Lsha1, SHA1, SHA_DIGEST_LENGTH) |
51 MAKE_HASH_FUNCTION(Lsha256, SHA256, SHA256_DIGEST_LENGTH) | 53 MAKE_HASH_FUNCTION(Lsha256, SHA256, SHA256_DIGEST_LENGTH) |
52 MAKE_HASH_FUNCTION(Lsha384, SHA384, SHA384_DIGEST_LENGTH) | 54 MAKE_HASH_FUNCTION(Lsha384, SHA384, SHA384_DIGEST_LENGTH) |
53 MAKE_HASH_FUNCTION(Lsha512, SHA512, SHA512_DIGEST_LENGTH) | 55 MAKE_HASH_FUNCTION(Lsha512, SHA512, SHA512_DIGEST_LENGTH) |
54 MAKE_HASH_FUNCTION(Lmd5, MD5, MD5_DIGEST_LENGTH) | 56 MAKE_HASH_FUNCTION(Lmd5, MD5, MD5_DIGEST_LENGTH) |
55 | 57 |
58 struct hash_desc { | |
59 int (*Init)(void*); | |
60 int (*Update)(void*, const void *, size_t); | |
61 int (*Final)(unsigned char*, void*); | |
62 size_t digestLength; | |
63 void *ctx, *ctxo; | |
64 }; | |
65 | |
66 static void hmac(struct hash_desc *desc, const char *key, size_t key_len, | |
67 const char *msg, size_t msg_len, unsigned char *result) | |
68 { | |
69 union xory { | |
70 unsigned char bytes[64]; | |
71 uint32_t quadbytes[16]; | |
72 }; | |
73 | |
74 int i; | |
75 char hashedKey[64]; /* Maximum used digest length */ | |
76 union xory k_ipad, k_opad; | |
77 | |
78 if (key_len > 64) { | |
79 desc->Init(desc->ctx); | |
80 desc->Update(desc->ctx, key, key_len); | |
81 desc->Final(desc->ctx, hashedKey); | |
82 key = (const char*)hashedKey; | |
83 key_len = desc->digestLength; | |
84 } | |
85 | |
86 memcpy(k_ipad.bytes, key, key_len); | |
87 memset(k_ipad.bytes + key_len, 0, 64 - key_len); | |
88 memcpy(k_opad.bytes, k_ipad.bytes, 64); | |
89 | |
90 for (i = 0; i < 16; i++) { | |
91 k_ipad.quadbytes[i] ^= HMAC_IPAD; | |
92 k_opad.quadbytes[i] ^= HMAC_OPAD; | |
93 } | |
94 | |
95 desc->Init(desc->ctx); | |
96 desc->Update(desc->ctx, k_ipad.bytes, 64); | |
97 desc->Init(desc->ctxo); | |
98 desc->Update(desc->ctxo, k_opad.bytes, 64); | |
99 desc->Update(desc->ctx, msg, msg_len); | |
100 desc->Final(result, desc->ctx); | |
101 desc->Update(desc->ctxo, result, desc->digestLength); | |
102 desc->Final(result, desc->ctxo); | |
103 } | |
104 | |
105 #define MAKE_HMAC_FUNCTION(myFunc, func, size, type) \ | |
106 static int myFunc(lua_State *L) { \ | |
107 type ctx, ctxo; \ | |
108 unsigned char hash[size], result[2*size]; \ | |
109 size_t key_len, msg_len; \ | |
110 const char *key = luaL_checklstring(L, 1, &key_len); \ | |
111 const char *msg = luaL_checklstring(L, 2, &msg_len); \ | |
112 const int hex_out = lua_toboolean(L, 3); \ | |
113 struct hash_desc desc; \ | |
114 desc.Init = (int (*)(void*))func##_Init; \ | |
115 desc.Update = (int (*)(void*, const void *, size_t))func##_Update; \ | |
116 desc.Final = (int (*)(unsigned char*, void*))func##_Final; \ | |
117 desc.digestLength = size; \ | |
118 desc.ctx = &ctx; \ | |
119 desc.ctxo = &ctxo; \ | |
120 hmac(&desc, key, key_len, msg, msg_len, hash); \ | |
121 if (hex_out) { \ | |
122 toHex(hash, size, result); \ | |
123 lua_pushlstring(L, (char*)result, size*2); \ | |
124 } else { \ | |
125 lua_pushlstring(L, (char*)hash, size); \ | |
126 } \ | |
127 return 1; \ | |
128 } | |
129 | |
130 MAKE_HMAC_FUNCTION(Lhmac_sha1, SHA1, SHA_DIGEST_LENGTH, SHA_CTX) | |
131 MAKE_HMAC_FUNCTION(Lhmac_sha256, SHA256, SHA256_DIGEST_LENGTH, SHA256_CTX) | |
132 MAKE_HMAC_FUNCTION(Lhmac_sha512, SHA512, SHA512_DIGEST_LENGTH, SHA512_CTX) | |
133 MAKE_HMAC_FUNCTION(Lhmac_md5, MD5, MD5_DIGEST_LENGTH, MD5_CTX) | |
134 | |
56 static const luaL_Reg Reg[] = | 135 static const luaL_Reg Reg[] = |
57 { | 136 { |
58 { "sha1", Lsha1 }, | 137 { "sha1", Lsha1 }, |
59 { "sha224", Lsha224 }, | 138 { "sha224", Lsha224 }, |
60 { "sha256", Lsha256 }, | 139 { "sha256", Lsha256 }, |
61 { "sha384", Lsha384 }, | 140 { "sha384", Lsha384 }, |
62 { "sha512", Lsha512 }, | 141 { "sha512", Lsha512 }, |
63 { "md5", Lmd5 }, | 142 { "md5", Lmd5 }, |
64 { NULL, NULL } | 143 { "hmac_sha1", Lhmac_sha1 }, |
144 { "hmac_sha256", Lhmac_sha256 }, | |
145 { "hmac_sha512", Lhmac_sha512 }, | |
146 { "hmac_md5", Lhmac_md5 }, | |
147 { NULL, NULL } | |
65 }; | 148 }; |
66 | 149 |
67 LUALIB_API int luaopen_util_hashes(lua_State *L) | 150 LUALIB_API int luaopen_util_hashes(lua_State *L) |
68 { | 151 { |
69 luaL_register(L, "hashes", Reg); | 152 luaL_register(L, "hashes", Reg); |