Skip to content

Commit 4e9925d

Browse files
committed
tarsum: allow for alternate block ciphers
Not breaking the default cipher and algorithm for calculating checksums, but allow for using alternate block ciphers during the checksum calculation. Docker-DCO-1.1-Signed-off-by: Vincent Batts <vbatts@redhat.com> (github: vbatts)
1 parent db5edfb commit 4e9925d

File tree

2 files changed

+117
-29
lines changed

2 files changed

+117
-29
lines changed

pkg/tarsum/tarsum.go

Lines changed: 73 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -35,25 +35,35 @@ func NewTarSum(r io.Reader, dc bool, v Version) (TarSum, error) {
3535
return &tarSum{Reader: r, DisableCompression: dc, tarSumVersion: v}, nil
3636
}
3737

38+
// Create a new TarSum, providing a THash to use rather than the DefaultTHash
39+
func NewTarSumHash(r io.Reader, dc bool, v Version, tHash THash) (TarSum, error) {
40+
if _, ok := tarSumVersions[v]; !ok {
41+
return nil, ErrVersionNotImplemented
42+
}
43+
return &tarSum{Reader: r, DisableCompression: dc, tarSumVersion: v, tHash: tHash}, nil
44+
}
45+
3846
// TarSum is the generic interface for calculating fixed time
3947
// checksums of a tar archive
4048
type TarSum interface {
4149
io.Reader
4250
GetSums() FileInfoSums
4351
Sum([]byte) string
4452
Version() Version
53+
Hash() THash
4554
}
4655

