Initial implementation of a chunk capable hash function in crypto module
This commit is contained in:
parent
9970f8dc34
commit
332b53b9db
|
@ -105,12 +105,10 @@ static int crypto_mask( lua_State* L )
|
|||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static inline int bad_mech (lua_State *L) { return luaL_error (L, "unknown hash mech"); }
|
||||
static inline int bad_mem (lua_State *L) { return luaL_error (L, "insufficient memory"); }
|
||||
static inline int bad_file (lua_State *L) { return luaL_error (L, "file does not exist"); }
|
||||
|
||||
|
||||
/* rawdigest = crypto.hash("MD5", str)
|
||||
* strdigest = crypto.toHex(rawdigest)
|
||||
*/
|
||||
|
@ -130,6 +128,112 @@ static int crypto_lhash (lua_State *L)
|
|||
return 1;
|
||||
}
|
||||
|
||||
typedef struct digest_user_datum_t {
|
||||
const digest_mech_info_t *mech_info;
|
||||
void *ctx;
|
||||
} digest_user_datum_t;
|
||||
|
||||
/* General Usage for extensible hash functions:
|
||||
* sha = crypto.new_hash("MD5")
|
||||
* sha.update("Data")
|
||||
* sha.update("Data2")
|
||||
* strdigest = crypto.toHex(sha.finalize())
|
||||
*/
|
||||
|
||||
/* crypto.new_hash("MECHTYPE") */
|
||||
static int crypto_new_hash (lua_State *L)
|
||||
{
|
||||
const digest_mech_info_t *mi = crypto_digest_mech (luaL_checkstring (L, 1));
|
||||
if (!mi)
|
||||
return bad_mech (L);
|
||||
|
||||
void *ctx = os_malloc (mi->ctx_size);
|
||||
mi->create (ctx);
|
||||
|
||||
// create a userdataum with specific metatable
|
||||
digest_user_datum_t *dudat = (digest_user_datum_t *)lua_newuserdata(L, sizeof(digest_user_datum_t));
|
||||
luaL_getmetatable(L, "crypto.hash");
|
||||
lua_setmetatable(L, -2);
|
||||
|
||||
// Set pointers to the mechanics and CTX
|
||||
dudat->mech_info = mi;
|
||||
dudat->ctx = ctx;
|
||||
|
||||
return 1; // Pass userdata object back
|
||||
}
|
||||
|
||||
/* Called as object, params:
|
||||
1 - userdata "this"
|
||||
2 - new string to add to the hash state */
|
||||
static int crypto_hash_update (lua_State *L)
|
||||
{
|
||||
NODE_DBG("enter crypto_hash_update.\n");
|
||||
digest_user_datum_t *dudat;
|
||||
size_t sl;
|
||||
|
||||
dudat = (digest_user_datum_t *)luaL_checkudata(L, 1, "crypto.hash");
|
||||
luaL_argcheck(L, dudat, 1, "crypto.hash expected");
|
||||
if(dudat==NULL){
|
||||
NODE_DBG("userdata is nil.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
const digest_mech_info_t *mi = dudat->mech_info;
|
||||
|
||||
if (!mi)
|
||||
return bad_mech (L);
|
||||
|
||||
size_t len = 0;
|
||||
const char *data = luaL_checklstring (L, 2, &len);
|
||||
|
||||
mi->update (dudat->ctx, data, len);
|
||||
|
||||
return 0; // No return value
|
||||
}
|
||||
|
||||
/* Called as object, no params. Returns digest of default size. */
|
||||
static int crypto_hash_finalize (lua_State *L)
|
||||
{
|
||||
NODE_DBG("enter crypto_hash_update.\n");
|
||||
digest_user_datum_t *dudat;
|
||||
size_t sl;
|
||||
|
||||
dudat = (digest_user_datum_t *)luaL_checkudata(L, 1, "crypto.hash");
|
||||
luaL_argcheck(L, dudat, 1, "crypto.hash expected");
|
||||
if(dudat==NULL){
|
||||
NODE_DBG("userdata is nil.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
const digest_mech_info_t *mi = dudat->mech_info;
|
||||
|
||||
uint8_t digest[mi->digest_size]; // Allocate as local
|
||||
mi->finalize (digest, dudat->ctx);
|
||||
|
||||
lua_pushlstring (L, digest, sizeof (digest));
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Frees memory for the user datum and CTX hash state */
|
||||
static int crypto_hash_gcdelete (lua_State *L)
|
||||
{
|
||||
NODE_DBG("enter crypto_hash_delete.\n");
|
||||
digest_user_datum_t *dudat;
|
||||
size_t sl;
|
||||
|
||||
dudat = (digest_user_datum_t *)luaL_checkudata(L, 1, "crypto.hash");
|
||||
luaL_argcheck(L, dudat, 1, "crypto.hash expected");
|
||||
if(dudat==NULL){
|
||||
NODE_DBG("userdata is nil.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
os_free(dudat->ctx);
|
||||
os_free(dudat);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* rawdigest = crypto.hash("MD5", filename)
|
||||
* strdigest = crypto.toHex(rawdigest)
|
||||
|
@ -249,6 +353,15 @@ static int lcrypto_decrypt (lua_State *L)
|
|||
return crypto_encdec (L, false);
|
||||
}
|
||||
|
||||
// Hash function map
|
||||
static const LUA_REG_TYPE crypto_hash_map[] = {
|
||||
{ LSTRKEY( "update" ), LFUNCVAL( crypto_hash_update ) },
|
||||
{ LSTRKEY( "finalize" ), LFUNCVAL( crypto_hash_finalize ) },
|
||||
{ LSTRKEY( "__gc" ), LFUNCVAL( crypto_hash_gcdelete ) },
|
||||
{ LSTRKEY( "__index" ), LROVAL( crypto_hash_map ) },
|
||||
{ LNILKEY, LNILVAL }
|
||||
};
|
||||
|
||||
|
||||
// Module function map
|
||||
static const LUA_REG_TYPE crypto_map[] = {
|
||||
|
@ -258,10 +371,17 @@ static const LUA_REG_TYPE crypto_map[] = {
|
|||
{ LSTRKEY( "mask" ), LFUNCVAL( crypto_mask ) },
|
||||
{ LSTRKEY( "hash" ), LFUNCVAL( crypto_lhash ) },
|
||||
{ LSTRKEY( "fhash" ), LFUNCVAL( crypto_flhash ) },
|
||||
{ LSTRKEY( "new_hash" ), LFUNCVAL( crypto_new_hash ) },
|
||||
{ LSTRKEY( "hmac" ), LFUNCVAL( crypto_lhmac ) },
|
||||
{ LSTRKEY( "encrypt" ), LFUNCVAL( lcrypto_encrypt ) },
|
||||
{ LSTRKEY( "decrypt" ), LFUNCVAL( lcrypto_decrypt ) },
|
||||
{ LNILKEY, LNILVAL }
|
||||
};
|
||||
|
||||
NODEMCU_MODULE(CRYPTO, "crypto", crypto_map, NULL);
|
||||
int luaopen_crypto ( lua_State *L )
|
||||
{
|
||||
luaL_rometatable(L, "crypto.hash", (void *)crypto_hash_map); // create metatable for crypto.hash
|
||||
return 0;
|
||||
}
|
||||
|
||||
NODEMCU_MODULE(CRYPTO, "crypto", crypto_map, luaopen_crypto);
|
||||
|
|
|
@ -96,6 +96,7 @@ Compute a cryptographic hash of a Lua string.
|
|||
|
||||
#### Parameters
|
||||
`algo` the hash algorithm to use, case insensitive string
|
||||
`str` string to hash contents of
|
||||
|
||||
Supported hash algorithms are:
|
||||
|
||||
|
@ -112,6 +113,35 @@ A binary string containing the message digest. To obtain the textual version (AS
|
|||
print(crypto.toHex(crypto.hash("sha1","abc")))
|
||||
```
|
||||
|
||||
## crypto.new_hash()
|
||||
|
||||
Create a digest/hash object that can have any number of strings added to it. Object has `update` and `finalize` functions.
|
||||
|
||||
#### Syntax
|
||||
`hashobj = crypto.new_hash(algo)`
|
||||
|
||||
#### Parameters
|
||||
`algo` the hash algorithm to use, case insensitive string
|
||||
|
||||
Supported hash algorithms are:
|
||||
|
||||
- MD2 (not available by default, has to be explicitly enabled in `app/include/user_config.h`)
|
||||
- MD5
|
||||
- SHA1
|
||||
- SHA256, SHA384, SHA512 (unless disabled in `app/include/user_config.h`)
|
||||
|
||||
#### Returns
|
||||
Userdata object with `update` and `finalize` functions available.
|
||||
|
||||
#### Example
|
||||
```lua
|
||||
hashobj = crypto.new_hash("SHA1")
|
||||
hashobj:update("FirstString"))
|
||||
hashobj:update("SecondString"))
|
||||
digest = hashobj:finalize()
|
||||
print(crypto.toHex(digest))
|
||||
```
|
||||
|
||||
## crypto.hmac()
|
||||
|
||||
Compute a [HMAC](https://en.wikipedia.org/wiki/Hash-based_message_authentication_code) (Hashed Message Authentication Code) signature for a Lua string.
|
||||
|
|
Loading…
Reference in New Issue