diff options
| author | 2025-12-07 19:42:56 +0100 | |
|---|---|---|
| committer | 2025-12-07 19:43:28 +0100 | |
| commit | 9331455b902d2a853458f32806b624349a5e2405 (patch) | |
| tree | 3b0dc644add994ecc7473856df88cd9fdef91594 | |
| parent | 6b2edf74e4005a194546356c2141b7f09e013ca3 (diff) | |
| download | tweetpipe-9331455b902d2a853458f32806b624349a5e2405.tar.gz | |
Derive a per-chunk chunk_id-dependent key to prevent chunk reordering
| -rw-r--r-- | ext/tweetpwhash.c | 45 | ||||
| -rw-r--r-- | ext/tweetpwhash.h | 12 | ||||
| -rw-r--r-- | src/tweetpipe.c | 10 |
3 files changed, 65 insertions, 2 deletions
diff --git a/ext/tweetpwhash.c b/ext/tweetpwhash.c index cd738cf..ff7aed4 100644 --- a/ext/tweetpwhash.c +++ b/ext/tweetpwhash.c @@ -7,6 +7,7 @@ #define HB crypto_hash_BYTES #define BB crypto_hashblocks_BLOCKBYTES #define SB crypto_pwhash_SALTBYTES +#define CB crypto_kdf_CONTEXTBYTES typedef unsigned char u8; typedef unsigned long long u64; @@ -99,6 +100,50 @@ sv prf(u8 *out, const u8 *m, u64 mln, const u8 *k, u64 kln) chi(&c); chu(&c, ok, BB); chu(&c, ih, HB); chf(out, &c); } +sv hext(u8 *prk, const u8 *ikm, u64 ikmln) +{ + u64 i; + u8 s[HB]; + + FOR(i, HB) s[i] = 0; + prf(prk, ikm, ikmln, s, HB); +} + +sv hexp(u8 *out, u64 outln, const u8* prk, const u64 idx, const u8 *ctx) +{ + u64 l = 0, i = 0, j, bl; + u8 b[HB + CB + 8 + 1]; + + FOR(j, CB) b[HB + j] = ctx[j]; + ts64(b + HB + CB, idx); + + while (l < outln) { + b[HB + CB + 8] = ++i; + + if (i == 1) + prf(b, b + HB, CB + 8 + 1, prk, HB); + else + prf(b, b, HB + CB + 8 + 1, prk, HB); + + bl = MIN(HB, outln - l); + FOR(j, bl) out[l + j] = b[j]; + l += bl; + } +} + +int crypto_kdf(u8 *out, u64 outln, const u64 idx, const u8 *ctx, const u8 *ikm, u64 ikmln) +{ + u8 prk[HB]; + + if (outln > HB * 255) + return -1; + + hext(prk, ikm, ikmln); + hexp(out, outln, prk, idx, ctx); + + return 0; +} + int crypto_pwhash(u8 *out, u64 outln, const u8 *p, u64 pln, const u8 *s, u64 c) { u64 i, j, b, nb, bl, o; diff --git a/ext/tweetpwhash.h b/ext/tweetpwhash.h index 177c304..0514183 100644 --- a/ext/tweetpwhash.h +++ b/ext/tweetpwhash.h @@ -12,4 +12,16 @@ extern int crypto_pwhash_pbkdf2hmacsha512_tweet(unsigned char *,unsigned long lo #define crypto_pwhash_pbkdf2hmacsha512_SALTBYTES crypto_pwhash_pbkdf2hmacsha512_tweet_SALTBYTES #define crypto_pwhash_pbkdf2hmacsha512_VERSION crypto_pwhash_pbkdf2hmacsha512_tweet_VERSION #define crypto_pwhash_pbkdf2hmacsha512_IMPLEMENTATION "crypto_pwhash/pbkdf2hmacsha512/tweet" +#define crypto_kdf_PRIMITIVE "hkdfhmacsha512" +#define crypto_kdf crypto_kdf_hkdfhmacsha512 +#define crypto_kdf_CONTEXTBYTES crypto_kdf_hkdfhmacsha512_CONTEXTBYTES +#define crypto_kdf_IMPLEMENTATION crypto_kdf_hkdfhmacsha512_IMPLEMENTATION +#define crypto_kdf_VERSION crypto_kdf_hkdfhmacsha512_VERSION +#define crypto_kdf_hkdfhmacsha512_tweet_CONTEXTBYTES 8 +extern int crypto_kdf_hkdfhmacsha512_tweet(unsigned char *,unsigned long long,unsigned long long,const unsigned char *,const unsigned char *,unsigned long long); +#define crypto_kdf_hkdfhmacsha512_tweet_VERSION "-" +#define crypto_kdf_hkdfhmacsha512 crypto_kdf_hkdfhmacsha512_tweet +#define crypto_kdf_hkdfhmacsha512_CONTEXTBYTES crypto_kdf_hkdfhmacsha512_tweet_CONTEXTBYTES +#define crypto_kdf_hkdfhmacsha512_VERSION crypto_kdf_hkdfhmacsha512_tweet_VERSION +#define crypto_kdf_hkdfhmacsha512_IMPLEMENTATION "crypto_kdf/hkdfhmacsha512/tweet" #endif diff --git a/src/tweetpipe.c b/src/tweetpipe.c index e369f70..768faaf 100644 --- a/src/tweetpipe.c +++ b/src/tweetpipe.c @@ -70,6 +70,7 @@ stream_encrypt(Context *ctx) chunk_nonce + crypto_secretbox_NONCEBYTES - crypto_secretbox_BOXZEROBYTES; unsigned char *const chunk_msg = chunk_base + crypto_secretbox_ZEROBYTES; unsigned char nonce[crypto_secretbox_NONCEBYTES]; + unsigned char chunk_key[crypto_secretbox_KEYBYTES]; uint64_t chunk_id; ssize_t max_chunk_size; ssize_t chunk_size; @@ -109,6 +110,8 @@ stream_encrypt(Context *ctx) memzero(chunk_nonce, crypto_secretbox_NONCEBYTES - crypto_secretbox_BOXZEROBYTES + crypto_secretbox_ZEROBYTES); randombytes(nonce, crypto_secretbox_NONCEBYTES); + crypto_kdf(chunk_key, crypto_secretbox_KEYBYTES, chunk_id, (unsigned char *) "tweetkey", + ctx->key, crypto_secretbox_KEYBYTES); /* * encrypt with crypto_secretbox() * @@ -118,7 +121,7 @@ stream_encrypt(Context *ctx) * | 4 | 8 | 16 | 16 | chunk_size */ if (crypto_secretbox(chunk_base, chunk_base, chunk_size + crypto_secretbox_ZEROBYTES, nonce, - ctx->key) != 0) { + chunk_key) != 0) { die(0, "Encryption error"); } /* @@ -156,6 +159,7 @@ stream_decrypt(Context *ctx) chunk_nonce + crypto_secretbox_NONCEBYTES - crypto_secretbox_BOXZEROBYTES; unsigned char *const chunk_msg = chunk_base + crypto_secretbox_ZEROBYTES; unsigned char nonce[crypto_secretbox_NONCEBYTES]; + unsigned char chunk_key[crypto_secretbox_KEYBYTES]; uint64_t chunk_id; ssize_t readnb; ssize_t max_chunk_size; @@ -181,8 +185,10 @@ stream_decrypt(Context *ctx) } memcpy(nonce, chunk_nonce, crypto_secretbox_NONCEBYTES); memzero(chunk_nonce, crypto_secretbox_NONCEBYTES); + crypto_kdf(chunk_key, crypto_secretbox_KEYBYTES, chunk_id, (unsigned char *) "tweetkey", + ctx->key, crypto_secretbox_KEYBYTES); if (crypto_secretbox_open(chunk_base, chunk_base, chunk_size + crypto_secretbox_ZEROBYTES, - nonce, ctx->key) != 0) { + nonce, chunk_key) != 0) { printf("Unable to decrypt chunk #%" PRIu64 " - ", chunk_id); if (chunk_id == 0) { die(0, "Wrong password or key?"); |