summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorantirez <antirez@gmail.com>2020-04-23 11:17:42 +0200
committerantirez <antirez@gmail.com>2020-04-23 11:23:50 +0200
commit9ae8254e20c151bb153519a868933cbd13d4c164 (patch)
tree894e6a14e69bfd0f101f6b4eda31ea26e9802643
parenta95a086be7b6c8eda5b0d181b6874ac88502aae5 (diff)
downloadredis-9ae8254e20c151bb153519a868933cbd13d4c164.tar.gz
getRandomBytes(): use HMAC-SHA256.
Now that we have an interface to use this API directly, via ACL GENPASS, we are no longer sure what people could do with it. So why don't make it a strong primitive exported by Redis in order to create unique IDs and so forth? The implementation was tested against the test vectors that can be found in RFC4231.
-rw-r--r--src/util.c40
1 files changed, 30 insertions, 10 deletions
diff --git a/src/util.c b/src/util.c
index bd8f0fb98..d173f776f 100644
--- a/src/util.c
+++ b/src/util.c
@@ -42,7 +42,7 @@
#include <time.h>
#include "util.h"
-#include "sha1.h"
+#include "sha256.h"
/* Glob-style pattern matching. */
int stringmatchlen(const char *pattern, int patternLen,
@@ -622,7 +622,7 @@ int ld2string(char *buf, size_t len, long double value, ld2string_mode mode) {
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. */
+ static unsigned char seed[64]; /* 512 bit internal block size. */
static uint64_t counter = 0; /* The counter we hash with the seed. */
if (!seed_initialized) {
@@ -647,14 +647,34 @@ void getRandomBytes(unsigned char *p, size_t len) {
}
while(len) {
- unsigned char digest[20];
- SHA1_CTX ctx;
- unsigned int copylen = len > 20 ? 20 : len;
-
- SHA1Init(&ctx);
- SHA1Update(&ctx, seed, sizeof(seed));
- SHA1Update(&ctx, (unsigned char*)&counter,sizeof(counter));
- SHA1Final(digest, &ctx);
+ /* This implements SHA256-HMAC. */
+ unsigned char digest[SHA256_BLOCK_SIZE];
+ unsigned char kxor[64];
+ unsigned int copylen =
+ len > SHA256_BLOCK_SIZE ? SHA256_BLOCK_SIZE : len;
+
+ /* IKEY: key xored with 0x36. */
+ memcpy(kxor,seed,sizeof(kxor));
+ for (unsigned int i = 0; i < sizeof(kxor); i++) kxor[i] ^= 0x36;
+
+ /* Obtain HASH(IKEY||MESSAGE). */
+ SHA256_CTX ctx;
+ sha256_init(&ctx);
+ sha256_update(&ctx,kxor,sizeof(kxor));
+ sha256_update(&ctx,(unsigned char*)&counter,sizeof(counter));
+ sha256_final(&ctx,digest);
+
+ /* OKEY: key xored with 0x5c. */
+ memcpy(kxor,seed,sizeof(kxor));
+ for (unsigned int i = 0; i < sizeof(kxor); i++) kxor[i] ^= 0x5C;
+
+ /* Obtain HASH(OKEY || HASH(IKEY||MESSAGE)). */
+ sha256_init(&ctx);
+ sha256_update(&ctx,kxor,sizeof(kxor));
+ sha256_update(&ctx,digest,SHA256_BLOCK_SIZE);
+ sha256_final(&ctx,digest);
+
+ /* Increment the counter for the next iteration. */
counter++;
memcpy(p,digest,copylen);