Skip to content

Commit e5d5e74

Browse files
committed
crypto: xxhash
1 parent bc94f29 commit e5d5e74

File tree

6 files changed

+251
-2
lines changed

6 files changed

+251
-2
lines changed

Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ download-sqlite:
2828
mv sqlite-amalgamation-$(SQLITE_VERSION)/* src
2929

3030
download-external:
31-
curl -L https://github.com/mackyle/sqlite/raw/branch-$(SQLITE_BRANCH)/src/test_windirent.h --output src/test_windirent.h
31+
curl -L --silent https://github.com/mackyle/sqlite/raw/branch-$(SQLITE_BRANCH)/src/test_windirent.h --output src/test_windirent.h
32+
curl -L --silent https://github.com/cyan4973/xxhash/raw/v0.8.3/xxhash.h --output src/crypto/xxhash.impl.h
3233

3334
compile-linux:
3435
$(CC) -O1 $(LINIX_FLAGS) src/sqlite3-crypto.c src/crypto/*.c -o dist/crypto.so

docs/crypto.md

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,11 @@ Each hash function expects `data` to be TEXT or BLOB. Returns a BLOB hash. Use t
1515
[sha1](#crypto_sha1)
1616
[sha256](#crypto_sha256)
1717
[sha384](#crypto_sha384)
18-
[sha512](#crypto_sha512)
18+
[sha512](#crypto_sha512)
19+
[xxh32](#crypto_xxh32)
20+
[xxh64](#crypto_xxh64)
21+
[xxh3_64](#crypto_xxh3_64)
22+
[xxh3_128](#crypto_xxh3_128)
1923

2024
### crypto_blake3
2125

@@ -95,6 +99,58 @@ select hex(crypto_sha512('abc'));
9599
-- DDAF35A193617ABACC417349AE20413112E6FA4E89A97EA20A9EEEE64B55D39A2192992A274FC1A836BA3C23A3FEEBBD454D4423643CE80E2A9AC94FA54CA49F
96100
```
97101

102+
### crypto_xxh32
103+
104+
```text
105+
crypto_xxh32(data)
106+
```
107+
108+
Returns a XXH32 hash of the data as a blob.
109+
110+
```sql
111+
select hex(crypto_xxh32('abc'));
112+
-- 32D153FF
113+
```
114+
115+
### crypto_xx64
116+
117+
```text
118+
crypto_xx64(data)
119+
```
120+
121+
Returns a XXH64 hash of the data as a blob.
122+
123+
```sql
124+
select hex(crypto_xx64('abc'));
125+
-- 44BC2CF5AD770999
126+
```
127+
128+
### crypto_xxh3_64
129+
130+
```text
131+
crypto_xxh3_64(data)
132+
```
133+
134+
Returns a XXH3_64 hash of the data as a blob.
135+
136+
```sql
137+
select hex(crypto_xxh3_64('abc'));
138+
-- 78AF5F94892F3950
139+
```
140+
141+
### crypto_xxh3_128
142+
143+
```text
144+
crypto_xxh3_128(data)
145+
```
146+
147+
Returns a XXH3_128 hash of the data as a blob.
148+
149+
```sql
150+
select hex(crypto_xxh3_128('abc'));
151+
-- 06B05AB6733A618578AF5F94892F3950
152+
```
153+
98154
## Encoding and decoding functions
99155

100156
```text

src/crypto/extension.c

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ SQLITE_EXTENSION_INIT3
2020
#include "crypto/sha1.h"
2121
#include "crypto/sha2.h"
2222
#include "crypto/url.h"
23+
#include "crypto/xxhash.h"
2324

2425
// encoder/decoder function
2526
typedef uint8_t* (*encdec_fn)(const uint8_t* src, size_t len, size_t* out_len);
@@ -56,6 +57,30 @@ static void crypto_hash(sqlite3_context* context, int argc, sqlite3_value** argv
5657
final_func = (void*)md5_final;
5758
algo = 1;
5859
break;
60+
case 1032: /* XXH32 */
61+
init_func = (void*)xxh32_init;
62+
update_func = (void*)xxh32_update;
63+
final_func = (void*)xxh32_final;
64+
algo = 1;
65+
break;
66+
case 1064: /* XXH64 */
67+
init_func = (void*)xxh64_init;
68+
update_func = (void*)xxh64_update;
69+
final_func = (void*)xxh64_final;
70+
algo = 1;
71+
break;
72+
case 3064: /* XXH3 64-bit */
73+
init_func = (void*)xxh3_64_init;
74+
update_func = (void*)xxh3_64_update;
75+
final_func = (void*)xxh3_64_final;
76+
algo = 1;
77+
break;
78+
case 3128: /* XXH3 128-bit */
79+
init_func = (void*)xxh3_128_init;
80+
update_func = (void*)xxh3_128_update;
81+
final_func = (void*)xxh3_128_final;
82+
algo = 1;
83+
break;
5984
case 2256: /* SHA2-256 */
6085
init_func = (void*)sha256_init;
6186
update_func = (void*)sha256_update;
@@ -216,6 +241,14 @@ int crypto_init(sqlite3* db) {
216241
sqlite3_create_function(db, "sha384", 1, flags, (void*)2384, crypto_hash, 0, 0);
217242
sqlite3_create_function(db, "crypto_sha512", 1, flags, (void*)2512, crypto_hash, 0, 0);
218243
sqlite3_create_function(db, "sha512", 1, flags, (void*)2512, crypto_hash, 0, 0);
244+
sqlite3_create_function(db, "crypto_xxh32", 1, flags, (void*)1032, crypto_hash, 0, 0);
245+
sqlite3_create_function(db, "xxh32", 1, flags, (void*)1032, crypto_hash, 0, 0);
246+
sqlite3_create_function(db, "crypto_xxh64", 1, flags, (void*)1064, crypto_hash, 0, 0);
247+
sqlite3_create_function(db, "xxh64", 1, flags, (void*)1064, crypto_hash, 0, 0);
248+
sqlite3_create_function(db, "crypto_xxh3_64", 1, flags, (void*)3064, crypto_hash, 0, 0);
249+
sqlite3_create_function(db, "xxh3_64", 1, flags, (void*)3064, crypto_hash, 0, 0);
250+
sqlite3_create_function(db, "crypto_xxh3_128", 1, flags, (void*)3128, crypto_hash, 0, 0);
251+
sqlite3_create_function(db, "xxh3_128", 1, flags, (void*)3128, crypto_hash, 0, 0);
219252

220253
sqlite3_create_function(db, "crypto_encode", 2, flags, 0, crypto_encode, 0, 0);
221254
sqlite3_create_function(db, "encode", 2, flags, 0, crypto_encode, 0, 0);

src/crypto/xxhash.c

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
// Copyright (c) 2025 Anton Zhiyanov, MIT License
2+
// https://github.com/nalgeon/sqlean
3+
4+
#include <stddef.h>
5+
#include <stdint.h>
6+
#include <string.h>
7+
8+
#define XXH_STATIC_LINKING_ONLY
9+
#define XXH_IMPLEMENTATION
10+
#include "crypto/xxhash.h"
11+
#include "crypto/xxhash.impl.h"
12+
13+
#define XXH32_DIGEST_LENGTH 4
14+
#define XXH64_DIGEST_LENGTH 8
15+
#define XXH128_DIGEST_LENGTH 16
16+
17+
// XXH32.
18+
19+
void* xxh32_init() {
20+
XXH32_state_t* ctx = XXH32_createState();
21+
if (!ctx) {
22+
return NULL;
23+
}
24+
XXH32_reset(ctx, 0);
25+
return ctx;
26+
}
27+
28+
void xxh32_update(XXH32_state_t* ctx, const void* data, size_t len) {
29+
XXH32_update(ctx, data, len);
30+
}
31+
32+
int xxh32_final(XXH32_state_t* ctx, uint8_t* hash) {
33+
XXH32_hash_t digest = XXH32_digest(ctx);
34+
XXH32_canonical_t cano;
35+
XXH32_canonicalFromHash(&cano, digest);
36+
memcpy(hash, cano.digest, XXH32_DIGEST_LENGTH);
37+
XXH32_freeState(ctx);
38+
return XXH32_DIGEST_LENGTH;
39+
}
40+
41+
// XXH64.
42+
43+
void* xxh64_init() {
44+
XXH64_state_t* ctx = XXH64_createState();
45+
if (!ctx) {
46+
return NULL;
47+
}
48+
XXH64_reset(ctx, 0);
49+
return ctx;
50+
}
51+
52+
void xxh64_update(XXH64_state_t* ctx, const void* data, size_t len) {
53+
XXH64_update(ctx, data, len);
54+
}
55+
56+
int xxh64_final(XXH64_state_t* ctx, uint8_t* hash) {
57+
XXH64_hash_t digest = XXH64_digest(ctx);
58+
XXH64_canonical_t cano;
59+
XXH64_canonicalFromHash(&cano, digest);
60+
memcpy(hash, cano.digest, XXH64_DIGEST_LENGTH);
61+
XXH64_freeState(ctx);
62+
return XXH64_DIGEST_LENGTH;
63+
}
64+
65+
// XXH3 64-bit.
66+
67+
void* xxh3_64_init() {
68+
XXH3_state_t* ctx = XXH3_createState();
69+
if (!ctx) {
70+
return NULL;
71+
}
72+
XXH3_64bits_reset(ctx);
73+
return ctx;
74+
}
75+
76+
void xxh3_64_update(XXH3_state_t* ctx, const void* data, size_t len) {
77+
XXH3_64bits_update(ctx, data, len);
78+
}
79+
80+
int xxh3_64_final(XXH3_state_t* ctx, uint8_t* hash) {
81+
uint64_t digest = XXH3_64bits_digest(ctx);
82+
XXH64_canonical_t cano;
83+
XXH64_canonicalFromHash(&cano, digest);
84+
memcpy(hash, cano.digest, XXH64_DIGEST_LENGTH);
85+
XXH3_freeState(ctx);
86+
return XXH64_DIGEST_LENGTH;
87+
}
88+
89+
// XXH3 128-bit.
90+
91+
void* xxh3_128_init() {
92+
XXH3_state_t* ctx = XXH3_createState();
93+
if (!ctx) {
94+
return NULL;
95+
}
96+
XXH3_128bits_reset(ctx);
97+
return ctx;
98+
}
99+
100+
void xxh3_128_update(XXH3_state_t* ctx, const void* data, size_t len) {
101+
XXH3_128bits_update(ctx, data, len);
102+
}
103+
104+
int xxh3_128_final(XXH3_state_t* ctx, uint8_t* hash) {
105+
XXH128_hash_t digest = XXH3_128bits_digest(ctx);
106+
XXH128_canonical_t cano;
107+
XXH128_canonicalFromHash(&cano, digest);
108+
memcpy(hash, cano.digest, XXH128_DIGEST_LENGTH);
109+
XXH3_freeState(ctx);
110+
return XXH128_DIGEST_LENGTH;
111+
}

src/crypto/xxhash.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Copyright (c) 2025 Anton Zhiyanov, MIT License
2+
// https://github.com/nalgeon/sqlean
3+
4+
#ifndef __XXHASH3_H__
5+
#define __XXHASH3_H__
6+
7+
#include <stddef.h>
8+
#include <stdint.h>
9+
10+
#include "crypto/xxhash.impl.h"
11+
12+
void* xxh32_init();
13+
void xxh32_update(XXH32_state_t* ctx, const void* data, size_t len);
14+
int xxh32_final(XXH32_state_t* ctx, uint8_t* hash);
15+
16+
void* xxh64_init();
17+
void xxh64_update(XXH64_state_t* ctx, const void* data, size_t len);
18+
int xxh64_final(XXH64_state_t* ctx, uint8_t* hash);
19+
20+
void* xxh3_64_init();
21+
void xxh3_64_update(XXH3_state_t* ctx, const void* data, size_t len);
22+
int xxh3_64_final(XXH3_state_t* ctx, uint8_t* hash);
23+
24+
void* xxh3_128_init();
25+
void xxh3_128_update(XXH3_state_t* ctx, const void* data, size_t len);
26+
int xxh3_128_final(XXH3_state_t* ctx, uint8_t* hash);
27+
28+
#endif

test/crypto.sql

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,3 +147,23 @@ select '15_09', crypto_decode('<+ohcEHPu*CER),Dg-(An=QS8+DQ%9E-!.?G%G\:0f''qg@=!
147147
select '16_01', crypto_blake3(null) is NULL;
148148
select '16_02', hex(crypto_blake3('')) = upper('af1349b9f5f9a1a6a0404dea36dcc9499bcb25c9adc112b7cc9a93cae41f3262');
149149
select '16_03', hex(crypto_blake3('abc')) = upper('6437b3ac38465133ffb63b75273a8db548c558465d79db03fd359c6cd5bd9d85');
150+
151+
select '17_01', crypto_xxh32(null) is NULL;
152+
select '17_02', hex(crypto_xxh32('')) = '02CC5D05';
153+
select '17_03', hex(crypto_xxh32('abc')) = '32D153FF';
154+
select '17_04', hex(crypto_xxh32('The quick brown 🦊 jumps over 13 lazy 🐶.')) = '2C4A0402';
155+
156+
select '18_01', crypto_xxh64(null) is NULL;
157+
select '18_02', hex(crypto_xxh64('')) = 'EF46DB3751D8E999';
158+
select '18_03', hex(crypto_xxh64('abc')) = '44BC2CF5AD770999';
159+
select '18_04', hex(crypto_xxh64('The quick brown 🦊 jumps over 13 lazy 🐶.')) = '1ED3E109F48F652C';
160+
161+
select '19_01', crypto_xxh3_64(null) is NULL;
162+
select '19_02', hex(crypto_xxh3_64('')) = '2D06800538D394C2';
163+
select '19_03', hex(crypto_xxh3_64('abc')) = '78AF5F94892F3950';
164+
select '19_04', hex(crypto_xxh3_64('The quick brown 🦊 jumps over 13 lazy 🐶.')) = '09A3FF1CBDB28B84';
165+
166+
select '20_01', crypto_xxh3_128(null) is NULL;
167+
select '20_02', hex(crypto_xxh3_128('')) = '99AA06D3014798D86001C324468D497F';
168+
select '20_03', hex(crypto_xxh3_128('abc')) = '06B05AB6733A618578AF5F94892F3950';
169+
select '20_04', hex(crypto_xxh3_128('The quick brown 🦊 jumps over 13 lazy 🐶.')) = 'E688EC7B9C40A08C87C989C0484E449E';

0 commit comments

Comments
 (0)