Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ruanhaishen
redis
Commits
b2868c7b
You need to sign in or sign up before continuing.
Commit
b2868c7b
authored
Apr 05, 2018
by
antirez
Browse files
Modules API: RM_GetRandomBytes() / GetRandomHexChars().
parent
c7558288
Changes
4
Show whitespace changes
Inline
Side-by-side
src/module.c
View file @
b2868c7b
...
...
@@ -4183,6 +4183,25 @@ int RM_GetTimerInfo(RedisModuleCtx *ctx, RedisModuleTimerID id, uint64_t *remain
return
REDISMODULE_OK
;
}
/* --------------------------------------------------------------------------
* Modules utility APIs
* -------------------------------------------------------------------------- */
/* Return random bytes using SHA1 in counter mode with a /dev/urandom
* initialized seed. This function is fast so can be used to generate
* many bytes without any effect on the operating system entropy pool.
* Currently this function is not thread safe. */
void
RM_GetRandomBytes
(
unsigned
char
*
dst
,
size_t
len
)
{
getRandomBytes
(
dst
,
len
);
}
/* Like RedisModule_GetRandomBytes() but instead of setting the string to
* random bytes the string is set to random characters in the in the
* hex charset [0-9a-f]. */
void
RM_GetRandomHexChars
(
char
*
dst
,
size_t
len
)
{
getRandomHexChars
(
dst
,
len
);
}
/* --------------------------------------------------------------------------
* Modules API internals
* -------------------------------------------------------------------------- */
...
...
@@ -4575,4 +4594,6 @@ void moduleRegisterCoreAPI(void) {
REGISTER_API
(
GetTimerInfo
);
REGISTER_API
(
GetMyClusterID
);
REGISTER_API
(
GetClusterSize
);
REGISTER_API
(
GetRandomBytes
);
REGISTER_API
(
GetRandomHexChars
);
}
src/redismodule.h
View file @
b2868c7b
...
...
@@ -278,6 +278,9 @@ int REDISMODULE_API_FUNC(RedisModule_StopTimer)(RedisModuleCtx *ctx, RedisModule
int
REDISMODULE_API_FUNC
(
RedisModule_GetTimerInfo
)(
RedisModuleCtx
*
ctx
,
RedisModuleTimerID
id
,
uint64_t
*
remaining
,
void
**
data
);
const
char
*
REDISMODULE_API_FUNC
(
RedisModule_GetMyClusterID
)(
void
);
size_t
REDISMODULE_API_FUNC
(
RedisModule_GetClusterSize
)(
void
);
void
REDISMODULE_API_FUNC
(
RedisModule_GetRandomBytes
)(
unsigned
char
*
dst
,
size_t
len
);
void
REDISMODULE_API_FUNC
(
RedisModule_GetRandomHexChars
)(
char
*
dst
,
size_t
len
);
/* Experimental APIs */
#ifdef REDISMODULE_EXPERIMENTAL_API
...
...
@@ -411,6 +414,8 @@ static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int
REDISMODULE_GET_API
(
GetTimerInfo
);
REDISMODULE_GET_API
(
GetMyClusterID
);
REDISMODULE_GET_API
(
GetClusterSize
);
REDISMODULE_GET_API
(
GetRandomBytes
);
REDISMODULE_GET_API
(
GetRandomHexChars
);
#ifdef REDISMODULE_EXPERIMENTAL_API
REDISMODULE_GET_API
(
GetThreadSafeContext
);
...
...
src/server.h
View file @
b2868c7b
...
...
@@ -1366,7 +1366,8 @@ void moduleNotifyKeyspaceEvent(int type, const char *event, robj *key, int dbid)
/* Utils */
long
long
ustime
(
void
);
long
long
mstime
(
void
);
void
getRandomHexChars
(
char
*
p
,
unsigned
int
len
);
void
getRandomHexChars
(
char
*
p
,
size_t
len
);
void
getRandomBytes
(
unsigned
char
*
p
,
size_t
len
);
uint64_t
crc64
(
uint64_t
crc
,
const
unsigned
char
*
s
,
uint64_t
l
);
void
exitFromChild
(
int
retcode
);
size_t
redisPopcount
(
void
*
s
,
long
count
);
...
...
src/util.c
View file @
b2868c7b
...
...
@@ -536,14 +536,12 @@ int ld2string(char *buf, size_t len, long double value, int humanfriendly) {
return
l
;
}
/* Generate the Redis "Run ID", a SHA1-sized random number that identifies a
* given execution of Redis, so that if you are talking with an instance
* having run_id == A, and you reconnect and it has run_id == B, you can be
* sure that it is either a different instance or it was restarted. */
void
getRandomHexChars
(
char
*
p
,
unsigned
int
len
)
{
char
*
charset
=
"0123456789abcdef"
;
unsigned
int
j
;
/* Get random bytes, attempts to get an initial seed from /dev/urandom and
* the uses a one way hash function in counter mode to generate a random
* stream. However if /dev/urandom is not available, a weaker seed is used.
*
* This function is not thread safe, since the state is global. */
void
getRandomBytes
(
unsigned
char
*
p
,
size_t
len
)
{
/* Global state. */
static
int
seed_initialized
=
0
;
static
unsigned
char
seed
[
20
];
/* The SHA1 seed, from /dev/urandom. */
...
...
@@ -555,12 +553,21 @@ void getRandomHexChars(char *p, unsigned int len) {
* function we just need non-colliding strings, there are no
* cryptographic security needs. */
FILE
*
fp
=
fopen
(
"/dev/urandom"
,
"r"
);
if
(
fp
&&
fread
(
seed
,
sizeof
(
seed
),
1
,
fp
)
==
1
)
if
(
fp
==
NULL
||
fread
(
seed
,
sizeof
(
seed
),
1
,
fp
)
!=
1
)
{
/* Revert to a weaker seed, and in this case reseed again
* at every call.*/
for
(
unsigned
int
j
=
0
;
j
<
sizeof
(
seed
);
j
++
)
{
struct
timeval
tv
;
gettimeofday
(
&
tv
,
NULL
);
pid_t
pid
=
getpid
();
seed
[
j
]
=
tv
.
tv_sec
^
tv
.
tv_usec
^
pid
^
(
long
)
fp
;
}
}
else
{
seed_initialized
=
1
;
}
if
(
fp
)
fclose
(
fp
);
}
if
(
seed_initialized
)
{
while
(
len
)
{
unsigned
char
digest
[
20
];
SHA1_CTX
ctx
;
...
...
@@ -573,44 +580,21 @@ void getRandomHexChars(char *p, unsigned int len) {
counter
++
;
memcpy
(
p
,
digest
,
copylen
);
/* Convert to hex digits. */
for
(
j
=
0
;
j
<
copylen
;
j
++
)
p
[
j
]
=
charset
[
p
[
j
]
&
0x0F
];
len
-=
copylen
;
p
+=
copylen
;
}
}
else
{
/* If we can't read from /dev/urandom, do some reasonable effort
* in order to create some entropy, since this function is used to
* generate run_id and cluster instance IDs */
char
*
x
=
p
;
unsigned
int
l
=
len
;
struct
timeval
tv
;
pid_t
pid
=
getpid
();
}
/* Use time and PID to fill the initial array. */
gettimeofday
(
&
tv
,
NULL
);
if
(
l
>=
sizeof
(
tv
.
tv_usec
))
{
memcpy
(
x
,
&
tv
.
tv_usec
,
sizeof
(
tv
.
tv_usec
));
l
-=
sizeof
(
tv
.
tv_usec
);
x
+=
sizeof
(
tv
.
tv_usec
);
}
if
(
l
>=
sizeof
(
tv
.
tv_sec
))
{
memcpy
(
x
,
&
tv
.
tv_sec
,
sizeof
(
tv
.
tv_sec
));
l
-=
sizeof
(
tv
.
tv_sec
);
x
+=
sizeof
(
tv
.
tv_sec
);
}
if
(
l
>=
sizeof
(
pid
))
{
memcpy
(
x
,
&
pid
,
sizeof
(
pid
));
l
-=
sizeof
(
pid
);
x
+=
sizeof
(
pid
);
}
/* Finally xor it with rand() output, that was already seeded with
* time() at startup, and convert to hex digits. */
for
(
j
=
0
;
j
<
len
;
j
++
)
{
p
[
j
]
^=
rand
();
p
[
j
]
=
charset
[
p
[
j
]
&
0x0F
];
}
}
/* Generate the Redis "Run ID", a SHA1-sized random number that identifies a
* given execution of Redis, so that if you are talking with an instance
* having run_id == A, and you reconnect and it has run_id == B, you can be
* sure that it is either a different instance or it was restarted. */
void
getRandomHexChars
(
char
*
p
,
size_t
len
)
{
char
*
charset
=
"0123456789abcdef"
;
size_t
j
;
getRandomBytes
((
unsigned
char
*
)
p
,
len
);
for
(
j
=
0
;
j
<
len
;
j
++
)
p
[
j
]
=
charset
[
p
[
j
]
&
0x0F
];
}
/* Given the filename, return the absolute path as an SDS string, or NULL
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment