提交 f8ea19e5 编写于 作者: A antirez

DUMP/RESTORE now use CRC64 instead of truncated SHA1.

上级 9510d65d
#include "redis.h" #include "redis.h"
#include "sha1.h" #include "endianconv.h"
#include <arpa/inet.h> #include <arpa/inet.h>
#include <fcntl.h> #include <fcntl.h>
...@@ -1464,8 +1464,8 @@ void clusterCommand(redisClient *c) { ...@@ -1464,8 +1464,8 @@ void clusterCommand(redisClient *c) {
/* Generates a DUMP-format representation of the object 'o', adding it to the /* Generates a DUMP-format representation of the object 'o', adding it to the
* io stream pointed by 'rio'. This function can't fail. */ * io stream pointed by 'rio'. This function can't fail. */
void createDumpPayload(rio *payload, robj *o) { void createDumpPayload(rio *payload, robj *o) {
unsigned char hash[20], buf[2]; unsigned char buf[2];
SHA1_CTX ctx; uint64_t crc;
/* Serialize the object in a RDB-like format. It consist of an object type /* Serialize the object in a RDB-like format. It consist of an object type
* byte followed by the serialized object. This is understood by RESTORE. */ * byte followed by the serialized object. This is understood by RESTORE. */
...@@ -1474,35 +1474,34 @@ void createDumpPayload(rio *payload, robj *o) { ...@@ -1474,35 +1474,34 @@ void createDumpPayload(rio *payload, robj *o) {
redisAssert(rdbSaveObject(payload,o)); redisAssert(rdbSaveObject(payload,o));
/* Write the footer, this is how it looks like: /* Write the footer, this is how it looks like:
* ----------------+---------------------+--------------+ * ----------------+---------------------+---------------+
* ... RDB payload | 2 bytes RDB version | 8 bytes SHA1 | * ... RDB payload | 2 bytes RDB version | 8 bytes CRC64 |
* ----------------+---------------------+--------------+ * ----------------+---------------------+---------------+
* The SHA1 is just 8 bytes of truncated SHA1 of everything excluding itself. * RDB version and CRC are both in little endian.
* The 2 bytes RDB version is a little endian unsigned integer. */ */
/* RDB version */ /* RDB version */
buf[0] = REDIS_RDB_VERSION & 0xff; buf[0] = REDIS_RDB_VERSION & 0xff;
buf[1] = (REDIS_RDB_VERSION >> 8) & 0xff; buf[1] = (REDIS_RDB_VERSION >> 8) & 0xff;
payload->io.buffer.ptr = sdscatlen(payload->io.buffer.ptr,buf,2); payload->io.buffer.ptr = sdscatlen(payload->io.buffer.ptr,buf,2);
/* Truncated SHA1 */ /* CRC64 */
SHA1Init(&ctx); crc = crc64((unsigned char*)payload->io.buffer.ptr,
SHA1Update(&ctx,(unsigned char*)payload->io.buffer.ptr, sdslen(payload->io.buffer.ptr));
sdslen(payload->io.buffer.ptr)); memrev64ifbe(&crc);
SHA1Final(hash,&ctx); payload->io.buffer.ptr = sdscatlen(payload->io.buffer.ptr,&crc,8);
payload->io.buffer.ptr = sdscatlen(payload->io.buffer.ptr,hash,8);
} }
/* Verify that the RDB version of the dump payload matches the one of this Redis /* Verify that the RDB version of the dump payload matches the one of this Redis
* instance and that the truncated SHA1 is ok. * instance and that the checksum is ok.
* If the DUMP payload looks valid REDIS_OK is returned, otherwise REDIS_ERR * If the DUMP payload looks valid REDIS_OK is returned, otherwise REDIS_ERR
* is returned. */ * is returned. */
int verifyDumpPayload(unsigned char *p, size_t len) { int verifyDumpPayload(unsigned char *p, size_t len) {
unsigned char hash[20], *footer; unsigned char *footer;
SHA1_CTX ctx;
uint16_t rdbver; uint16_t rdbver;
uint64_t crc;
/* At least 2 bytes of RDB version and 8 of truncated SHA should be present. */ /* At least 2 bytes of RDB version and 8 of CRC64 should be present. */
if (len < 10) return REDIS_ERR; if (len < 10) return REDIS_ERR;
footer = p+(len-10); footer = p+(len-10);
...@@ -1510,11 +1509,10 @@ int verifyDumpPayload(unsigned char *p, size_t len) { ...@@ -1510,11 +1509,10 @@ int verifyDumpPayload(unsigned char *p, size_t len) {
rdbver = (footer[1] << 8) | footer[0]; rdbver = (footer[1] << 8) | footer[0];
if (rdbver != REDIS_RDB_VERSION) return REDIS_ERR; if (rdbver != REDIS_RDB_VERSION) return REDIS_ERR;
/* Verify truncated SHA1 */ /* Verify CRC64 */
SHA1Init(&ctx); crc = crc64(p,len-8);
SHA1Update(&ctx,p,len-8); memrev64ifbe(&crc);
SHA1Final(hash,&ctx); return (memcmp(&crc,footer+2,8) == 0) ? REDIS_OK : REDIS_ERR;
return (memcmp(hash,footer+2,8) == 0) ? REDIS_OK : REDIS_ERR;
} }
/* DUMP keyname /* DUMP keyname
...@@ -1561,7 +1559,7 @@ void restoreCommand(redisClient *c) { ...@@ -1561,7 +1559,7 @@ void restoreCommand(redisClient *c) {
return; return;
} }
/* Verify truncated SHA1 and RDB version. */ /* Verify RDB version and data checksum. */
if (verifyDumpPayload(c->argv[3]->ptr,sdslen(c->argv[3]->ptr)) == REDIS_ERR) { if (verifyDumpPayload(c->argv[3]->ptr,sdslen(c->argv[3]->ptr)) == REDIS_ERR) {
addReplyError(c,"DUMP payload version or checksum are wrong"); addReplyError(c,"DUMP payload version or checksum are wrong");
return; return;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册