Source file src/pkg/cmd/go/internal/tlog/tlog.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package tlog
16
17 import (
18 "crypto/sha256"
19 "encoding/base64"
20 "errors"
21 "fmt"
22 "math/bits"
23 )
24
25
26 type Hash [HashSize]byte
27
28
29 const HashSize = 32
30
31
32 func (h Hash) String() string {
33 return base64.StdEncoding.EncodeToString(h[:])
34 }
35
36
37 func (h Hash) MarshalJSON() ([]byte, error) {
38 return []byte(`"` + h.String() + `"`), nil
39 }
40
41
42 func (h *Hash) UnmarshalJSON(data []byte) error {
43 if len(data) != 1+44+1 || data[0] != '"' || data[len(data)-2] != '=' || data[len(data)-1] != '"' {
44 return errors.New("cannot decode hash")
45 }
46
47
48
49
50
51
52
53
54 var tmp Hash
55 n, err := base64.RawStdEncoding.Decode(tmp[:], data[1:len(data)-2])
56 if err != nil || n != HashSize {
57 return errors.New("cannot decode hash")
58 }
59 *h = tmp
60 return nil
61 }
62
63
64 func ParseHash(s string) (Hash, error) {
65 data, err := base64.StdEncoding.DecodeString(s)
66 if err != nil || len(data) != HashSize {
67 return Hash{}, fmt.Errorf("malformed hash")
68 }
69 var h Hash
70 copy(h[:], data)
71 return h, nil
72 }
73
74
75
76 func maxpow2(n int64) (k int64, l int) {
77 l = 0
78 for 1<<uint(l+1) < n {
79 l++
80 }
81 return 1 << uint(l), l
82 }
83
84 var zeroPrefix = []byte{0x00}
85
86
87 func RecordHash(data []byte) Hash {
88
89
90 h := sha256.New()
91 h.Write(zeroPrefix)
92 h.Write(data)
93 var h1 Hash
94 h.Sum(h1[:0])
95 return h1
96 }
97
98
99 func NodeHash(left, right Hash) Hash {
100
101
102
103
104 var buf [1 + HashSize + HashSize]byte
105 buf[0] = 0x01
106 copy(buf[1:], left[:])
107 copy(buf[1+HashSize:], right[:])
108 return sha256.Sum256(buf[:])
109 }
110
111
112
113
114
115
116
117
118
119
120
121 func StoredHashIndex(level int, n int64) int64 {
122
123
124
125 for l := level; l > 0; l-- {
126 n = 2*n + 1
127 }
128
129
130 i := int64(0)
131 for ; n > 0; n >>= 1 {
132 i += n
133 }
134
135 return i + int64(level)
136 }
137
138
139
140 func SplitStoredHashIndex(index int64) (level int, n int64) {
141
142
143
144 n = index / 2
145 indexN := StoredHashIndex(0, n)
146 if indexN > index {
147 panic("bad math")
148 }
149 for {
150
151 x := indexN + 1 + int64(bits.TrailingZeros64(uint64(n+1)))
152 if x > index {
153 break
154 }
155 n++
156 indexN = x
157 }
158
159
160 level = int(index - indexN)
161 return level, n >> uint(level)
162 }
163
164
165
166 func StoredHashCount(n int64) int64 {
167 if n == 0 {
168 return 0
169 }
170
171 numHash := StoredHashIndex(0, n-1) + 1
172
173 for i := uint64(n - 1); i&1 != 0; i >>= 1 {
174 numHash++
175 }
176 return numHash
177 }
178
179
180
181
182
183
184
185
186 func StoredHashes(n int64, data []byte, r HashReader) ([]Hash, error) {
187 return StoredHashesForRecordHash(n, RecordHash(data), r)
188 }
189
190
191
192 func StoredHashesForRecordHash(n int64, h Hash, r HashReader) ([]Hash, error) {
193
194 hashes := []Hash{h}
195
196
197
198
199 m := int(bits.TrailingZeros64(uint64(n + 1)))
200 indexes := make([]int64, m)
201 for i := 0; i < m; i++ {
202
203
204 indexes[m-1-i] = StoredHashIndex(i, n>>uint(i)-1)
205 }
206
207
208 old, err := r.ReadHashes(indexes)
209 if err != nil {
210 return nil, err
211 }
212 if len(old) != len(indexes) {
213 return nil, fmt.Errorf("tlog: ReadHashes(%d indexes) = %d hashes", len(indexes), len(old))
214 }
215
216
217 for i := 0; i < m; i++ {
218 h = NodeHash(old[m-1-i], h)
219 hashes = append(hashes, h)
220 }
221 return hashes, nil
222 }
223
224
225 type HashReader interface {
226
227
228
229
230
231 ReadHashes(indexes []int64) ([]Hash, error)
232 }
233
234
235 type HashReaderFunc func([]int64) ([]Hash, error)
236
237 func (f HashReaderFunc) ReadHashes(indexes []int64) ([]Hash, error) {
238 return f(indexes)
239 }
240
241
242
243
244
245
246 func TreeHash(n int64, r HashReader) (Hash, error) {
247 if n == 0 {
248 return Hash{}, nil
249 }
250 indexes := subTreeIndex(0, n, nil)
251 hashes, err := r.ReadHashes(indexes)
252 if err != nil {
253 return Hash{}, err
254 }
255 if len(hashes) != len(indexes) {
256 return Hash{}, fmt.Errorf("tlog: ReadHashes(%d indexes) = %d hashes", len(indexes), len(hashes))
257 }
258 hash, hashes := subTreeHash(0, n, hashes)
259 if len(hashes) != 0 {
260 panic("tlog: bad index math in TreeHash")
261 }
262 return hash, nil
263 }
264
265
266
267
268
269 func subTreeIndex(lo, hi int64, need []int64) []int64 {
270
271 for lo < hi {
272 k, level := maxpow2(hi - lo + 1)
273 if lo&(k-1) != 0 {
274 panic("tlog: bad math in subTreeIndex")
275 }
276 need = append(need, StoredHashIndex(level, lo>>uint(level)))
277 lo += k
278 }
279 return need
280 }
281
282
283
284
285
286 func subTreeHash(lo, hi int64, hashes []Hash) (Hash, []Hash) {
287
288
289
290
291 numTree := 0
292 for lo < hi {
293 k, _ := maxpow2(hi - lo + 1)
294 if lo&(k-1) != 0 || lo >= hi {
295 panic("tlog: bad math in subTreeHash")
296 }
297 numTree++
298 lo += k
299 }
300
301 if len(hashes) < numTree {
302 panic("tlog: bad index math in subTreeHash")
303 }
304
305
306 h := hashes[numTree-1]
307 for i := numTree - 2; i >= 0; i-- {
308 h = NodeHash(hashes[i], h)
309 }
310 return h, hashes[numTree:]
311 }
312
313
314
315 type RecordProof []Hash
316
317
318 func ProveRecord(t, n int64, r HashReader) (RecordProof, error) {
319 if t < 0 || n < 0 || n >= t {
320 return nil, fmt.Errorf("tlog: invalid inputs in ProveRecord")
321 }
322 indexes := leafProofIndex(0, t, n, nil)
323 if len(indexes) == 0 {
324 return RecordProof{}, nil
325 }
326 hashes, err := r.ReadHashes(indexes)
327 if err != nil {
328 return nil, err
329 }
330 if len(hashes) != len(indexes) {
331 return nil, fmt.Errorf("tlog: ReadHashes(%d indexes) = %d hashes", len(indexes), len(hashes))
332 }
333
334 p, hashes := leafProof(0, t, n, hashes)
335 if len(hashes) != 0 {
336 panic("tlog: bad index math in ProveRecord")
337 }
338 return p, nil
339 }
340
341
342
343
344
345 func leafProofIndex(lo, hi, n int64, need []int64) []int64 {
346
347 if !(lo <= n && n < hi) {
348 panic("tlog: bad math in leafProofIndex")
349 }
350 if lo+1 == hi {
351 return need
352 }
353 if k, _ := maxpow2(hi - lo); n < lo+k {
354 need = leafProofIndex(lo, lo+k, n, need)
355 need = subTreeIndex(lo+k, hi, need)
356 } else {
357 need = subTreeIndex(lo, lo+k, need)
358 need = leafProofIndex(lo+k, hi, n, need)
359 }
360 return need
361 }
362
363
364
365
366 func leafProof(lo, hi, n int64, hashes []Hash) (RecordProof, []Hash) {
367
368 if !(lo <= n && n < hi) {
369 panic("tlog: bad math in leafProof")
370 }
371
372 if lo+1 == hi {
373
374
375 return RecordProof{}, hashes
376 }
377
378
379
380 var p RecordProof
381 var th Hash
382 if k, _ := maxpow2(hi - lo); n < lo+k {
383
384 p, hashes = leafProof(lo, lo+k, n, hashes)
385 th, hashes = subTreeHash(lo+k, hi, hashes)
386 } else {
387
388 th, hashes = subTreeHash(lo, lo+k, hashes)
389 p, hashes = leafProof(lo+k, hi, n, hashes)
390 }
391 return append(p, th), hashes
392 }
393
394 var errProofFailed = errors.New("invalid transparency proof")
395
396
397
398 func CheckRecord(p RecordProof, t int64, th Hash, n int64, h Hash) error {
399 if t < 0 || n < 0 || n >= t {
400 return fmt.Errorf("tlog: invalid inputs in CheckRecord")
401 }
402 th2, err := runRecordProof(p, 0, t, n, h)
403 if err != nil {
404 return err
405 }
406 if th2 == th {
407 return nil
408 }
409 return errProofFailed
410 }
411
412
413
414
415 func runRecordProof(p RecordProof, lo, hi, n int64, leafHash Hash) (Hash, error) {
416
417 if !(lo <= n && n < hi) {
418 panic("tlog: bad math in runRecordProof")
419 }
420
421 if lo+1 == hi {
422
423
424 if len(p) != 0 {
425 return Hash{}, errProofFailed
426 }
427 return leafHash, nil
428 }
429
430 if len(p) == 0 {
431 return Hash{}, errProofFailed
432 }
433
434 k, _ := maxpow2(hi - lo)
435 if n < lo+k {
436 th, err := runRecordProof(p[:len(p)-1], lo, lo+k, n, leafHash)
437 if err != nil {
438 return Hash{}, err
439 }
440 return NodeHash(th, p[len(p)-1]), nil
441 } else {
442 th, err := runRecordProof(p[:len(p)-1], lo+k, hi, n, leafHash)
443 if err != nil {
444 return Hash{}, err
445 }
446 return NodeHash(p[len(p)-1], th), nil
447 }
448 }
449
450
451
452
453 type TreeProof []Hash
454
455
456
457 func ProveTree(t, n int64, h HashReader) (TreeProof, error) {
458 if t < 1 || n < 1 || n > t {
459 return nil, fmt.Errorf("tlog: invalid inputs in ProveTree")
460 }
461 indexes := treeProofIndex(0, t, n, nil)
462 if len(indexes) == 0 {
463 return TreeProof{}, nil
464 }
465 hashes, err := h.ReadHashes(indexes)
466 if err != nil {
467 return nil, err
468 }
469 if len(hashes) != len(indexes) {
470 return nil, fmt.Errorf("tlog: ReadHashes(%d indexes) = %d hashes", len(indexes), len(hashes))
471 }
472
473 p, hashes := treeProof(0, t, n, hashes)
474 if len(hashes) != 0 {
475 panic("tlog: bad index math in ProveTree")
476 }
477 return p, nil
478 }
479
480
481
482
483 func treeProofIndex(lo, hi, n int64, need []int64) []int64 {
484
485 if !(lo < n && n <= hi) {
486 panic("tlog: bad math in treeProofIndex")
487 }
488
489 if n == hi {
490 if lo == 0 {
491 return need
492 }
493 return subTreeIndex(lo, hi, need)
494 }
495
496 if k, _ := maxpow2(hi - lo); n <= lo+k {
497 need = treeProofIndex(lo, lo+k, n, need)
498 need = subTreeIndex(lo+k, hi, need)
499 } else {
500 need = subTreeIndex(lo, lo+k, need)
501 need = treeProofIndex(lo+k, hi, n, need)
502 }
503 return need
504 }
505
506
507
508
509 func treeProof(lo, hi, n int64, hashes []Hash) (TreeProof, []Hash) {
510
511 if !(lo < n && n <= hi) {
512 panic("tlog: bad math in treeProof")
513 }
514
515
516 if n == hi {
517 if lo == 0 {
518
519
520 return TreeProof{}, hashes
521 }
522 th, hashes := subTreeHash(lo, hi, hashes)
523 return TreeProof{th}, hashes
524 }
525
526
527
528 var p TreeProof
529 var th Hash
530 if k, _ := maxpow2(hi - lo); n <= lo+k {
531
532 p, hashes = treeProof(lo, lo+k, n, hashes)
533 th, hashes = subTreeHash(lo+k, hi, hashes)
534 } else {
535
536 th, hashes = subTreeHash(lo, lo+k, hashes)
537 p, hashes = treeProof(lo+k, hi, n, hashes)
538 }
539 return append(p, th), hashes
540 }
541
542
543
544 func CheckTree(p TreeProof, t int64, th Hash, n int64, h Hash) error {
545 if t < 1 || n < 1 || n > t {
546 return fmt.Errorf("tlog: invalid inputs in CheckTree")
547 }
548 h2, th2, err := runTreeProof(p, 0, t, n, h)
549 if err != nil {
550 return err
551 }
552 if th2 == th && h2 == h {
553 return nil
554 }
555 return errProofFailed
556 }
557
558
559
560
561
562 func runTreeProof(p TreeProof, lo, hi, n int64, old Hash) (Hash, Hash, error) {
563
564 if !(lo < n && n <= hi) {
565 panic("tlog: bad math in runTreeProof")
566 }
567
568
569 if n == hi {
570 if lo == 0 {
571 if len(p) != 0 {
572 return Hash{}, Hash{}, errProofFailed
573 }
574 return old, old, nil
575 }
576 if len(p) != 1 {
577 return Hash{}, Hash{}, errProofFailed
578 }
579 return p[0], p[0], nil
580 }
581
582 if len(p) == 0 {
583 return Hash{}, Hash{}, errProofFailed
584 }
585
586
587 k, _ := maxpow2(hi - lo)
588 if n <= lo+k {
589 oh, th, err := runTreeProof(p[:len(p)-1], lo, lo+k, n, old)
590 if err != nil {
591 return Hash{}, Hash{}, err
592 }
593 return oh, NodeHash(th, p[len(p)-1]), nil
594 } else {
595 oh, th, err := runTreeProof(p[:len(p)-1], lo+k, hi, n, old)
596 if err != nil {
597 return Hash{}, Hash{}, err
598 }
599 return NodeHash(p[len(p)-1], oh), NodeHash(p[len(p)-1], th), nil
600 }
601 }
602
View as plain text