util-src/hashes.c
changeset 5537 15464633d8fb
parent 4829 0ebc636faa59
child 5538 62089c9c142d
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);