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)
| ... | ... |
@@ -35,6 +35,14 @@ func NewTarSum(r io.Reader, dc bool, v Version) (TarSum, error) {
|
| 35 | 35 |
return &tarSum{Reader: r, DisableCompression: dc, tarSumVersion: v}, nil
|
| 36 | 36 |
} |
| 37 | 37 |
|
| 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 |
+ |
|
| 38 | 46 |
// TarSum is the generic interface for calculating fixed time |
| 39 | 47 |
// checksums of a tar archive |
| 40 | 48 |
type TarSum interface {
|
| ... | ... |
@@ -42,6 +50,7 @@ type TarSum interface {
|
| 42 | 42 |
GetSums() FileInfoSums |
| 43 | 43 |
Sum([]byte) string |
| 44 | 44 |
Version() Version |
| 45 |
+ Hash() THash |
|
| 45 | 46 |
} |
| 46 | 47 |
|
| 47 | 48 |
// tarSum struct is the structure for a Version0 checksum calculation |
| ... | ... |
@@ -49,11 +58,12 @@ type tarSum struct {
|
| 49 | 49 |
io.Reader |
| 50 | 50 |
tarR *tar.Reader |
| 51 | 51 |
tarW *tar.Writer |
| 52 |
- gz writeCloseFlusher |
|
| 52 |
+ writer writeCloseFlusher |
|
| 53 | 53 |
bufTar *bytes.Buffer |
| 54 |
- bufGz *bytes.Buffer |
|
| 54 |
+ bufWriter *bytes.Buffer |
|
| 55 | 55 |
bufData []byte |
| 56 | 56 |
h hash.Hash |
| 57 |
+ tHash THash |
|
| 57 | 58 |
sums FileInfoSums |
| 58 | 59 |
fileCounter int64 |
| 59 | 60 |
currentFile string |
| ... | ... |
@@ -63,10 +73,36 @@ type tarSum struct {
|
| 63 | 63 |
tarSumVersion Version // this field is not exported so it can not be mutated during use |
| 64 | 64 |
} |
| 65 | 65 |
|
| 66 |
+func (ts tarSum) Hash() THash {
|
|
| 67 |
+ return ts.tHash |
|
| 68 |
+} |
|
| 69 |
+ |
|
| 66 | 70 |
func (ts tarSum) Version() Version {
|
| 67 | 71 |
return ts.tarSumVersion |
| 68 | 72 |
} |
| 69 | 73 |
|
| 74 |
+// A hash.Hash type generator and its name |
|
| 75 |
+type THash interface {
|
|
| 76 |
+ Hash() hash.Hash |
|
| 77 |
+ Name() string |
|
| 78 |
+} |
|
| 79 |
+ |
|
| 80 |
+// Convenience method for creating a THash |
|
| 81 |
+func NewTHash(name string, h func() hash.Hash) THash {
|
|
| 82 |
+ return simpleTHash{n: name, h: h}
|
|
| 83 |
+} |
|
| 84 |
+ |
|
| 85 |
+// TarSum default is "sha256" |
|
| 86 |
+var DefaultTHash = NewTHash("sha256", sha256.New)
|
|
| 87 |
+ |
|
| 88 |
+type simpleTHash struct {
|
|
| 89 |
+ n string |
|
| 90 |
+ h func() hash.Hash |
|
| 91 |
+} |
|
| 92 |
+ |
|
| 93 |
+func (sth simpleTHash) Name() string { return sth.n }
|
|
| 94 |
+func (sth simpleTHash) Hash() hash.Hash { return sth.h() }
|
|
| 95 |
+ |
|
| 70 | 96 |
func (ts tarSum) selectHeaders(h *tar.Header, v Version) (set [][2]string) {
|
| 71 | 97 |
for _, elem := range [][2]string{
|
| 72 | 98 |
{"name", h.Name},
|
| ... | ... |
@@ -113,25 +149,35 @@ func (ts *tarSum) encodeHeader(h *tar.Header) error {
|
| 113 | 113 |
return nil |
| 114 | 114 |
} |
| 115 | 115 |
|
| 116 |
+func (ts *tarSum) initTarSum() error {
|
|
| 117 |
+ ts.bufTar = bytes.NewBuffer([]byte{})
|
|
| 118 |
+ ts.bufWriter = bytes.NewBuffer([]byte{})
|
|
| 119 |
+ ts.tarR = tar.NewReader(ts.Reader) |
|
| 120 |
+ ts.tarW = tar.NewWriter(ts.bufTar) |
|
| 121 |
+ if !ts.DisableCompression {
|
|
| 122 |
+ ts.writer = gzip.NewWriter(ts.bufWriter) |
|
| 123 |
+ } else {
|
|
| 124 |
+ ts.writer = &nopCloseFlusher{Writer: ts.bufWriter}
|
|
| 125 |
+ } |
|
| 126 |
+ if ts.tHash == nil {
|
|
| 127 |
+ ts.tHash = DefaultTHash |
|
| 128 |
+ } |
|
| 129 |
+ ts.h = ts.tHash.Hash() |
|
| 130 |
+ ts.h.Reset() |
|
| 131 |
+ ts.first = true |
|
| 132 |
+ ts.sums = FileInfoSums{}
|
|
| 133 |
+ return nil |
|
| 134 |
+} |
|
| 135 |
+ |
|
| 116 | 136 |
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}
|
|
| 137 |
+ if ts.writer == nil {
|
|
| 138 |
+ if err := ts.initTarSum(); err != nil {
|
|
| 139 |
+ return 0, err |
|
| 126 | 140 |
} |
| 127 |
- ts.h = sha256.New() |
|
| 128 |
- ts.h.Reset() |
|
| 129 |
- ts.first = true |
|
| 130 |
- ts.sums = FileInfoSums{}
|
|
| 131 | 141 |
} |
| 132 | 142 |
|
| 133 | 143 |
if ts.finished {
|
| 134 |
- return ts.bufGz.Read(buf) |
|
| 144 |
+ return ts.bufWriter.Read(buf) |
|
| 135 | 145 |
} |
| 136 | 146 |
if ts.bufData == nil {
|
| 137 | 147 |
switch {
|
| ... | ... |
@@ -167,10 +213,10 @@ func (ts *tarSum) Read(buf []byte) (int, error) {
|
| 167 | 167 |
if err := ts.tarW.Close(); err != nil {
|
| 168 | 168 |
return 0, err |
| 169 | 169 |
} |
| 170 |
- if _, err := io.Copy(ts.gz, ts.bufTar); err != nil {
|
|
| 170 |
+ if _, err := io.Copy(ts.writer, ts.bufTar); err != nil {
|
|
| 171 | 171 |
return 0, err |
| 172 | 172 |
} |
| 173 |
- if err := ts.gz.Close(); err != nil {
|
|
| 173 |
+ if err := ts.writer.Close(); err != nil {
|
|
| 174 | 174 |
return 0, err |
| 175 | 175 |
} |
| 176 | 176 |
ts.finished = true |
| ... | ... |
@@ -189,12 +235,12 @@ func (ts *tarSum) Read(buf []byte) (int, error) {
|
| 189 | 189 |
return 0, err |
| 190 | 190 |
} |
| 191 | 191 |
ts.tarW.Flush() |
| 192 |
- if _, err := io.Copy(ts.gz, ts.bufTar); err != nil {
|
|
| 192 |
+ if _, err := io.Copy(ts.writer, ts.bufTar); err != nil {
|
|
| 193 | 193 |
return 0, err |
| 194 | 194 |
} |
| 195 |
- ts.gz.Flush() |
|
| 195 |
+ ts.writer.Flush() |
|
| 196 | 196 |
|
| 197 |
- return ts.bufGz.Read(buf) |
|
| 197 |
+ return ts.bufWriter.Read(buf) |
|
| 198 | 198 |
} |
| 199 | 199 |
return n, err |
| 200 | 200 |
} |
| ... | ... |
@@ -210,18 +256,18 @@ func (ts *tarSum) Read(buf []byte) (int, error) {
|
| 210 | 210 |
} |
| 211 | 211 |
ts.tarW.Flush() |
| 212 | 212 |
|
| 213 |
- // Filling the gz writter |
|
| 214 |
- if _, err = io.Copy(ts.gz, ts.bufTar); err != nil {
|
|
| 213 |
+ // Filling the output writer |
|
| 214 |
+ if _, err = io.Copy(ts.writer, ts.bufTar); err != nil {
|
|
| 215 | 215 |
return 0, err |
| 216 | 216 |
} |
| 217 |
- ts.gz.Flush() |
|
| 217 |
+ ts.writer.Flush() |
|
| 218 | 218 |
|
| 219 |
- return ts.bufGz.Read(buf) |
|
| 219 |
+ return ts.bufWriter.Read(buf) |
|
| 220 | 220 |
} |
| 221 | 221 |
|
| 222 | 222 |
func (ts *tarSum) Sum(extra []byte) string {
|
| 223 | 223 |
ts.sums.SortBySums() |
| 224 |
- h := sha256.New() |
|
| 224 |
+ h := ts.tHash.Hash() |
|
| 225 | 225 |
if extra != nil {
|
| 226 | 226 |
h.Write(extra) |
| 227 | 227 |
} |
| ... | ... |
@@ -229,7 +275,7 @@ func (ts *tarSum) Sum(extra []byte) string {
|
| 229 | 229 |
log.Debugf("-->%s<--", fis.Sum())
|
| 230 | 230 |
h.Write([]byte(fis.Sum())) |
| 231 | 231 |
} |
| 232 |
- checksum := ts.Version().String() + "+sha256:" + hex.EncodeToString(h.Sum(nil)) |
|
| 232 |
+ checksum := ts.Version().String() + "+" + ts.tHash.Name() + ":" + hex.EncodeToString(h.Sum(nil)) |
|
| 233 | 233 |
log.Debugf("checksum processed: %s", checksum)
|
| 234 | 234 |
return checksum |
| 235 | 235 |
} |
| ... | ... |
@@ -3,8 +3,11 @@ package tarsum |
| 3 | 3 |
import ( |
| 4 | 4 |
"bytes" |
| 5 | 5 |
"compress/gzip" |
| 6 |
+ "crypto/md5" |
|
| 6 | 7 |
"crypto/rand" |
| 8 |
+ "crypto/sha1" |
|
| 7 | 9 |
"crypto/sha256" |
| 10 |
+ "crypto/sha512" |
|
| 8 | 11 |
"encoding/hex" |
| 9 | 12 |
"fmt" |
| 10 | 13 |
"io" |
| ... | ... |
@@ -22,6 +25,7 @@ type testLayer struct {
|
| 22 | 22 |
gzip bool |
| 23 | 23 |
tarsum string |
| 24 | 24 |
version Version |
| 25 |
+ hash THash |
|
| 25 | 26 |
} |
| 26 | 27 |
|
| 27 | 28 |
var testLayers = []testLayer{
|
| ... | ... |
@@ -75,6 +79,31 @@ var testLayers = []testLayer{
|
| 75 | 75 |
// this tar has newer of collider-1.tar, ensuring is has different hash |
| 76 | 76 |
filename: "testdata/collision/collision-3.tar", |
| 77 | 77 |
tarsum: "tarsum+sha256:f886e431c08143164a676805205979cd8fa535dfcef714db5515650eea5a7c0f"}, |
| 78 |
+ {
|
|
| 79 |
+ options: &sizedOptions{1, 1024 * 1024, false, false}, // a 1mb file (in memory)
|
|
| 80 |
+ tarsum: "tarsum+md5:0d7529ec7a8360155b48134b8e599f53", |
|
| 81 |
+ hash: md5THash, |
|
| 82 |
+ }, |
|
| 83 |
+ {
|
|
| 84 |
+ options: &sizedOptions{1, 1024 * 1024, false, false}, // a 1mb file (in memory)
|
|
| 85 |
+ tarsum: "tarsum+sha1:f1fee39c5925807ff75ef1925e7a23be444ba4df", |
|
| 86 |
+ hash: sha1Hash, |
|
| 87 |
+ }, |
|
| 88 |
+ {
|
|
| 89 |
+ options: &sizedOptions{1, 1024 * 1024, false, false}, // a 1mb file (in memory)
|
|
| 90 |
+ tarsum: "tarsum+sha224:6319390c0b061d639085d8748b14cd55f697cf9313805218b21cf61c", |
|
| 91 |
+ hash: sha224Hash, |
|
| 92 |
+ }, |
|
| 93 |
+ {
|
|
| 94 |
+ options: &sizedOptions{1, 1024 * 1024, false, false}, // a 1mb file (in memory)
|
|
| 95 |
+ tarsum: "tarsum+sha384:a578ce3ce29a2ae03b8ed7c26f47d0f75b4fc849557c62454be4b5ffd66ba021e713b48ce71e947b43aab57afd5a7636", |
|
| 96 |
+ hash: sha384Hash, |
|
| 97 |
+ }, |
|
| 98 |
+ {
|
|
| 99 |
+ options: &sizedOptions{1, 1024 * 1024, false, false}, // a 1mb file (in memory)
|
|
| 100 |
+ tarsum: "tarsum+sha512:e9bfb90ca5a4dfc93c46ee061a5cf9837de6d2fdf82544d6460d3147290aecfabf7b5e415b9b6e72db9b8941f149d5d69fb17a394cbfaf2eac523bd9eae21855", |
|
| 101 |
+ hash: sha512Hash, |
|
| 102 |
+ }, |
|
| 78 | 103 |
} |
| 79 | 104 |
|
| 80 | 105 |
type sizedOptions struct {
|
| ... | ... |
@@ -203,6 +232,14 @@ func TestEmptyTar(t *testing.T) {
|
| 203 | 203 |
} |
| 204 | 204 |
} |
| 205 | 205 |
|
| 206 |
+var ( |
|
| 207 |
+ md5THash = NewTHash("md5", md5.New)
|
|
| 208 |
+ sha1Hash = NewTHash("sha1", sha1.New)
|
|
| 209 |
+ sha224Hash = NewTHash("sha224", sha256.New224)
|
|
| 210 |
+ sha384Hash = NewTHash("sha384", sha512.New384)
|
|
| 211 |
+ sha512Hash = NewTHash("sha512", sha512.New)
|
|
| 212 |
+) |
|
| 213 |
+ |
|
| 206 | 214 |
func TestTarSums(t *testing.T) {
|
| 207 | 215 |
for _, layer := range testLayers {
|
| 208 | 216 |
var ( |
| ... | ... |
@@ -226,8 +263,13 @@ func TestTarSums(t *testing.T) {
|
| 226 | 226 |
defer file.Close() |
| 227 | 227 |
} |
| 228 | 228 |
|
| 229 |
- // double negatives! |
|
| 230 |
- ts, err := NewTarSum(fh, !layer.gzip, layer.version) |
|
| 229 |
+ var ts TarSum |
|
| 230 |
+ if layer.hash == nil {
|
|
| 231 |
+ // double negatives! |
|
| 232 |
+ ts, err = NewTarSum(fh, !layer.gzip, layer.version) |
|
| 233 |
+ } else {
|
|
| 234 |
+ ts, err = NewTarSumHash(fh, !layer.gzip, layer.version, layer.hash) |
|
| 235 |
+ } |
|
| 231 | 236 |
if err != nil {
|
| 232 | 237 |
t.Errorf("%q :: %q", err, layer.filename)
|
| 233 | 238 |
continue |