Commit 2981d24e authored by Geoff Simmons's avatar Geoff Simmons

add CRC32

parent 1f6827bc
Pipeline #67 skipped
......@@ -12,9 +12,9 @@
vmod_blobdigest
===============
---------------------------------------
digests and hmacs for the VCL blob type
---------------------------------------
---------------------------------------------------
digests , checksums and hmacs for the VCL blob type
---------------------------------------------------
:Manual section: 3
......@@ -38,9 +38,9 @@ import blobdigest [from "path"] ;
DESCRIPTION
===========
This Varnish Module (VMOD) generates message digests and keyed-hash
message authentication codes (HMACs) using the VCL data type BLOB,
which may contain arbitrary data of any length.
This Varnish Module (VMOD) generates message digests, keyed-hash
message authentication codes (HMACs) and checksums using the VCL data
type BLOB, which may contain arbitrary data of any length.
Currently (in Varnish versions through 5.0), BLOBs may only be used in
VCL as arguments of VMOD functions, so this VMOD must be used in
......@@ -188,6 +188,7 @@ HASH ALGORITHMS
The ``hash`` enum in the following can have one of the following
values:
* ``CRC32`` (not for HMACs)
* ``MD5``
* ``SHA1``
* ``SHA224``
......
......@@ -10,6 +10,8 @@ libvmod_blobdigest_la_SOURCES = \
vmod_blobdigest.c \
byte_order.h \
byte_order.c \
crc32.h \
crc32.c \
md5.h \
md5.c \
sha1.h \
......
/* crc32.c - an implementation of CRC32 hash function
*
* Copyright: 2006-2012 Aleksey Kravchenko <rhash.admin@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. Use this program at your own risk!
*/
#include <string.h>
#include "byte_order.h"
#include "crc32.h"
#ifdef GENERATE_CRC32_TABLE
unsigned rhash_crc32_table[256];
/**
* Initialize global array rhash_crc32_table. The array takes 1 KiB of
* the program size, so generating array at run-time can save a little space.
*/
void rhash_crc32_init_table(void)
{
unsigned crc, poly;
int i, j;
poly = 0xEDB88320;
for (i = 0; i < 256; i++) {
crc = i;
for (j = 8; j > 0; j--) {
if (crc & 1) crc = (crc >> 1) ^ poly;
else crc >>= 1;
}
rhash_crc32_table[i] = crc;
}
}
#else /* CRC32_GENTABLE */
unsigned rhash_crc32_table[256] = {
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
};
#endif /* CRC32_GENTABLE */
/**
* Calculate CRC32 sum for a null-terminated string.
*
* @param crcinit intermediate crc32 hash result
* @param str the string to process
* @return updated crc32 sum
*/
unsigned rhash_get_crc32_str(unsigned crcinit, const char *str)
{
return rhash_get_crc32(crcinit, (const unsigned char*)str, strlen(str));
}
/**
* Calculate CRC32 sum of a given message.
*
* @param crcinit intermediate CRC32 hash result
* @param msg the message to process
* @param size the length of the message
* @return updated CRC32 hash sum
*/
unsigned rhash_get_crc32(unsigned crcinit, const unsigned char *msg, size_t size)
{
register unsigned crc = crcinit ^ 0xFFFFFFFF;
const unsigned char *e;
/* process not aligned message head */
for (; (3 & (msg - (unsigned char*)0)) && size > 0; msg++, size--)
crc = rhash_crc32_table[(crc ^ *msg) & 0xFF] ^ (crc >> 8);
/* fast CRC32 calculation of a DWORD-aligned message */
for (e = msg + (size & ~15); msg < e; msg += 16) {
crc ^= le2me_32( ((const unsigned *)msg)[0] );
crc = rhash_crc32_table[crc & 0xFF] ^ (crc >> 8);
crc = rhash_crc32_table[crc & 0xFF] ^ (crc >> 8);
crc = rhash_crc32_table[crc & 0xFF] ^ (crc >> 8);
crc = rhash_crc32_table[crc & 0xFF] ^ (crc >> 8);
crc ^= le2me_32( ((const unsigned *)msg)[1] );
crc = rhash_crc32_table[crc & 0xFF] ^ (crc >> 8);
crc = rhash_crc32_table[crc & 0xFF] ^ (crc >> 8);
crc = rhash_crc32_table[crc & 0xFF] ^ (crc >> 8);
crc = rhash_crc32_table[crc & 0xFF] ^ (crc >> 8);
crc ^= le2me_32( ((const unsigned *)msg)[2] );
crc = rhash_crc32_table[crc & 0xFF] ^ (crc >> 8);
crc = rhash_crc32_table[crc & 0xFF] ^ (crc >> 8);
crc = rhash_crc32_table[crc & 0xFF] ^ (crc >> 8);
crc = rhash_crc32_table[crc & 0xFF] ^ (crc >> 8);
crc ^= le2me_32( ((const unsigned *)msg)[3] );
crc = rhash_crc32_table[crc & 0xFF] ^ (crc >> 8);
crc = rhash_crc32_table[crc & 0xFF] ^ (crc >> 8);
crc = rhash_crc32_table[crc & 0xFF] ^ (crc >> 8);
crc = rhash_crc32_table[crc & 0xFF] ^ (crc >> 8);
}
/* process not aligned message tail */
for (e = msg + (size & 15); msg < e; msg++) {
crc = rhash_crc32_table[(crc ^ *msg) & 0xFF] ^ (crc >> 8);
}
return (crc ^ 0xFFFFFFFF);
}
/* crc32.h */
#ifndef CRC32_H
#define CRC32_H
#ifdef __cplusplus
extern "C" {
#endif
/* hash functions */
unsigned rhash_get_crc32(unsigned crcinit, const unsigned char* msg, size_t size);
unsigned rhash_get_crc32_str(unsigned crcinit, const char* str);
#ifdef GENERATE_CRC32_TABLE
void rhash_crc32_init_table(void); /* initialize algorithm static data */
#endif
#ifdef __cplusplus
} /* extern "C" */
#endif /* __cplusplus */
#endif /* CRC32_H */
......@@ -4,6 +4,7 @@ use strict;
use warnings;
my @vals = (qw(
CRC32
MD5
SHA1
SHA224
......
# looks like -*- vcl -*-
varnishtest "CRC32 checksum"
# VMODs blobcode and blob must be installed
varnish v1 -vcl {
import blobdigest from "${vmod_topbuild}/src/.libs/libvmod_blobdigest.so";
import blobcode;
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new a = blobcode.blob(IDENTITY, "a");
new msg = blobcode.blob(IDENTITY, "message");
new alphalc = blobcode.blob(IDENTITY,
"abcdefghijklmnopqrstuvwxyz");
new empty = blobcode.blob(IDENTITY, "");
new alphauc = blobcode.blob(IDENTITY,
"ABCDEFGHIJKLMNOPQRSTUVWXYZ");
new digits = blobcode.blob(IDENTITY, "1234567890");
new pangram =
blobcode.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 = blobcode.blob(BASE64,
"AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+Pw==");
new b64to127 = blobcode.blob(BASE64,
"QEFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaW1xdXl9gYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXp7fH1+fw==");
new b128to191 = blobcode.blob(BASE64,
"gIGCg4SFhoeIiYqLjI2Oj5CRkpOUlZaXmJmam5ydnp+goaKjpKWmp6ipqqusra6vsLGys7S1tre4ubq7vL2+vw==");
new b192to255 = blobcode.blob(BASE64,
"wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+/w==");
new d1 = blobdigest.digest(CRC32);
new d2 = blobdigest.digest(CRC32);
new d3 = blobdigest.digest(CRC32, a.get());
new d4 = blobdigest.digest(CRC32, msg.get());
new d5 = blobdigest.digest(CRC32, alphalc.get());
new d7 = blobdigest.digest(CRC32, alphauc.get());
new d8 = blobdigest.digest(CRC32, digits.get());
new d9 = blobdigest.digest(CRC32, pangram.get());
new d11 = blobdigest.digest(CRC32, 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 = blobcode.encode(HEXUC, d1.final());
if (!d2.update(a.get())) {
set resp.status = 500;
return(deliver);
}
set resp.http.a = blobcode.encode(HEXUC, d2.final());
if (!d3.update(blobcode.decode(IDENTITY, "b"))) {
set resp.status = 500;
return(deliver);
}
if (!d3.update(blobcode.decode(IDENTITY, "c"))) {
set resp.status = 500;
return(deliver);
}
set resp.http.abc = blobcode.encode(HEXUC, d3.final());
if (!d4.update(blobcode.decode(IDENTITY, " "))) {
set resp.status = 500;
return(deliver);
}
if (!d4.update(blobcode.decode(IDENTITY, "digest"))) {
set resp.status = 500;
return(deliver);
}
set resp.http.msgdigest = blobcode.encode(HEXUC, d4.final());
if (!d5.update(blobcode.decode(IDENTITY, ""))) {
set resp.status = 500;
return(deliver);
}
set resp.http.alphalc = blobcode.encode(HEXUC, d5.final());
if (!d7.update(alphalc.get())) {
set resp.status = 500;
return(deliver);
}
if (!d7.update(blobcode.decode(IDENTITY, "0123456789"))) {
set resp.status = 500;
return(deliver);
}
set resp.http.alphanum = blobcode.encode(HEXUC, d7.final());
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 = blobcode.encode(HEXUC, d8.final());
set resp.http.pangram = blobcode.encode(HEXUC, d9.final());
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 = blobcode.encode(HEXUC, d11.final());
# Tests for the hash() function
set resp.http.emptyf
= blobcode.encode(HEXUC, blobdigest.hash(CRC32, empty.get()));
set resp.http.af
= blobcode.encode(HEXUC, blobdigest.hash(CRC32,
blobcode.decode(IDENTITY, "a")));
set resp.http.abcf
= blobcode.encode(HEXUC, blobdigest.hash(CRC32,
blobcode.decode(IDENTITY, "abc")));
set resp.http.msgdigestf
= blobcode.encode(HEXUC, blobdigest.hash(CRC32,
blobcode.decode(IDENTITY,
"message digest")));
set resp.http.alphalcf
= blobcode.encode(HEXUC, blobdigest.hash(CRC32,
blobcode.decode(IDENTITY,
"abcdefghijklmnopqrstuvwxyz")));
set resp.http.alphanumf
= blobcode.encode(HEXUC, blobdigest.hash(CRC32,
blobcode.decode(IDENTITY,
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")));
set resp.http.digitsf
= blobcode.encode(HEXUC, blobdigest.hash(CRC32,
blobcode.decode(IDENTITY,
"12345678901234567890123456789012345678901234567890123456789012345678901234567890")));
set resp.http.pangramf
= blobcode.encode(HEXUC, blobdigest.hash(CRC32,
blobcode.decode(IDENTITY,
"The quick brown fox jumps over the lazy dog")));
# all 256 byte values in ascending order
set resp.http.allbytesf
= blobcode.encode(HEXUC, blobdigest.hash(CRC32,
blobcode.decode(BASE64,
"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.a == "E8B7BE43"
expect resp.http.abc == "352441C2"
expect resp.http.msgdigest == "20159D7F"
expect resp.http.alphalc == "4C2750BD"
expect resp.http.alphanum == "1FC2E6D2"
expect resp.http.digits == "7CA94A72"
expect resp.http.pangram == "414FA339"
expect resp.http.emptyf == "00000000"
expect resp.http.af == "E8B7BE43"
expect resp.http.abcf == "352441C2"
expect resp.http.msgdigestf == "20159D7F"
expect resp.http.alphalcf == "4C2750BD"
expect resp.http.alphanumf == "1FC2E6D2"
expect resp.http.digitsf == "7CA94A72"
expect resp.http.pangramf == "414FA339"
# verified with: base64 -d | rhash -C -
expect resp.http.allbytes == "29058C73"
expect resp.http.allbytesf == "29058C73"
} -run
......@@ -40,6 +40,8 @@
#include "vcc_if.h"
#include "vmod_blobdigest.h"
#include "byte_order.h"
#define ERR(ctx, msg) \
errmsg((ctx), "vmod blobdigest error: " msg)
......@@ -105,6 +107,9 @@ static void
init(const enum algorithm hash, hash_ctx * const hctx)
{
switch(hash) {
case CRC32:
hctx->crc32 = 0;
break;
case MD5:
rhash_md5_init(&hctx->md5);
break;
......@@ -145,6 +150,9 @@ update(const enum algorithm hash, hash_ctx *restrict const hctx,
const uint8_t *restrict const msg, const size_t len)
{
switch(hash) {
case CRC32:
hctx->crc32 = rhash_get_crc32(hctx->crc32, msg, len);
break;
case MD5:
rhash_md5_update(&hctx->md5, msg, len);
break;
......@@ -177,6 +185,9 @@ final(const enum algorithm hash, hash_ctx *restrict const hctx,
uint8_t *restrict result)
{
switch(hash) {
case CRC32:
be32_copy(result, 0, &hctx->crc32, sizeof(uint32_t));
break;
case MD5:
rhash_md5_final(&hctx->md5, result);
break;
......
......@@ -28,6 +28,7 @@
#include <sys/types.h>
#include "parse_algorithm.h"
#include "crc32.h"
#include "md5.h"
#include "sha1.h"
#include "vsha256.h"
......@@ -38,6 +39,7 @@
#define SHA3_BLOCKSZ(bits) ((1600 - (bits) * 2) / 8)
typedef union hash_ctx {
uint32_t crc32;
md5_ctx md5;
sha1_ctx sha1;
sha256_ctx sha224;
......@@ -50,6 +52,10 @@ static const struct hashspec {
const size_t digestsz;
const size_t blocksz;
} hashspec[] = {
[CRC32] = {
sizeof(uint32_t),
sizeof(uint32_t),
},
[MD5] = {
md5_hash_size,
md5_block_size,
......
......@@ -7,7 +7,7 @@
# See LICENSE
#
$Module blobdigest 3 digests and hmacs for the VCL blob type
$Module blobdigest 3 digests, checksums and hmacs for the VCL blob type
::
......@@ -23,9 +23,9 @@ $Module blobdigest 3 digests and hmacs for the VCL blob type
DESCRIPTION
===========
This Varnish Module (VMOD) generates message digests and keyed-hash
message authentication codes (HMACs) using the VCL data type BLOB,
which may contain arbitrary data of any length.
This Varnish Module (VMOD) generates message digests, keyed-hash
message authentication codes (HMACs) and checksums using the VCL data
type BLOB, which may contain arbitrary data of any length.
Currently (in Varnish versions through 5.0), BLOBs may only be used in
VCL as arguments of VMOD functions, so this VMOD must be used in
......@@ -173,6 +173,7 @@ HASH ALGORITHMS
The ``hash`` enum in the following can have one of the following
values:
* ``CRC32`` (not for HMACs)
* ``MD5``
* ``SHA1``
* ``SHA224``
......@@ -184,8 +185,8 @@ values:
* ``SHA3_384``
* ``SHA3_512``
$Object digest(ENUM {MD5, SHA1, SHA224, SHA256, SHA384, SHA512, SHA3_224,
SHA3_256, SHA3_384, SHA3_512} hash, BLOB init=0)
$Object digest(ENUM {CRC32, MD5, SHA1, SHA224, SHA256, SHA384, SHA512, SHA3_224,
SHA3_256, SHA3_384, SHA3_512} hash, BLOB init=0)
Prototype
new OBJ = blobdigest.digest(ENUM hash[, BLOB init])
......@@ -348,8 +349,9 @@ 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 {MD5, SHA1, SHA224, SHA256, SHA384, SHA512, SHA3_224,
SHA3_256, SHA3_384, SHA3_512} hash, BLOB msg)
$Function BLOB hash(ENUM {CRC32, MD5, 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``.
......
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