Merge pull request #1004 from cheloftus/dev

Added crypto.fhash function for hashing files
This commit is contained in:
Terry Ellison 2016-02-19 20:16:09 +00:00
commit 68919dea65
4 changed files with 108 additions and 0 deletions

View File

@ -122,6 +122,39 @@ int ICACHE_FLASH_ATTR crypto_hash (const digest_mech_info_t *mi,
} }
int ICACHE_FLASH_ATTR crypto_fhash (const digest_mech_info_t *mi,
read_fn read, int readarg,
uint8_t *digest)
{
if (!mi)
return EINVAL;
// Initialise
void *ctx = (void *)os_malloc (mi->ctx_size);
if (!ctx)
return ENOMEM;
mi->create (ctx);
// Hash bytes from file in blocks
uint8_t* buffer = (uint8_t*)os_malloc (mi->block_size);
if (!buffer)
return ENOMEM;
int read_len = 0;
do {
read_len = read(readarg, buffer, mi->block_size);
mi->update (ctx, buffer, read_len);
} while (read_len == mi->block_size);
// Finish up
mi->finalize (digest, ctx);
os_free (buffer);
os_free (ctx);
return 0;
}
int ICACHE_FLASH_ATTR crypto_hmac (const digest_mech_info_t *mi, int ICACHE_FLASH_ATTR crypto_hmac (const digest_mech_info_t *mi,
const char *data, size_t data_len, const char *data, size_t data_len,
const char *key, size_t key_len, const char *key, size_t key_len,

View File

@ -6,6 +6,7 @@
typedef void (*create_ctx_fn)(void *ctx); typedef void (*create_ctx_fn)(void *ctx);
typedef void (*update_ctx_fn)(void *ctx, const uint8_t *msg, int len); typedef void (*update_ctx_fn)(void *ctx, const uint8_t *msg, int len);
typedef void (*finalize_ctx_fn)(uint8_t *digest, void *ctx); typedef void (*finalize_ctx_fn)(uint8_t *digest, void *ctx);
typedef size_t ( *read_fn )(int fd, void *ptr, size_t len);
/** /**
* Description of a message digest mechanism. * Description of a message digest mechanism.
@ -53,6 +54,16 @@ const digest_mech_info_t *crypto_digest_mech (const char *mech);
*/ */
int crypto_hash (const digest_mech_info_t *mi, const char *data, size_t data_len, uint8_t *digest); int crypto_hash (const digest_mech_info_t *mi, const char *data, size_t data_len, uint8_t *digest);
/**
* Wrapper function for performing a one-in-all hashing operation of a file.
* @param mi A mech from @c crypto_digest_mech(). A null pointer @c mi
* is harmless, but will of course result in an error return.
* @param read Pointer to the read function (e.g. fs_read)
* @param readarg Argument to pass to the read function (e.g. file descriptor)
* @param digest Output buffer, must be at least @c mi->digest_size in size.
* @return 0 on success, non-zero on error.
*/
int crypto_fhash (const digest_mech_info_t *mi, read_fn read, int readarg, uint8_t *digest);
/** /**
* Generate a HMAC signature. * Generate a HMAC signature.

View File

@ -1,10 +1,12 @@
// Module for cryptography // Module for cryptography
#include <c_errno.h>
#include "module.h" #include "module.h"
#include "lauxlib.h" #include "lauxlib.h"
#include "platform.h" #include "platform.h"
#include "c_types.h" #include "c_types.h"
#include "c_stdlib.h" #include "c_stdlib.h"
#include "flash_fs.h"
#include "../crypto/digests.h" #include "../crypto/digests.h"
#include "../crypto/mech.h" #include "../crypto/mech.h"
@ -106,6 +108,7 @@ static int crypto_mask( lua_State* L )
static inline int bad_mech (lua_State *L) { return luaL_error (L, "unknown hash mech"); } 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_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) /* rawdigest = crypto.hash("MD5", str)
@ -128,6 +131,40 @@ static int crypto_lhash (lua_State *L)
} }
/* rawdigest = crypto.hash("MD5", filename)
* strdigest = crypto.toHex(rawdigest)
*/
static int crypto_flhash (lua_State *L)
{
const digest_mech_info_t *mi = crypto_digest_mech (luaL_checkstring (L, 1));
if (!mi)
return bad_mech (L);
const char *filename = luaL_checkstring (L, 2);
// Open the file
int file_fd = fs_open (filename, FS_RDONLY);
if(file_fd < FS_OPEN_OK) {
return bad_file(L);
}
// Compute hash
uint8_t digest[mi->digest_size];
int returncode = crypto_fhash (mi, &fs_read, file_fd, digest);
// Finish up
fs_close(file_fd);
if (returncode == ENOMEM)
return bad_mem (L);
else if (returncode == EINVAL)
return bad_mech(L);
else
lua_pushlstring (L, digest, sizeof (digest));
return 1;
}
/* rawsignature = crypto.hmac("SHA1", str, key) /* rawsignature = crypto.hmac("SHA1", str, key)
* strsignature = crypto.toHex(rawsignature) * strsignature = crypto.toHex(rawsignature)
*/ */
@ -220,6 +257,7 @@ static const LUA_REG_TYPE crypto_map[] = {
{ LSTRKEY( "toHex" ), LFUNCVAL( crypto_hex_encode ) }, { LSTRKEY( "toHex" ), LFUNCVAL( crypto_hex_encode ) },
{ LSTRKEY( "mask" ), LFUNCVAL( crypto_mask ) }, { LSTRKEY( "mask" ), LFUNCVAL( crypto_mask ) },
{ LSTRKEY( "hash" ), LFUNCVAL( crypto_lhash ) }, { LSTRKEY( "hash" ), LFUNCVAL( crypto_lhash ) },
{ LSTRKEY( "fhash" ), LFUNCVAL( crypto_flhash ) },
{ LSTRKEY( "hmac" ), LFUNCVAL( crypto_lhmac ) }, { LSTRKEY( "hmac" ), LFUNCVAL( crypto_lhmac ) },
{ LSTRKEY( "encrypt" ), LFUNCVAL( lcrypto_encrypt ) }, { LSTRKEY( "encrypt" ), LFUNCVAL( lcrypto_encrypt ) },
{ LSTRKEY( "decrypt" ), LFUNCVAL( lcrypto_decrypt ) }, { LSTRKEY( "decrypt" ), LFUNCVAL( lcrypto_decrypt ) },

View File

@ -61,6 +61,32 @@ print(crypto.decrypt("AES-ECB", key, cipher))
- [`crypto.encrypt()`](#cryptoencrypt) - [`crypto.encrypt()`](#cryptoencrypt)
## crypto.fhash()
Compute a cryptographic hash of a a file.
#### Syntax
`hash = crypto.fhash(algo, filename)`
#### Parameters
- `algo` the hash algorithm to use, case insensitive string
- `filename` the path to the file to hash
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
A binary string containing the message digest. To obtain the textual version (ASCII hex characters), please use [`crypto.toHex()`](#cryptotohex ).
#### Example
```lua
print(crypto.toHex(crypto.fhash("sha1","myfile.lua")))
```
## crypto.hash() ## crypto.hash()
Compute a cryptographic hash of a Lua string. Compute a cryptographic hash of a Lua string.