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 }