4756
// tarSum struct is the structure for a Version0 checksum calculation
4857
type tarSum struct {
4958
io.Reader
5059
tarR *tar.Reader
5160
tarW *tar.Writer
52-
gz writeCloseFlusher
61+
writer writeCloseFlusher
5362
bufTar *bytes.Buffer
54-
bufGz *bytes.Buffer
63+
bufWriter *bytes.Buffer
5564
bufData []byte
5665
h hash.Hash
66+
tHash THash
5767
sums FileInfoSums
5868
fileCounter int64
5969
currentFile string
@@ -63,10 +73,36 @@ type tarSum struct {
6373
tarSumVersion Version // this field is not exported so it can not be mutated during use
6474
}
6575

76+
func (ts tarSum) Hash() THash {
77+
return ts.tHash
78+
}
79+
6680
func (ts tarSum) Version() Version {
6781
return ts.tarSumVersion
6882
}
6983

84+
// A hash.Hash type generator and its name
85+
type THash interface {
86+
Hash() hash.Hash
87+
Name() string
88+
}
89+
90+
// Convenience method for creating a THash
91+
func NewTHash(name string, h func() hash.Hash) THash {
92+
return simpleTHash{n: name, h: h}
93+
}
94+
95+
// TarSum default is "sha256"
96+
var DefaultTHash = NewTHash("sha256", sha256.New)
97+
98+
type simpleTHash struct {
99+
n string
100+
h func() hash.Hash
101+
}
102+
103+
func (sth simpleTHash) Name() string { return sth.n }
104+
func (sth simpleTHash) Hash() hash.Hash { return sth.h() }
105+
70106
func (ts tarSum) selectHeaders(h *tar.Header, v Version) (set [][2]string) {
71107
for _, elem := range [][2]string{
72108
{"name", h.Name},
@@ -113,25 +149,35 @@ func (ts *tarSum) encodeHeader(h *tar.Header) error {
113149
return nil
114150
}
115151

152+
func (ts *tarSum) initTarSum() error {
153+
ts.bufTar = bytes.NewBuffer([]byte{})
154+
ts.bufWriter = bytes.NewBuffer([]byte{})
155+
ts.tarR = tar.NewReader(ts.Reader)
156+
ts.tarW = tar.NewWriter(ts.bufTar)
157+
if !ts.DisableCompression {
158+
ts.writer = gzip.NewWriter(ts.bufWriter)
159+
} else {
160+
ts.writer = &nopCloseFlusher{Writer: ts.bufWriter}
161+
}
162+
if ts.tHash == nil {
163+
ts.tHash = DefaultTHash
164+
}
165+
ts.h = ts.tHash.Hash()
166+
ts.h.Reset()
167+
ts.first = true
168+
ts.sums = FileInfoSums{}
169+
return nil
170+
}
171+
116172
func (ts *tarSum) Read(buf []byte) (int, error) {
117-
if ts.gz == nil {
118-
ts.bufTar = bytes.NewBuffer([]byte{})
119-
ts.bufGz = bytes.NewBuffer([]byte{})
120-
ts.tarR = tar.NewReader(ts.Reader)
121-
ts.tarW = tar.NewWriter(ts.bufTar)
122-
if !ts.DisableCompression {
123-
ts.gz = gzip.NewWriter(ts.bufGz)
124-
} else {
125-
ts.gz = &nopCloseFlusher{Writer: ts.bufGz}
173+
if ts.writer == nil {
174+
if err := ts.initTarSum(); err != nil {
175+
return 0, err
126176
}
127-
ts.h = sha256.New()
128-
ts.h.Reset()
129-
ts.first = true
130-
ts.sums = FileInfoSums{}
131177
}
132178

133179
if ts.finished {
134-
return ts.bufGz.Read(buf)
180+
return ts.bufWriter.Read(buf)
135181
}
136182
if ts.bufData == nil {
137183
switch {
@@ -167,10 +213,10 @@ func (ts *tarSum) Read(buf []byte) (int, error) {
167213
if err := ts.tarW.Close(); err != nil {
168214
return 0, err
169215
}
170-
if _, err := io.Copy(ts.gz, ts.bufTar); err != nil {
216+
if _, err := io.Copy(ts.writer, ts.bufTar); err != nil {
171217
return 0, err
172218
}
173-
if err := ts.gz.Close(); err != nil {
219+
if err := ts.writer.Close(); err != nil {
174220
return 0, err
175221
}
176222
ts.finished = true
@@ -189,12 +235,12 @@ func (ts *tarSum) Read(buf []byte) (int, error) {
189235
return 0, err
190236
}
191237
ts.tarW.Flush()
192-
if _, err := io.Copy(ts.gz, ts.bufTar); err != nil {
238+
if _, err := io.Copy(ts.writer, ts.bufTar); err != nil {
193239
return 0, err
194240
}
195-
ts.gz.Flush()
241+
ts.writer.Flush()
196242

197-
return ts.bufGz.Read(buf)
243+
return ts.bufWriter.Read(buf)
198244
}
199245
return n, err
200246
}
@@ -210,26 +256,26 @@ func (ts *tarSum) Read(buf []byte) (int, error) {
210256
}
211257
ts.tarW.Flush()
212258

213-
// Filling the gz writter
214-
if _, err = io.Copy(ts.gz, ts.bufTar); err != nil {
259+
// Filling the output writer
260+
if _, err = io.Copy(ts.writer, ts.bufTar); err != nil {
215261
return 0, err
216262
}
217-
ts.gz.Flush()
263+
ts.writer.Flush()
218264

219-
return ts.bufGz.Read(buf)
265+
return ts.bufWriter.Read(buf)
220266
}
221267

222268
func (ts *tarSum) Sum(extra []byte) string {
223269
ts.sums.SortBySums()
224-
h := sha256.New()
270+
h := ts.tHash.Hash()
225271
if extra != nil {
226272
h.Write(extra)
227273
}
228274
for _, fis := range ts.sums {
229275
log.Debugf("-->%s<--", fis.Sum())
230276
h.Write([]byte(fis.Sum()))
231277
}
232-
checksum := ts.Version().String() + "+sha256:" + hex.EncodeToString(h.Sum(nil))
278+
checksum := ts.Version().String() + "+" + ts.tHash.Name() + ":" + hex.EncodeToString(h.Sum(nil))
233279
log.Debugf("checksum processed: %s", checksum)
234280
return checksum
235281
}

pkg/tarsum/tarsum_test.go

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,11 @@ package tarsum
33
import (
44
"bytes"
55
"compress/gzip"
6+
"crypto/md5"
67
"crypto/rand"
8+
"crypto/sha1"
79
"crypto/sha256"
10+
"crypto/sha512"
811
"encoding/hex"
912
"fmt"
1013
"io"
@@ -22,6 +25,7 @@ type testLayer struct {
2225
gzip bool
2326
tarsum string
2427
version Version
28+
hash THash
2529
}
2630

2731
var testLayers = []testLayer{
@@ -75,6 +79,31 @@ var testLayers = []testLayer{
7579
// this tar has newer of collider-1.tar, ensuring is has different hash
7680
filename: "testdata/collision/collision-3.tar",
7781
tarsum: "tarsum+sha256:f886e431c08143164a676805205979cd8fa535dfcef714db5515650eea5a7c0f"},
82+
{
83+
options: &sizedOptions{1, 1024 * 1024, false, false}, // a 1mb file (in memory)
84+
tarsum: "tarsum+md5:0d7529ec7a8360155b48134b8e599f53",
85+
hash: md5THash,
86+
},
87+
{
88+
options: &sizedOptions{1, 1024 * 1024, false, false}, // a 1mb file (in memory)
89+
tarsum: "tarsum+sha1:f1fee39c5925807ff75ef1925e7a23be444ba4df",
90+
hash: sha1Hash,
91+
},
92+
{
93+
options: &sizedOptions{1, 1024 * 1024, false, false}, // a 1mb file (in memory)
94+
tarsum: "tarsum+sha224:6319390c0b061d639085d8748b14cd55f697cf9313805218b21cf61c",
95+
hash: sha224Hash,
96+
},
97+
{
98+
options: &sizedOptions{1, 1024 * 1024, false, false}, // a 1mb file (in memory)
99+
tarsum: "tarsum+sha384:a578ce3ce29a2ae03b8ed7c26f47d0f75b4fc849557c62454be4b5ffd66ba021e713b48ce71e947b43aab57afd5a7636",
100+
hash: sha384Hash,
101+
},
102+
{
103+
options: &sizedOptions{1, 1024 * 1024, false, false}, // a 1mb file (in memory)
104+
tarsum: "tarsum+sha512:e9bfb90ca5a4dfc93c46ee061a5cf9837de6d2fdf82544d6460d3147290aecfabf7b5e415b9b6e72db9b8941f149d5d69fb17a394cbfaf2eac523bd9eae21855",
105+
hash: sha512Hash,
106+
},
78107
}
79108

80109
type sizedOptions struct {
@@ -203,6 +232,14 @@ func TestEmptyTar(t *testing.T) {
203232
}
204233
}
205234

235+
var (
236+
md5THash = NewTHash("md5", md5.New)
237+
sha1Hash = NewTHash("sha1", sha1.New)
238+
sha224Hash = NewTHash("sha224", sha256.New224)
239+
sha384Hash = NewTHash("sha384", sha512.New384)
240+
sha512Hash = NewTHash("sha512", sha512.New)
241+
)
242+
206243
func TestTarSums(t *testing.T) {
207244
for _, layer := range testLayers {
208245
var (
@@ -226,8 +263,13 @@ func TestTarSums(t *testing.T) {
226263
defer file.Close()
227264
}
228265

229-
// double negatives!
230-
ts, err := NewTarSum(fh, !layer.gzip, layer.version)
266+
var ts TarSum
267+
if layer.hash == nil {
268+
// double negatives!
269+
ts, err = NewTarSum(fh, !layer.gzip, layer.version)
270+
} else {
271+
ts, err = NewTarSumHash(fh, !layer.gzip, layer.version, layer.hash)
272+
}
231273
if err != nil {
232274
t.Errorf("%q :: %q", err, layer.filename)
233275
continue

0 commit comments

Comments
 (0)