Commit 235534b9 authored by Nils Goroll's avatar Nils Goroll

Add RS hash and check that it is equal to the key() method of the shard director

parent 392bb2ea
......@@ -189,6 +189,7 @@ values:
* ``CRC32`` (not for HMACs)
* ``MD5``
* ``RS`` (not for HMACs)
* ``SHA1``
* ``SHA224``
* ``SHA256``
......@@ -202,8 +203,8 @@ values:
CONTENTS
========
* digest(ENUM {CRC32,MD5,SHA1,SHA224,SHA256,SHA384,SHA512,SHA3_224,SHA3_256,SHA3_384,SHA3_512}, BLOB, ENUM {TASK,TOP})
* BLOB hash(ENUM {CRC32,MD5,SHA1,SHA224,SHA256,SHA384,SHA512,SHA3_224,SHA3_256,SHA3_384,SHA3_512}, BLOB)
* digest(ENUM {CRC32,RS,MD5,SHA1,SHA224,SHA256,SHA384,SHA512,SHA3_224,SHA3_256,SHA3_384,SHA3_512}, BLOB, ENUM {TASK,TOP})
* BLOB hash(ENUM {CRC32,MD5,RS,SHA1,SHA224,SHA256,SHA384,SHA512,SHA3_224,SHA3_256,SHA3_384,SHA3_512}, BLOB)
* hmac(ENUM {MD5,SHA1,SHA224,SHA256,SHA384,SHA512,SHA3_224,SHA3_256,SHA3_384,SHA3_512}, BLOB)
* BLOB hmacf(ENUM {MD5,SHA1,SHA224,SHA256,SHA384,SHA512,SHA3_224,SHA3_256,SHA3_384,SHA3_512}, BLOB, BLOB)
* STRING version()
......@@ -216,7 +217,7 @@ digest
::
new OBJ = digest(ENUM {CRC32,MD5,SHA1,SHA224,SHA256,SHA384,SHA512,SHA3_224,SHA3_256,SHA3_384,SHA3_512} hash, BLOB init=0, ENUM {TASK,TOP} scope=TASK)
new OBJ = digest(ENUM {CRC32,RS,MD5,SHA1,SHA224,SHA256,SHA384,SHA512,SHA3_224,SHA3_256,SHA3_384,SHA3_512} hash, BLOB init=0, ENUM {TASK,TOP} scope=TASK)
Initialize a message digest context for the algorithm ``hash``, and
optionally update it with ``init``. If ``init`` is left out, then an
......@@ -403,7 +404,7 @@ hash
::
BLOB hash(ENUM {CRC32,MD5,SHA1,SHA224,SHA256,SHA384,SHA512,SHA3_224,SHA3_256,SHA3_384,SHA3_512} hash, BLOB msg)
BLOB hash(ENUM {CRC32,MD5,RS,SHA1,SHA224,SHA256,SHA384,SHA512,SHA3_224,SHA3_256,SHA3_384,SHA3_512} hash, BLOB msg)
Returns the message digest for ``msg`` as specified by ``hash``.
......
VMODENUM(CRC32)
VMODENUM(MD5)
VMODENUM(RS)
VMODENUM(SHA1)
VMODENUM(SHA224)
VMODENUM(SHA256)
......
# looks like -*- vcl -*-
varnishtest "inverted CRC32 checksum"
varnish v1 -vcl {
import blobdigest from "${vmod_topbuild}/src/.libs/libvmod_blobdigest.so";
import blob;
import directors;
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new shard = directors.shard();
new a = blob.blob(IDENTITY, "a");
new msg = blob.blob(IDENTITY, "message");
new alphalc = blob.blob(IDENTITY,
"abcdefghijklmnopqrstuvwxyz");
new empty = blob.blob(IDENTITY, "");
new alphauc = blob.blob(IDENTITY,
"ABCDEFGHIJKLMNOPQRSTUVWXYZ");
new digits = blob.blob(IDENTITY, "1234567890");
new pangram =
blob.blob(IDENTITY,
"The quick brown fox jumps over the lazy dog");
new d1 = blobdigest.digest(ICRC32);
new d2 = blobdigest.digest(ICRC32);
new d3 = blobdigest.digest(ICRC32, a.get());
new d4 = blobdigest.digest(ICRC32, msg.get());
new d5 = blobdigest.digest(ICRC32, alphalc.get());
new d7 = blobdigest.digest(ICRC32, alphauc.get());
new d8 = blobdigest.digest(ICRC32, digits.get());
new d9 = blobdigest.digest(ICRC32, pangram.get());
}
sub vcl_recv {
return(synth(200));
}
sub vcl_synth {
if (!d1.update(empty.get())) {
set resp.status = 500;
return(deliver);
}
set resp.http.empty = blob.encode(HEX, UPPER, d1.final());
if (!d2.update(a.get())) {
set resp.status = 500;
return(deliver);
}
set resp.http.a = blob.encode(HEX, UPPER, d2.final());
set resp.http.as = blob.encode(HEX, UPPER,
blobdigest._uint32blob(shard.key("a", CRC32)));
if (!d3.update(blob.decode(encoded="b"))) {
set resp.status = 500;
return(deliver);
}
if (!d3.update(blob.decode(encoded="c"))) {
set resp.status = 500;
return(deliver);
}
set resp.http.abc = blob.encode(HEX, UPPER, d3.final());
set resp.http.abcs = blob.encode(HEX, UPPER,
blobdigest._uint32blob(shard.key("abc", CRC32)));
if (!d4.update(blob.decode(encoded=" "))) {
set resp.status = 500;
return(deliver);
}
if (!d4.update(blob.decode(encoded="digest"))) {
set resp.status = 500;
return(deliver);
}
set resp.http.msgdigest = blob.encode(HEX, UPPER, d4.final());
set resp.http.msgdigests = blob.encode(HEX, UPPER,
blobdigest._uint32blob(shard.key("message digest", CRC32)));
if (!d5.update(blob.decode(encoded=""))) {
set resp.status = 500;
return(deliver);
}
set resp.http.alphalc = blob.encode(HEX, UPPER, d5.final());
set resp.http.alphalcs = blob.encode(HEX, UPPER,
blobdigest._uint32blob(
shard.key(blob.encode(IDENTITY, blob=alphalc.get()), CRC32)));
if (!d7.update(alphalc.get())) {
set resp.status = 500;
return(deliver);
}
if (!d7.update(blob.decode(encoded="0123456789"))) {
set resp.status = 500;
return(deliver);
}
set resp.http.alphanum = blob.encode(HEX, UPPER, d7.final());
set resp.http.alphanums = blob.encode(HEX, UPPER,
blobdigest._uint32blob(shard.key(
blob.encode(IDENTITY, blob=alphauc.get()) +
blob.encode(IDENTITY, blob=alphalc.get()) +
"0123456789", CRC32)));
if (!d8.update(digits.get())) {
set resp.status = 500;
return(deliver);
}
if (!d8.update(digits.get())) {
set resp.status = 500;
return(deliver);
}
if (!d8.update(digits.get())) {
set resp.status = 500;
return(deliver);
}
if (!d8.update(digits.get())) {
set resp.status = 500;
return(deliver);
}
if (!d8.update(digits.get())) {
set resp.status = 500;
return(deliver);
}
if (!d8.update(digits.get())) {
set resp.status = 500;
return(deliver);
}
if (!d8.update(digits.get())) {
set resp.status = 500;
return(deliver);
}
set resp.http.digits = blob.encode(HEX, UPPER, d8.final());
set resp.http.digitss = blob.encode(HEX, UPPER,
blobdigest._uint32blob(shard.key(
blob.encode(IDENTITY, blob=digits.get()) +
blob.encode(IDENTITY, blob=digits.get()) +
blob.encode(IDENTITY, blob=digits.get()) +
blob.encode(IDENTITY, blob=digits.get()) +
blob.encode(IDENTITY, blob=digits.get()) +
blob.encode(IDENTITY, blob=digits.get()) +
blob.encode(IDENTITY, blob=digits.get()) +
blob.encode(IDENTITY, blob=digits.get()), CRC32)));
set resp.http.pangram = blob.encode(HEX, UPPER, d9.final());
set resp.http.pangrams = blob.encode(HEX, UPPER,
blobdigest._uint32blob(shard.key(
blob.encode(IDENTITY, blob=pangram.get()), CRC32)));
# Tests for the hash() function
set resp.http.emptyf
= blob.encode(HEX, UPPER, blobdigest.hash(ICRC32, empty.get()));
set resp.http.af
= blob.encode(HEX, UPPER, blobdigest.hash(ICRC32,
blob.decode(encoded="a")));
set resp.http.abcf
= blob.encode(HEX, UPPER, blobdigest.hash(ICRC32,
blob.decode(encoded="abc")));
set resp.http.msgdigestf
= blob.encode(HEX, UPPER, blobdigest.hash(ICRC32,
blob.decode(encoded=
"message digest")));
set resp.http.alphalcf
= blob.encode(HEX, UPPER, blobdigest.hash(ICRC32,
blob.decode(encoded=
"abcdefghijklmnopqrstuvwxyz")));
set resp.http.alphanumf
= blob.encode(HEX, UPPER, blobdigest.hash(ICRC32,
blob.decode(encoded=
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")));
set resp.http.digitsf
= blob.encode(HEX, UPPER, blobdigest.hash(ICRC32,
blob.decode(encoded=
"12345678901234567890123456789012345678901234567890123456789012345678901234567890")));
set resp.http.pangramf
= blob.encode(HEX, UPPER, blobdigest.hash(ICRC32,
blob.decode(encoded=
"The quick brown fox jumps over the lazy dog")));
}
} -start
client c1 {
txreq
rxresp
expect resp.status == 200
# from librhash
expect resp.http.empty == "00000000"
expect resp.http.emptyf == resp.http.empty
expect resp.http.a == "00000061"
expect resp.http.as == resp.http.a
expect resp.http.af == resp.http.a
expect resp.http.abc == "B1012AAC"
expect resp.http.abcs == resp.http.abc
expect resp.http.abcf == resp.http.abc
expect resp.http.msgdigest == "B4ACD743"
expect resp.http.msgdigests == resp.http.msgdigest
expect resp.http.msgdigestf == resp.http.msgdigest
expect resp.http.alphalc == "C19D0661"
expect resp.http.alphalcs == resp.http.alphalc
expect resp.http.alphalcf == resp.http.alphalc
expect resp.http.alphanum == "4389DF19"
expect resp.http.alphanums == resp.http.alphanum
expect resp.http.alphanumf == resp.http.alphanum
expect resp.http.digits == "9DA5ECA0"
expect resp.http.digitss == resp.http.digits
expect resp.http.digitsf == resp.http.digits
expect resp.http.pangram == "29A4500B"
expect resp.http.pangrams == resp.http.pangram
expect resp.http.pangramf == resp.http.pangram
expect resp.http.allbytes == "D65ECA00"
expect resp.http.allbytesf == resp.http.allbytes
} -run
# looks like -*- vcl -*-
varnishtest "RS checksum"
varnish v1 -vcl {
import blobdigest from "${vmod_topbuild}/src/.libs/libvmod_blobdigest.so";
import blob;
import directors;
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new shard = directors.shard();
new a = blob.blob(IDENTITY, "a");
new msg = blob.blob(IDENTITY, "message");
new alphalc = blob.blob(IDENTITY,
"abcdefghijklmnopqrstuvwxyz");
new empty = blob.blob(IDENTITY, "");
new alphauc = blob.blob(IDENTITY,
"ABCDEFGHIJKLMNOPQRSTUVWXYZ");
new digits = blob.blob(IDENTITY, "1234567890");
new pangram =
blob.blob(IDENTITY,
"The quick brown fox jumps over the lazy dog");
# Byte values 0 to 63, 64 to 127, etc up to 255
new b0to63 = blob.blob(BASE64,
"AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+Pw==");
new b64to127 = blob.blob(BASE64,
"QEFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaW1xdXl9gYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXp7fH1+fw==");
new b128to191 = blob.blob(BASE64,
"gIGCg4SFhoeIiYqLjI2Oj5CRkpOUlZaXmJmam5ydnp+goaKjpKWmp6ipqqusra6vsLGys7S1tre4ubq7vL2+vw==");
new b192to255 = blob.blob(BASE64,
"wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+/w==");
new d1 = blobdigest.digest(RS);
new d2 = blobdigest.digest(RS);
new d3 = blobdigest.digest(RS, a.get());
new d4 = blobdigest.digest(RS, msg.get());
new d5 = blobdigest.digest(RS, alphalc.get());
new d7 = blobdigest.digest(RS, alphauc.get());
new d8 = blobdigest.digest(RS, digits.get());
new d9 = blobdigest.digest(RS, pangram.get());
new d11 = blobdigest.digest(RS, b0to63.get());
}
sub vcl_recv {
return(synth(200));
}
sub vcl_synth {
if (!d1.update(empty.get())) {
set resp.status = 500;
return(deliver);
}
set resp.http.empty = blob.encode(HEX, UPPER, d1.final());
if (!d2.update(a.get())) {
set resp.status = 500;
return(deliver);
}
set resp.http.a = blob.encode(HEX, UPPER, d2.final());
set resp.http.as = blob.encode(HEX, UPPER,
blobdigest._uint32blob(shard.key("a", RS)));
if (!d3.update(blob.decode(encoded="b"))) {
set resp.status = 500;
return(deliver);
}
if (!d3.update(blob.decode(encoded="c"))) {
set resp.status = 500;
return(deliver);
}
set resp.http.abc = blob.encode(HEX, UPPER, d3.final());
set resp.http.abcs = blob.encode(HEX, UPPER,
blobdigest._uint32blob(shard.key("abc", RS)));
if (!d4.update(blob.decode(encoded=" "))) {
set resp.status = 500;
return(deliver);
}
if (!d4.update(blob.decode(encoded="digest"))) {
set resp.status = 500;
return(deliver);
}
set resp.http.msgdigest = blob.encode(HEX, UPPER, d4.final());
set resp.http.msgdigests = blob.encode(HEX, UPPER,
blobdigest._uint32blob(shard.key("message digest", RS)));
if (!d5.update(blob.decode(encoded=""))) {
set resp.status = 500;
return(deliver);
}
set resp.http.alphalc = blob.encode(HEX, UPPER, d5.final());
set resp.http.alphalcs = blob.encode(HEX, UPPER,
blobdigest._uint32blob(
shard.key(blob.encode(IDENTITY, blob=alphalc.get()), RS)));
if (!d7.update(alphalc.get())) {
set resp.status = 500;
return(deliver);
}
if (!d7.update(blob.decode(encoded="0123456789"))) {
set resp.status = 500;
return(deliver);
}
set resp.http.alphanum = blob.encode(HEX, UPPER, d7.final());
set resp.http.alphanums = blob.encode(HEX, UPPER,
blobdigest._uint32blob(shard.key(
blob.encode(IDENTITY, blob=alphauc.get()) +
blob.encode(IDENTITY, blob=alphalc.get()) +
"0123456789", RS)));
if (!d8.update(digits.get())) {
set resp.status = 500;
return(deliver);
}
if (!d8.update(digits.get())) {
set resp.status = 500;
return(deliver);
}
if (!d8.update(digits.get())) {
set resp.status = 500;
return(deliver);
}
if (!d8.update(digits.get())) {
set resp.status = 500;
return(deliver);
}
if (!d8.update(digits.get())) {
set resp.status = 500;
return(deliver);
}
if (!d8.update(digits.get())) {
set resp.status = 500;
return(deliver);
}
if (!d8.update(digits.get())) {
set resp.status = 500;
return(deliver);
}
set resp.http.digits = blob.encode(HEX, UPPER, d8.final());
set resp.http.digitss = blob.encode(HEX, UPPER,
blobdigest._uint32blob(shard.key(
blob.encode(IDENTITY, blob=digits.get()) +
blob.encode(IDENTITY, blob=digits.get()) +
blob.encode(IDENTITY, blob=digits.get()) +
blob.encode(IDENTITY, blob=digits.get()) +
blob.encode(IDENTITY, blob=digits.get()) +
blob.encode(IDENTITY, blob=digits.get()) +
blob.encode(IDENTITY, blob=digits.get()) +
blob.encode(IDENTITY, blob=digits.get()), RS)));
set resp.http.pangram = blob.encode(HEX, UPPER, d9.final());
set resp.http.pangrams = blob.encode(HEX, UPPER,
blobdigest._uint32blob(shard.key(
blob.encode(IDENTITY, blob=pangram.get()), RS)));
if (!d11.update(b64to127.get())) {
set resp.status = 500;
return(deliver);
}
if (!d11.update(b128to191.get())) {
set resp.status = 500;
return(deliver);
}
if (!d11.update(b192to255.get())) {
set resp.status = 500;
return(deliver);
}
set resp.http.allbytes = blob.encode(HEX, UPPER, d11.final());
# Tests for the hash() function
set resp.http.emptyf
= blob.encode(HEX, UPPER, blobdigest.hash(RS, empty.get()));
set resp.http.af
= blob.encode(HEX, UPPER, blobdigest.hash(RS,
blob.decode(encoded="a")));
set resp.http.abcf
= blob.encode(HEX, UPPER, blobdigest.hash(RS,
blob.decode(encoded="abc")));
set resp.http.msgdigestf
= blob.encode(HEX, UPPER, blobdigest.hash(RS,
blob.decode(encoded=
"message digest")));
set resp.http.alphalcf
= blob.encode(HEX, UPPER, blobdigest.hash(RS,
blob.decode(encoded=
"abcdefghijklmnopqrstuvwxyz")));
set resp.http.alphanumf
= blob.encode(HEX, UPPER, blobdigest.hash(RS,
blob.decode(encoded=
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")));
set resp.http.digitsf
= blob.encode(HEX, UPPER, blobdigest.hash(RS,
blob.decode(encoded=
"12345678901234567890123456789012345678901234567890123456789012345678901234567890")));
set resp.http.pangramf
= blob.encode(HEX, UPPER, blobdigest.hash(RS,
blob.decode(encoded=
"The quick brown fox jumps over the lazy dog")));
# all 256 byte values in ascending order
set resp.http.allbytesf
= blob.encode(HEX, UPPER, blobdigest.hash(RS,
blob.decode(decoding=BASE64, encoded=
"AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+/w==")));
}
} -start
client c1 {
txreq
rxresp
expect resp.status == 200
# from librhash
expect resp.http.empty == "00000000"
expect resp.http.emptyf == resp.http.empty
expect resp.http.a == "00000061"
expect resp.http.as == resp.http.a
expect resp.http.af == resp.http.a
expect resp.http.abc == "B1012AAC"
expect resp.http.abcs == resp.http.abc
expect resp.http.abcf == resp.http.abc
expect resp.http.msgdigest == "B4ACD743"
expect resp.http.msgdigests == resp.http.msgdigest
expect resp.http.msgdigestf == resp.http.msgdigest
expect resp.http.alphalc == "C19D0661"
expect resp.http.alphalcs == resp.http.alphalc
expect resp.http.alphalcf == resp.http.alphalc
expect resp.http.alphanum == "4389DF19"
expect resp.http.alphanums == resp.http.alphanum
expect resp.http.alphanumf == resp.http.alphanum
expect resp.http.digits == "9DA5ECA0"
expect resp.http.digitss == resp.http.digits
expect resp.http.digitsf == resp.http.digits
expect resp.http.pangram == "29A4500B"
expect resp.http.pangrams == resp.http.pangram
expect resp.http.pangramf == resp.http.pangram
expect resp.http.allbytes == "D65ECA00"
expect resp.http.allbytesf == resp.http.allbytes
} -run
......@@ -96,6 +96,25 @@ parse_scope(VCL_ENUM e)
WRONG("illegal scope enum");
}
/* too simple to qualify for an own source file */
static void
hash_rs(uint32_t state[2], const unsigned char *msg, size_t size)
{
/* hash function from Robert Sedgwicks 'Algorithms in C' book */
uint32_t res = state[0];
uint32_t a = state[1];
const uint32_t b = 378551;
const unsigned char *e;
for (e = msg + size; msg < e; msg++) {
res = res * a + *msg;
a *= b;
}
state[0] = res;
state[1] = a;
}
static void
init(const enum algorithm hash, hash_ctx * const hctx)
{
......@@ -106,6 +125,10 @@ init(const enum algorithm hash, hash_ctx * const hctx)
case MD5:
rhash_md5_init(&hctx->md5);
break;
case RS:
hctx->uint32[0] = 0;
hctx->uint32[1] = 63689;
break;
case SHA1:
rhash_sha1_init(&hctx->sha1);
break;
......@@ -149,6 +172,9 @@ update(const enum algorithm hash, hash_ctx *restrict const hctx,
case MD5:
rhash_md5_update(&hctx->md5, msg, len);
break;
case RS:
hash_rs(hctx->uint32, msg, len);
break;
case SHA1:
rhash_sha1_update(&hctx->sha1, msg, len);
break;
......@@ -179,6 +205,7 @@ final(const enum algorithm hash, hash_ctx *restrict const hctx,
{
switch(hash) {
case CRC32:
case RS:
be32_copy(result, 0, &hctx->uint32[0], sizeof(uint32_t));
break;
case MD5:
......
......@@ -73,6 +73,10 @@ static const struct hashspec {
md5_hash_size,
md5_block_size,
},
[RS] = {
sizeof(uint32_t),
sizeof(uint32_t),
},
[SHA1] = {
sha1_hash_size,
sha1_block_size,
......
......@@ -174,6 +174,7 @@ values:
* ``CRC32`` (not for HMACs)
* ``MD5``
* ``RS`` (not for HMACs)
* ``SHA1``
* ``SHA224``
* ``SHA256``
......@@ -184,8 +185,8 @@ values:
* ``SHA3_384``
* ``SHA3_512``
$Object digest(ENUM {CRC32, MD5, SHA1, SHA224, SHA256, SHA384, SHA512, SHA3_224,
SHA3_256, SHA3_384, SHA3_512} hash,
$Object digest(ENUM {CRC32, RS, MD5, SHA1, SHA224, SHA256, SHA384, SHA512,
SHA3_224, SHA3_256, SHA3_384, SHA3_512} hash,
BLOB init=0, ENUM {TASK, TOP} scope=TASK)
Initialize a message digest context for the algorithm ``hash``, and
......@@ -352,7 +353,7 @@ Example::
# Baz-Hash-Base64: base64-encoded SHA3_256 hash of "baz"
# Baz-Hash-Hex: hex-encoded SHA3_256 hash of "bar"
$Function BLOB hash(ENUM {CRC32, MD5, SHA1, SHA224, SHA256, SHA384, SHA512,
$Function BLOB hash(ENUM {CRC32, MD5, RS, SHA1, SHA224, SHA256, SHA384, SHA512,
SHA3_224, SHA3_256, SHA3_384, SHA3_512} hash,
BLOB msg)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment