mirror of
https://github.com/minetest/minetest.git
synced 2024-11-27 10:03:45 +01:00
Add LuaSecureRandom
This commit is contained in:
parent
d506d56707
commit
ad5ac39d8d
@ -2765,6 +2765,15 @@ It can be created via `PcgRandom(seed)` or `PcgRandom(seed, sequence)`.
|
|||||||
* This is only a rough approximation of a normal distribution with mean=(max-min)/2 and variance=1
|
* This is only a rough approximation of a normal distribution with mean=(max-min)/2 and variance=1
|
||||||
* Increasing num_trials improves accuracy of the approximation
|
* Increasing num_trials improves accuracy of the approximation
|
||||||
|
|
||||||
|
### `SecureRandom`
|
||||||
|
Interface for the operating system's crypto-secure PRNG.
|
||||||
|
|
||||||
|
It can be created via `SecureRandom()`. The constructor returns nil if a secure random device cannot be
|
||||||
|
be found on the system.
|
||||||
|
|
||||||
|
#### Methods
|
||||||
|
* `next_bytes([count])`: return next `count` (default 1, capped at 2048) many random bytes, as a string.
|
||||||
|
|
||||||
### `PerlinNoise`
|
### `PerlinNoise`
|
||||||
A perlin noise generator.
|
A perlin noise generator.
|
||||||
It can be created via `PerlinNoise(seed, octaves, persistence, scale)`
|
It can be created via `PerlinNoise(seed, octaves, persistence, scale)`
|
||||||
|
@ -29,6 +29,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/sysctl.h>
|
#include <sys/sysctl.h>
|
||||||
#elif defined(_WIN32)
|
#elif defined(_WIN32)
|
||||||
|
#include <windows.h>
|
||||||
|
#include <wincrypt.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#endif
|
#endif
|
||||||
#if !defined(_WIN32)
|
#if !defined(_WIN32)
|
||||||
@ -701,5 +703,44 @@ v2u32 getDisplaySize()
|
|||||||
# endif // __ANDROID__
|
# endif // __ANDROID__
|
||||||
#endif // SERVER
|
#endif // SERVER
|
||||||
|
|
||||||
} //namespace porting
|
|
||||||
|
|
||||||
|
////
|
||||||
|
//// OS-specific Secure Random
|
||||||
|
////
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
|
||||||
|
bool secure_rand_fill_buf(void *buf, size_t len)
|
||||||
|
{
|
||||||
|
HCRYPTPROV wctx;
|
||||||
|
|
||||||
|
if (!CryptAcquireContext(&wctx, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
CryptGenRandom(wctx, len, (BYTE *)buf);
|
||||||
|
CryptReleaseContext(wctx, 0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
bool secure_rand_fill_buf(void *buf, size_t len)
|
||||||
|
{
|
||||||
|
// N.B. This function checks *only* for /dev/urandom, because on most
|
||||||
|
// common OSes it is non-blocking, whereas /dev/random is blocking, and it
|
||||||
|
// is exceptionally uncommon for there to be a situation where /dev/random
|
||||||
|
// exists but /dev/urandom does not. This guesswork is necessary since
|
||||||
|
// random devices are not covered by any POSIX standard...
|
||||||
|
FILE *fp = fopen("/dev/urandom", "rb");
|
||||||
|
if (!fp)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bool success = fread(buf, len, 1, fp) == 1;
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} //namespace porting
|
||||||
|
@ -343,6 +343,7 @@ void setXorgClassHint(const video::SExposedVideoData &video_data,
|
|||||||
// threads in the process inherit this exception handler
|
// threads in the process inherit this exception handler
|
||||||
void setWin32ExceptionHandler();
|
void setWin32ExceptionHandler();
|
||||||
|
|
||||||
|
bool secure_rand_fill_buf(void *buf, size_t len);
|
||||||
} // namespace porting
|
} // namespace porting
|
||||||
|
|
||||||
#ifdef __ANDROID__
|
#ifdef __ANDROID__
|
||||||
|
@ -22,6 +22,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "common/c_converter.h"
|
#include "common/c_converter.h"
|
||||||
#include "common/c_content.h"
|
#include "common/c_content.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "porting.h"
|
||||||
|
#include "util/numeric.h"
|
||||||
|
|
||||||
///////////////////////////////////////
|
///////////////////////////////////////
|
||||||
/*
|
/*
|
||||||
@ -600,3 +602,116 @@ const luaL_reg LuaPcgRandom::methods[] = {
|
|||||||
luamethod(LuaPcgRandom, rand_normal_dist),
|
luamethod(LuaPcgRandom, rand_normal_dist),
|
||||||
{0,0}
|
{0,0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
/*
|
||||||
|
LuaSecureRandom
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool LuaSecureRandom::fillRandBuf()
|
||||||
|
{
|
||||||
|
return porting::secure_rand_fill_buf(m_rand_buf, RAND_BUF_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
int LuaSecureRandom::l_next_bytes(lua_State *L)
|
||||||
|
{
|
||||||
|
NO_MAP_LOCK_REQUIRED;
|
||||||
|
|
||||||
|
LuaSecureRandom *o = checkobject(L, 1);
|
||||||
|
u32 count = lua_isnumber(L, 2) ? lua_tointeger(L, 2) : 1;
|
||||||
|
|
||||||
|
// Limit count
|
||||||
|
count = MYMIN(RAND_BUF_SIZE, count);
|
||||||
|
|
||||||
|
// Find out whether we can pass directly from our array, or have to do some gluing
|
||||||
|
size_t count_remaining = RAND_BUF_SIZE - o->m_rand_idx;
|
||||||
|
if (count_remaining >= count) {
|
||||||
|
lua_pushlstring(L, o->m_rand_buf + o->m_rand_idx, count);
|
||||||
|
o->m_rand_idx += count;
|
||||||
|
} else {
|
||||||
|
char output_buf[RAND_BUF_SIZE];
|
||||||
|
|
||||||
|
// Copy over with what we have left from our current buffer
|
||||||
|
memcpy(output_buf, o->m_rand_buf + o->m_rand_idx, count_remaining);
|
||||||
|
|
||||||
|
// Refill buffer and copy over the remainder of what was requested
|
||||||
|
o->fillRandBuf();
|
||||||
|
memcpy(output_buf + count_remaining, o->m_rand_buf, count - count_remaining);
|
||||||
|
|
||||||
|
// Update index
|
||||||
|
o->m_rand_idx = count - count_remaining;
|
||||||
|
|
||||||
|
lua_pushlstring(L, output_buf, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int LuaSecureRandom::create_object(lua_State *L)
|
||||||
|
{
|
||||||
|
LuaSecureRandom *o = new LuaSecureRandom();
|
||||||
|
|
||||||
|
// Fail and return nil if we can't securely fill the buffer
|
||||||
|
if (!o->fillRandBuf()) {
|
||||||
|
delete o;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
*(void **)(lua_newuserdata(L, sizeof(void *))) = o;
|
||||||
|
luaL_getmetatable(L, className);
|
||||||
|
lua_setmetatable(L, -2);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int LuaSecureRandom::gc_object(lua_State *L)
|
||||||
|
{
|
||||||
|
LuaSecureRandom *o = *(LuaSecureRandom **)(lua_touserdata(L, 1));
|
||||||
|
delete o;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
LuaSecureRandom *LuaSecureRandom::checkobject(lua_State *L, int narg)
|
||||||
|
{
|
||||||
|
luaL_checktype(L, narg, LUA_TUSERDATA);
|
||||||
|
void *ud = luaL_checkudata(L, narg, className);
|
||||||
|
if (!ud)
|
||||||
|
luaL_typerror(L, narg, className);
|
||||||
|
return *(LuaSecureRandom **)ud;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void LuaSecureRandom::Register(lua_State *L)
|
||||||
|
{
|
||||||
|
lua_newtable(L);
|
||||||
|
int methodtable = lua_gettop(L);
|
||||||
|
luaL_newmetatable(L, className);
|
||||||
|
int metatable = lua_gettop(L);
|
||||||
|
|
||||||
|
lua_pushliteral(L, "__metatable");
|
||||||
|
lua_pushvalue(L, methodtable);
|
||||||
|
lua_settable(L, metatable);
|
||||||
|
|
||||||
|
lua_pushliteral(L, "__index");
|
||||||
|
lua_pushvalue(L, methodtable);
|
||||||
|
lua_settable(L, metatable);
|
||||||
|
|
||||||
|
lua_pushliteral(L, "__gc");
|
||||||
|
lua_pushcfunction(L, gc_object);
|
||||||
|
lua_settable(L, metatable);
|
||||||
|
|
||||||
|
lua_pop(L, 1);
|
||||||
|
|
||||||
|
luaL_openlib(L, 0, methods, 0);
|
||||||
|
lua_pop(L, 1);
|
||||||
|
|
||||||
|
lua_register(L, className, create_object);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char LuaSecureRandom::className[] = "SecureRandom";
|
||||||
|
const luaL_reg LuaSecureRandom::methods[] = {
|
||||||
|
luamethod(LuaSecureRandom, next_bytes),
|
||||||
|
{0,0}
|
||||||
|
};
|
||||||
|
@ -160,4 +160,37 @@ public:
|
|||||||
static void Register(lua_State *L);
|
static void Register(lua_State *L);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
LuaSecureRandom
|
||||||
|
*/
|
||||||
|
class LuaSecureRandom : public ModApiBase {
|
||||||
|
private:
|
||||||
|
static const size_t RAND_BUF_SIZE = 2048;
|
||||||
|
static const char className[];
|
||||||
|
static const luaL_reg methods[];
|
||||||
|
|
||||||
|
u32 m_rand_idx;
|
||||||
|
char m_rand_buf[RAND_BUF_SIZE];
|
||||||
|
|
||||||
|
// Exported functions
|
||||||
|
|
||||||
|
// garbage collector
|
||||||
|
static int gc_object(lua_State *L);
|
||||||
|
|
||||||
|
// next_bytes(self, count) -> get count many bytes
|
||||||
|
static int l_next_bytes(lua_State *L);
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool fillRandBuf();
|
||||||
|
|
||||||
|
// LuaSecureRandom()
|
||||||
|
// Creates an LuaSecureRandom and leaves it on top of stack
|
||||||
|
static int create_object(lua_State *L);
|
||||||
|
|
||||||
|
static LuaSecureRandom *checkobject(lua_State *L, int narg);
|
||||||
|
|
||||||
|
static void Register(lua_State *L);
|
||||||
|
};
|
||||||
|
|
||||||
#endif /* L_NOISE_H_ */
|
#endif /* L_NOISE_H_ */
|
||||||
|
@ -98,6 +98,7 @@ void GameScripting::InitializeModApi(lua_State *L, int top)
|
|||||||
LuaPerlinNoiseMap::Register(L);
|
LuaPerlinNoiseMap::Register(L);
|
||||||
LuaPseudoRandom::Register(L);
|
LuaPseudoRandom::Register(L);
|
||||||
LuaPcgRandom::Register(L);
|
LuaPcgRandom::Register(L);
|
||||||
|
LuaSecureRandom::Register(L);
|
||||||
LuaVoxelManip::Register(L);
|
LuaVoxelManip::Register(L);
|
||||||
NodeMetaRef::Register(L);
|
NodeMetaRef::Register(L);
|
||||||
NodeTimerRef::Register(L);
|
NodeTimerRef::Register(L);
|
||||||
|
Loading…
Reference in New Issue
Block a user