...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package verify
18
19 import (
20 "bytes"
21 "encoding/hex"
22 "errors"
23 "fmt"
24 "hash"
25 "io"
26
27 "github.com/google/go-containerregistry/internal/and"
28 v1 "github.com/google/go-containerregistry/pkg/v1"
29 )
30
31
32 const SizeUnknown = -1
33
34 type verifyReader struct {
35 inner io.Reader
36 hasher hash.Hash
37 expected v1.Hash
38 gotSize, wantSize int64
39 }
40
41
42 type Error struct {
43 got string
44 want v1.Hash
45 gotSize int64
46 }
47
48 func (v Error) Error() string {
49 return fmt.Sprintf("error verifying %s checksum after reading %d bytes; got %q, want %q",
50 v.want.Algorithm, v.gotSize, v.got, v.want)
51 }
52
53
54 func (vc *verifyReader) Read(b []byte) (int, error) {
55 n, err := vc.inner.Read(b)
56 vc.gotSize += int64(n)
57 if err == io.EOF {
58 if vc.wantSize != SizeUnknown && vc.gotSize != vc.wantSize {
59 return n, fmt.Errorf("error verifying size; got %d, want %d", vc.gotSize, vc.wantSize)
60 }
61 got := hex.EncodeToString(vc.hasher.Sum(nil))
62 if want := vc.expected.Hex; got != want {
63 return n, Error{
64 got: vc.expected.Algorithm + ":" + got,
65 want: vc.expected,
66 gotSize: vc.gotSize,
67 }
68 }
69 }
70 return n, err
71 }
72
73
74
75
76
77
78
79
80
81
82 func ReadCloser(r io.ReadCloser, size int64, h v1.Hash) (io.ReadCloser, error) {
83 w, err := v1.Hasher(h.Algorithm)
84 if err != nil {
85 return nil, err
86 }
87 r2 := io.TeeReader(r, w)
88 if size != SizeUnknown {
89 r2 = io.LimitReader(r2, size)
90 }
91 return &and.ReadCloser{
92 Reader: &verifyReader{
93 inner: r2,
94 hasher: w,
95 expected: h,
96 wantSize: size,
97 },
98 CloseFunc: r.Close,
99 }, nil
100 }
101
102
103
104
105 func Descriptor(d v1.Descriptor) error {
106 if d.Data == nil {
107 return errors.New("error verifying descriptor; Data == nil")
108 }
109
110 h, sz, err := v1.SHA256(bytes.NewReader(d.Data))
111 if err != nil {
112 return err
113 }
114 if h != d.Digest {
115 return fmt.Errorf("error verifying Digest; got %q, want %q", h, d.Digest)
116 }
117 if sz != d.Size {
118 return fmt.Errorf("error verifying Size; got %d, want %d", sz, d.Size)
119 }
120
121 return nil
122 }
123
View as plain text