From fce1819222261d4bc19c4e36e052fd76856ec4fe Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Mon, 25 May 2015 15:49:56 +0930 Subject: [PATCH] crypto/shachain: examples and some documentation. Signed-off-by: Rusty Russell --- ccan/crypto/shachain/_info | 30 ++++++++++ ccan/crypto/shachain/shachain.h | 101 +++++++++++++++++++++++++++++++- 2 files changed, 128 insertions(+), 3 deletions(-) diff --git a/ccan/crypto/shachain/_info b/ccan/crypto/shachain/_info index 7cbf02da..b4f8d818 100644 --- a/ccan/crypto/shachain/_info +++ b/ccan/crypto/shachain/_info @@ -12,6 +12,36 @@ * * License: BSD-MIT * Author: Rusty Russell + * + * Example: + * + * #include + * #include + * #include + * #include + * #include + * + * int main(int argc, char *argv[]) + * { + * size_t i, j, limit = 10; + * struct sha256 seed; + * + * if (argc < 2) + * errx(1, "Usage: %s []", argv[0]); + * sha256(&seed, argv[1], strlen(argv[1])); + * if (argv[2]) + * limit = atol(argv[2]); + * + * for (i = 0; i < limit; i++) { + * struct sha256 v; + * shachain_from_seed(&seed, i, &v); + * printf("%zu: ", i); + * for (j = 0; j < sizeof(v.u.u8); j++) + * printf("%02x", v.u.u8[j]); + * printf("\n"); + * } + * return 0; + * } */ int main(int argc, char *argv[]) { diff --git a/ccan/crypto/shachain/shachain.h b/ccan/crypto/shachain/shachain.h index f3c9ad70..4a3051e6 100644 --- a/ccan/crypto/shachain/shachain.h +++ b/ccan/crypto/shachain/shachain.h @@ -11,9 +11,45 @@ #define shachain_index_t uint64_t #endif +/** + * shachain_from_seed - Generate an unpredictable SHA from a seed value. + * @seed: (secret) seed value to use + * @index: index of value to generate. + * @hash: value generated + * + * There will be no way to derive the result from that generated for + * any *lesser* index. + * + * Example: + * #include + * + * static void next_hash(struct sha256 *hash) + * { + * static uint64_t index = 0; + * static struct sha256 seed; + * + * // First time, initialize seed. + * if (index == 0) { + * // DO NOT DO THIS! Very predictable! + * time_t now = time(NULL); + * memcpy(&seed, &now, sizeof(now)); + * } + * + * shachain_from_seed(&seed, index++, hash); + * } + */ void shachain_from_seed(const struct sha256 *seed, shachain_index_t index, struct sha256 *hash); +/** + * shachain - structure for recording/deriving incrementing chain members + * @max_index: maximum index value successfully shachain_add_hash()ed. + * @num_valid: number of known[] array valid. If non-zero, @max_index valid. + * @known: known values to allow us to derive those <= @max_index. + * + * This is sufficient storage to derive any shachain hash value previously + * added. + */ struct shachain { shachain_index_t max_index; unsigned int num_valid; @@ -23,11 +59,70 @@ struct shachain { } known[sizeof(shachain_index_t) * 8]; }; -void shachain_init(struct shachain *shachain); +/** + * shachain_init - initialize an shachain + * @chain: the chain to initialize + * + * Alternately, ensure that it's all zero. + */ +void shachain_init(struct shachain *chain); -bool shachain_add_hash(struct shachain *shachain, +/** + * shachain_add_hash - record the hash for the next index. + * @chain: the chain to add to + * @index: the index of the hash + * @hash: the hash value. + * + * You can only add index 0 (for a freshly initialized chain), or one more + * than the previously successfully added value. + * + * This can fail (return false without altering @chain) if the hash + * for this index isn't consistent with previous hashes (ie. wasn't + * generated from the same seed), though it can't always detect that. + * If the hash is inconsistent yet undetected, the next addition will + * fail. + * + * Example: + * static void next_hash(const struct sha256 *hash) + * { + * static uint64_t index = 0; + * static struct shachain chain; + * + * if (!shachain_add_hash(&chain, index++, hash)) + * errx(1, "Corrupted hash value?"); + * } + */ +bool shachain_add_hash(struct shachain *chain, shachain_index_t index, const struct sha256 *hash); -bool shachain_get_hash(const struct shachain *shachain, +/** + * shachain_get_hash - get the hash for a given index. + * @chain: the chain query + * @index: the index of the hash to get + * @hash: the hash value. + * + * This will return true and set @hash to that given in the successful + * shachain_get_hash() call for that index. If there was no + * successful shachain_get_hash() for that index, it will return + * false. + * + * Example: + * #include + * + * static void next_hash(const struct sha256 *hash) + * { + * static uint64_t index = 0; + * static struct shachain chain; + * + * if (!shachain_add_hash(&chain, index++, hash)) + * errx(1, "Corrupted hash value?"); + * else { + * struct sha256 check; + * assert(shachain_get_hash(&chain, index-1, &check)); + * assert(structeq(&check, hash)); + * } + * } + */ +bool shachain_get_hash(const struct shachain *chain, shachain_index_t index, struct sha256 *hash); #endif /* CCAN_CRYPTO_SHACHAIN_H */ -- 2.39.2