Merge pull request #1004 from cheloftus/dev
Added crypto.fhash function for hashing files
This commit is contained in:
commit
68919dea65
|
@ -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,
|
||||
const char *data, size_t data_len,
|
||||
const char *key, size_t key_len,
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
typedef void (*create_ctx_fn)(void *ctx);
|
||||
typedef void (*update_ctx_fn)(void *ctx, const uint8_t *msg, int len);
|
||||
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.
|
||||
|
@ -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);
|
||||
|
||||
/**
|
||||
* 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.
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
// Module for cryptography
|
||||
|
||||
#include <c_errno.h>
|
||||
#include "module.h"
|
||||
#include "lauxlib.h"
|
||||
#include "platform.h"
|
||||
#include "c_types.h"
|
||||
#include "c_stdlib.h"
|
||||
#include "flash_fs.h"
|
||||
#include "../crypto/digests.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_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)
|
||||
|
@ -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)
|
||||
* strsignature = crypto.toHex(rawsignature)
|
||||
*/
|
||||
|
@ -220,6 +257,7 @@ static const LUA_REG_TYPE crypto_map[] = {
|
|||
{ LSTRKEY( "toHex" ), LFUNCVAL( crypto_hex_encode ) },
|
||||
{ LSTRKEY( "mask" ), LFUNCVAL( crypto_mask ) },
|
||||
{ LSTRKEY( "hash" ), LFUNCVAL( crypto_lhash ) },
|
||||
{ LSTRKEY( "fhash" ), LFUNCVAL( crypto_flhash ) },
|
||||
{ LSTRKEY( "hmac" ), LFUNCVAL( crypto_lhmac ) },
|
||||
{ LSTRKEY( "encrypt" ), LFUNCVAL( lcrypto_encrypt ) },
|
||||
{ LSTRKEY( "decrypt" ), LFUNCVAL( lcrypto_decrypt ) },
|
||||
|
|
|
@ -61,6 +61,32 @@ print(crypto.decrypt("AES-ECB", key, cipher))
|
|||
- [`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()
|
||||
|
||||
Compute a cryptographic hash of a Lua string.
|
||||
|
|
Loading…
Reference in New Issue