luajitos

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

PBKDF2_Lua.c (6423B)


      1 /*
      2  * PBKDF2_Lua.c - Lua bindings for key derivation functions
      3  * Includes: PBKDF2, Argon2id, HKDF
      4  */
      5 
      6 #include "PBKDF2_Lua.h"
      7 #include "PBKDF2.h"
      8 #include "Argon2.h"
      9 #include "HKDF.h"
     10 #include "CSPRNG.h"
     11 #include "hashing/hash.h"
     12 #include <string.h>
     13 #include <stdlib.h>
     14 
     15 /* ============================================================================
     16  * PBKDF2 Key Derivation Functions
     17  * ========================================================================= */
     18 
     19 /* deriveKey(password, salt, iterations) - Derive 32-byte key from password (returns binary) */
     20 int l_deriveKey(lua_State *L) {
     21     size_t password_len;
     22     const char *password = luaL_checklstring(L, 1, &password_len);
     23 
     24     size_t salt_len;
     25     const uint8_t *salt = (const uint8_t*)luaL_checklstring(L, 2, &salt_len);
     26 
     27     uint32_t iterations = luaL_optinteger(L, 3, PBKDF2_ITERATIONS_RECOMMENDED);
     28 
     29     if (iterations < 10000) {
     30         return luaL_error(L, "Iterations too low (minimum 10,000, recommended 600,000)");
     31     }
     32 
     33     uint8_t key[32];
     34     if (pbkdf2_hmac_sha256((const uint8_t*)password, password_len,
     35                            salt, salt_len,
     36                            iterations,
     37                            key, 32) != 0) {
     38         return luaL_error(L, "Key derivation failed");
     39     }
     40 
     41     lua_pushlstring(L, (const char*)key, 32);
     42     memset(key, 0, 32);  /* Zero sensitive data */
     43     return 1;
     44 }
     45 
     46 /* deriveKeyString(password, salt, iterations) - Derive key from password (returns base64) */
     47 int l_deriveKeyString(lua_State *L) {
     48     size_t password_len;
     49     const char *password = luaL_checklstring(L, 1, &password_len);
     50 
     51     size_t salt_len;
     52     const uint8_t *salt = (const uint8_t*)luaL_checklstring(L, 2, &salt_len);
     53 
     54     uint32_t iterations = luaL_optinteger(L, 3, PBKDF2_ITERATIONS_RECOMMENDED);
     55 
     56     if (iterations < 10000) {
     57         return luaL_error(L, "Iterations too low (minimum 10,000, recommended 600,000)");
     58     }
     59 
     60     uint8_t key[32];
     61     if (pbkdf2_hmac_sha256((const uint8_t*)password, password_len,
     62                            salt, salt_len,
     63                            iterations,
     64                            key, 32) != 0) {
     65         memset(key, 0, 32);
     66         return luaL_error(L, "Key derivation failed");
     67     }
     68 
     69     size_t b64_len;
     70     char *b64 = base64_encode(key, 32, &b64_len);
     71     memset(key, 0, 32);  /* Zero sensitive data */
     72 
     73     if (!b64) {
     74         return luaL_error(L, "Base64 encoding failed");
     75     }
     76 
     77     lua_pushlstring(L, b64, b64_len);
     78     free(b64);
     79     return 1;
     80 }
     81 
     82 /* generateSalt(length) - Generate random salt (default 16 bytes) */
     83 int l_generateSalt(lua_State *L) {
     84     size_t len = luaL_optinteger(L, 1, 16);
     85 
     86     if (len < 8 || len > 256) {
     87         return luaL_error(L, "Salt length must be between 8 and 256 bytes");
     88     }
     89 
     90     uint8_t *salt = malloc(len);
     91     if (!salt) {
     92         return luaL_error(L, "Memory allocation failed");
     93     }
     94 
     95     random_bytes(salt, len);
     96     lua_pushlstring(L, (const char*)salt, len);
     97     free(salt);
     98     return 1;
     99 }
    100 
    101 /* deriveKeySimple(password) - Argon2id-based key derivation (returns base64) */
    102 int l_deriveKeySimple(lua_State *L) {
    103     size_t password_len;
    104     const char *password = luaL_checklstring(L, 1, &password_len);
    105 
    106     /* Use SHA-256 of password as salt (deterministic) */
    107     uint8_t salt[32];
    108     sha256((const uint8_t*)password, password_len, salt);
    109 
    110     /* Derive key using Argon2id with recommended defaults */
    111     uint8_t key[32];
    112     if (argon2id_simple((const uint8_t*)password, password_len,
    113                         salt, 32,
    114                         key, 32) != 0) {
    115         memset(key, 0, 32);
    116         memset(salt, 0, 32);
    117         return luaL_error(L, "Argon2id key derivation failed");
    118     }
    119 
    120     size_t b64_len;
    121     char *b64 = base64_encode(key, 32, &b64_len);
    122     memset(key, 0, 32);  /* Zero sensitive data */
    123     memset(salt, 0, 32);
    124 
    125     if (!b64) {
    126         return luaL_error(L, "Base64 encoding failed");
    127     }
    128 
    129     lua_pushlstring(L, b64, b64_len);
    130     free(b64);
    131     return 1;
    132 }
    133 
    134 /* Argon2id key derivation with custom salt */
    135 int l_argon2id_derive(lua_State *L) {
    136     size_t password_len;
    137     const char *password = luaL_checklstring(L, 1, &password_len);
    138 
    139     size_t salt_len;
    140     const uint8_t *salt = (const uint8_t*)luaL_checklstring(L, 2, &salt_len);
    141 
    142     /* Optional parameters */
    143     uint32_t t_cost = luaL_optinteger(L, 3, ARGON2_TIME_DEFAULT);
    144     uint32_t m_cost = luaL_optinteger(L, 4, ARGON2_MEMORY_DEFAULT);
    145 
    146     uint8_t key[32];
    147     if (argon2id((const uint8_t*)password, password_len,
    148                  salt, salt_len,
    149                  t_cost, m_cost,
    150                  key, 32) != 0) {
    151         memset(key, 0, 32);
    152         return luaL_error(L, "Argon2id derivation failed");
    153     }
    154 
    155     size_t b64_len;
    156     char *b64 = base64_encode(key, 32, &b64_len);
    157     memset(key, 0, 32);
    158 
    159     if (!b64) {
    160         return luaL_error(L, "Base64 encoding failed");
    161     }
    162 
    163     lua_pushlstring(L, b64, b64_len);
    164     free(b64);
    165     return 1;
    166 }
    167 
    168 /* ============================================================================
    169  * HKDF Key Derivation Functions
    170  * ========================================================================= */
    171 
    172 /* HKDF key derivation */
    173 int l_hkdf_derive(lua_State *L) {
    174     size_t ikm_len;
    175     const uint8_t *ikm = (const uint8_t*)luaL_checklstring(L, 1, &ikm_len);
    176 
    177     /* Optional salt */
    178     const uint8_t *salt = NULL;
    179     size_t salt_len = 0;
    180     if (!lua_isnoneornil(L, 2)) {
    181         salt = (const uint8_t*)luaL_checklstring(L, 2, &salt_len);
    182     }
    183 
    184     /* Optional info */
    185     const uint8_t *info = NULL;
    186     size_t info_len = 0;
    187     if (!lua_isnoneornil(L, 3)) {
    188         info = (const uint8_t*)luaL_checklstring(L, 3, &info_len);
    189     }
    190 
    191     /* Output length (default 32) */
    192     size_t okm_len = luaL_optinteger(L, 4, 32);
    193     if (okm_len > 255 * 32) {
    194         return luaL_error(L, "Output length too large (max 8160 bytes)");
    195     }
    196 
    197     uint8_t *okm = malloc(okm_len);
    198     if (!okm) {
    199         return luaL_error(L, "Memory allocation failed");
    200     }
    201 
    202     if (hkdf_sha256(salt, salt_len, ikm, ikm_len, info, info_len, okm, okm_len) != 0) {
    203         free(okm);
    204         return luaL_error(L, "HKDF derivation failed");
    205     }
    206 
    207     size_t b64_len;
    208     char *b64 = base64_encode(okm, okm_len, &b64_len);
    209     memset(okm, 0, okm_len);
    210     free(okm);
    211 
    212     if (!b64) {
    213         return luaL_error(L, "Base64 encoding failed");
    214     }
    215 
    216     lua_pushlstring(L, b64, b64_len);
    217     free(b64);
    218     return 1;
    219 }