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>
10 #define SHACHAIN_BITS (sizeof(uint64_t) * 8)
14 * shachain_from_seed - Generate an unpredictable SHA from a seed value.
15 * @seed: (secret) seed value to use
16 * @index: index of value to generate (0 == seed)
17 * @hash: value generated
19 * There will be no way to derive the result from that generated for
20 * any *greater* index.
25 * static void next_hash(struct sha256 *hash)
27 * static uint64_t index = 0xFFFFFFFFFFFFFFFFULL;
28 * static struct sha256 seed;
30 * // First time, initialize seed.
31 * if (index == 0xFFFFFFFFFFFFFFFFULL) {
32 * // DO NOT DO THIS! Very predictable!
33 * time_t now = time(NULL);
34 * memcpy(&seed, &now, sizeof(now));
37 * shachain_from_seed(&seed, index--, hash);
40 void shachain_from_seed(const struct sha256 *seed, uint64_t index,
44 * shachain - structure for recording/deriving decrementing chain members
45 * @min_index: minimum index value successfully shachain_add_hash()ed.
46 * @num_valid: number of known[] array valid. If non-zero, @min_index valid.
47 * @known: known values to allow us to derive those >= @min_index.
49 * This is sufficient storage to derive any shachain hash value previously
54 unsigned int num_valid;
58 } known[SHACHAIN_BITS + 1];
62 * shachain_init - initialize an shachain
63 * @chain: the chain to initialize
65 * Alternately, ensure that it's all zero.
67 void shachain_init(struct shachain *chain);
70 * shachain_next_index - what's the next index I can add to the shachain?
73 * This returns 0xFFFFFFFFFFFFFFFF (for a freshly
74 * initialized chain), or one less than the previously successfully
77 uint64_t shachain_next_index(const struct shachain *chain);
80 * shachain_add_hash - record the hash for the next index.
81 * @chain: the chain to add to
82 * @index: the index of the hash
83 * @hash: the hash value.
85 * You can only add shachain_next_index(@chain).
87 * This can fail (return false without altering @chain) if the hash
88 * for this index isn't consistent with previous hashes (ie. wasn't
89 * generated from the same seed), though it can't always detect that.
90 * If the hash is inconsistent yet undetected, a future addition will
94 * static void next_hash(const struct sha256 *hash)
96 * static uint64_t index = 0xFFFFFFFFFFFFFFFFULL;
97 * static struct shachain chain;
99 * if (!shachain_add_hash(&chain, index--, hash))
100 * errx(1, "Corrupted hash value?");
103 bool shachain_add_hash(struct shachain *chain,
104 uint64_t index, const struct sha256 *hash);
107 * shachain_get_hash - get the hash for a given index.
108 * @chain: the chain query
109 * @index: the index of the hash to get
110 * @hash: the hash value.
112 * This will return true and set @hash to that given in the successful
113 * shachain_get_hash() call for that index. If there was no
114 * successful shachain_get_hash() for that index, it will return
118 * #include <ccan/structeq/structeq.h>
119 * // Defines sha256_eq
120 * STRUCTEQ_DEF(sha256, 0, u);
122 * static void next_hash(const struct sha256 *hash)
124 * static uint64_t index = 0xFFFFFFFFFFFFFFFFULL;
125 * static struct shachain chain;
127 * if (!shachain_add_hash(&chain, index--, hash))
128 * errx(1, "Corrupted hash value?");
130 * struct sha256 check;
131 * assert(shachain_get_hash(&chain, index+1, &check));
132 * assert(sha256_eq(&check, hash));
136 bool shachain_get_hash(const struct shachain *chain,
137 uint64_t index, struct sha256 *hash);
138 #endif /* CCAN_CRYPTO_SHACHAIN_H */