1 /* MIT (BSD) license - see LICENSE file for details */
2 #ifndef CCAN_CRYPTO_SHACHAIN_H
3 #define CCAN_CRYPTO_SHACHAIN_H
5 #include <ccan/crypto/sha256/sha256.h>
9 /* Useful for testing. */
10 #ifndef shachain_index_t
11 #define shachain_index_t uint64_t
15 * shachain_from_seed - Generate an unpredictable SHA from a seed value.
16 * @seed: (secret) seed value to use
17 * @index: index of value to generate (0 == seed)
18 * @hash: value generated
20 * There will be no way to derive the result from that generated for
21 * any *greater* index.
26 * static void next_hash(struct sha256 *hash)
28 * static uint64_t index = 0xFFFFFFFFFFFFFFFFULL;
29 * static struct sha256 seed;
31 * // First time, initialize seed.
32 * if (index == 0xFFFFFFFFFFFFFFFFULL) {
33 * // DO NOT DO THIS! Very predictable!
34 * time_t now = time(NULL);
35 * memcpy(&seed, &now, sizeof(now));
38 * shachain_from_seed(&seed, index--, hash);
41 void shachain_from_seed(const struct sha256 *seed, shachain_index_t index,
45 * shachain - structure for recording/deriving decrementing chain members
46 * @min_index: minimum index value successfully shachain_add_hash()ed.
47 * @num_valid: number of known[] array valid. If non-zero, @min_index valid.
48 * @known: known values to allow us to derive those >= @min_index.
50 * This is sufficient storage to derive any shachain hash value previously
54 shachain_index_t min_index;
55 unsigned int num_valid;
57 shachain_index_t index;
59 } known[sizeof(shachain_index_t) * 8 + 1];
63 * shachain_init - initialize an shachain
64 * @chain: the chain to initialize
66 * Alternately, ensure that it's all zero.
68 void shachain_init(struct shachain *chain);
71 * shachain_add_hash - record the hash for the next index.
72 * @chain: the chain to add to
73 * @index: the index of the hash
74 * @hash: the hash value.
76 * You can only add index 0xFFFFFFFFFFFFFFFF (for a freshly
77 * initialized chain), or one less than the previously successfully
80 * This can fail (return false without altering @chain) if the hash
81 * for this index isn't consistent with previous hashes (ie. wasn't
82 * generated from the same seed), though it can't always detect that.
83 * If the hash is inconsistent yet undetected, the next addition will
87 * static void next_hash(const struct sha256 *hash)
89 * static uint64_t index = 0xFFFFFFFFFFFFFFFFULL;
90 * static struct shachain chain;
92 * if (!shachain_add_hash(&chain, index--, hash))
93 * errx(1, "Corrupted hash value?");
96 bool shachain_add_hash(struct shachain *chain,
97 shachain_index_t index, const struct sha256 *hash);
100 * shachain_get_hash - get the hash for a given index.
101 * @chain: the chain query
102 * @index: the index of the hash to get
103 * @hash: the hash value.
105 * This will return true and set @hash to that given in the successful
106 * shachain_get_hash() call for that index. If there was no
107 * successful shachain_get_hash() for that index, it will return
111 * #include <ccan/structeq/structeq.h>
113 * static void next_hash(const struct sha256 *hash)
115 * static uint64_t index = 0xFFFFFFFFFFFFFFFFULL;
116 * static struct shachain chain;
118 * if (!shachain_add_hash(&chain, index--, hash))
119 * errx(1, "Corrupted hash value?");
121 * struct sha256 check;
122 * assert(shachain_get_hash(&chain, index+1, &check));
123 * assert(structeq(&check, hash));
127 bool shachain_get_hash(const struct shachain *chain,
128 shachain_index_t index, struct sha256 *hash);
129 #endif /* CCAN_CRYPTO_SHACHAIN_H */