diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 29c256c..21836cf 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -4,7 +4,7 @@ jobs: test: strategy: matrix: - go-version: [1.18.x, 1.19.x, 1.20.x, 1.21.x, 1.22.x] + go-version: [1.22.x, 1.23.x, 1.24.x] platform: [ubuntu-latest, windows-latest] runs-on: ${{ matrix.platform }} steps: @@ -16,6 +16,3 @@ jobs: uses: actions/checkout@v4 - name: Test run: go test -v ./... - - name: Test Blake3 - run: go test -v ./... - working-directory: blake3 diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..381020e --- /dev/null +++ b/Makefile @@ -0,0 +1,9 @@ +.PHONY: all build test + +all: build test + +build: + go build -v ./... + +test: + go test -v -cover -race ./... diff --git a/algorithm.go b/algorithm.go index bcf2b49..1d9d7fc 100644 --- a/algorithm.go +++ b/algorithm.go @@ -103,14 +103,16 @@ const ( var algorithmRegexp = regexp.MustCompile(`^[a-z0-9]+([+._-][a-z0-9]+)*$`) -// CryptoHash is the interface that any hash algorithm must implement +// CryptoHash is the interface that any digest algorithm must implement type CryptoHash interface { - // Available reports whether the given hash function is usable in the current binary. + // Available reports whether the given hash function is usable in the + // current binary. Available() bool - // Size returns the length, in bytes, of a digest resulting from the given hash function. + // Size returns the length, in bytes, of a digest resulting from the given + // hash function. Size() int - // New returns a new hash.Hash calculating the given hash function. If the hash function is not - // available, it may panic. + // New returns a new hash.Hash calculating the given hash function. If the + // hash function is not available, it may panic. New() hash.Hash } @@ -129,14 +131,16 @@ var ( algorithmsLock sync.RWMutex ) -// RegisterAlgorithm may be called to dynamically register an algorithm. The implementation is a CryptoHash, and -// the regex is meant to match the hash portion of the algorithm. If a duplicate algorithm is already registered, -// the return value is false, otherwise if registration was successful the return value is true. +// RegisterAlgorithm may be called to dynamically register an algorithm. The +// implementation is a CryptoHash, and the regex is meant to match the hash +// portion of the algorithm. If a duplicate algorithm is already registered, the +// return value is false, otherwise if registration was successful the return +// value is true. // // The algorithm encoding format must be based on hex. // -// The algorithm name must be conformant to the BNF specification in the OCI image-spec, otherwise the function -// will panic. +// The algorithm name must be conformant to the BNF specification in the OCI +// image-spec, otherwise the function will panic. func RegisterAlgorithm(algorithm Algorithm, implementation CryptoHash) bool { algorithmsLock.Lock() defer algorithmsLock.Unlock() @@ -150,8 +154,10 @@ func RegisterAlgorithm(algorithm Algorithm, implementation CryptoHash) bool { } algorithms[algorithm] = implementation - // We can do this since the Digest function below only implements a hex digest. If we open this in the future - // we need to allow for alternative digest algorithms to be implemented and for the user to pass their own + + // We can do this since the Digest function below only implements a hex + // digest. If we open this in the future we need to allow for alternative + // digest algorithms to be implemented and for the user to pass their own // custom regexp. anchoredEncodedRegexps[algorithm] = hexDigestRegex(implementation) return true diff --git a/blake3/blake3.go b/blake3.go similarity index 83% rename from blake3/blake3.go rename to blake3.go index 2f7df59..f40972e 100644 --- a/blake3/blake3.go +++ b/blake3.go @@ -11,18 +11,21 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. - -package blake3 +package digest import ( "hash" - "github.com/opencontainers/go-digest" "github.com/zeebo/blake3" ) +const ( + // Blake3 is the blake3 algorithm with the default 256-bit output size + Blake3 Algorithm = "blake3" +) + func init() { - digest.RegisterAlgorithm(digest.BLAKE3, &blake3hash{}) + RegisterAlgorithm(Blake3, &blake3hash{}) } type blake3hash struct{} diff --git a/blake3/blake3_test.go b/blake3/blake3_test.go deleted file mode 100644 index cb9a230..0000000 --- a/blake3/blake3_test.go +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2021 OCI Contributors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package blake3 - -import ( - "testing" - - "github.com/opencontainers/go-digest" - "github.com/opencontainers/go-digest/testdigest" -) - -func TestBLAKE3(t *testing.T) { - testdigest.RunTestCase(t, testdigest.TestCase{ - Input: "blake3:af1349b9f5f9a1a6a0404dea36dcc9499bcb25c9adc112b7cc9a93cae41f3262", - Algorithm: "blake3", - Encoded: "af1349b9f5f9a1a6a0404dea36dcc9499bcb25c9adc112b7cc9a93cae41f3262", - }) -} - -func TestBLAKE3Vector(t *testing.T) { - // From the BLAKE3 test vectors. - testvector := digest.BLAKE3.FromBytes([]byte{0, 1, 2, 3, 4}) - expected := "blake3:b40b44dfd97e7a84a996a91af8b85188c66c126940ba7aad2e7ae6b385402aa2" - if string(testvector) != expected { - t.Fatalf("Expected: %s; Got: %s", expected, testvector) - } -} diff --git a/blake3/go.mod b/blake3/go.mod deleted file mode 100644 index 45d35c9..0000000 --- a/blake3/go.mod +++ /dev/null @@ -1,15 +0,0 @@ -module github.com/opencontainers/go-digest/blake3 - -go 1.18 - -require ( - github.com/opencontainers/go-digest v1.0.0 - github.com/zeebo/blake3 v0.2.3 -) - -replace github.com/opencontainers/go-digest => ../ - -require ( - github.com/klauspost/cpuid/v2 v2.2.5 // indirect - golang.org/x/sys v0.13.0 // indirect -) diff --git a/blake3/go.sum b/blake3/go.sum deleted file mode 100644 index 125dc80..0000000 --- a/blake3/go.sum +++ /dev/null @@ -1,16 +0,0 @@ -github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= -github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg= -github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= -github.com/zeebo/assert v1.1.0 h1:hU1L1vLTHsnO8x8c9KAR5GmM5QscxHg5RNU5z5qbUWY= -github.com/zeebo/assert v1.1.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0= -github.com/zeebo/blake3 v0.2.2 h1:ddH9fUIlef5r+pqvJShGgSXFd6c7k54eQXZ48hNjotQ= -github.com/zeebo/blake3 v0.2.2/go.mod h1:TSQ0KjMH+pht+bRyvVooJ1rBpvvngSGaPISafq9MxJk= -github.com/zeebo/blake3 v0.2.3 h1:TFoLXsjeXqRNFxSbk35Dk4YtszE/MQQGK10BH4ptoTg= -github.com/zeebo/blake3 v0.2.3/go.mod h1:mjJjZpnsyIVtVgTOSpJ9vmRE4wgDeyt2HU3qXvvKCaQ= -github.com/zeebo/pcg v1.0.1 h1:lyqfGeWiv4ahac6ttHs+I5hwtH/+1mrhlCtVNQM2kHo= -github.com/zeebo/pcg v1.0.1/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4= -golang.org/x/sys v0.0.0-20201014080544-cc95f250f6bc h1:HVFDs9bKvTxP6bh1Rj9MCSo+UmafQtI8ZWDPVwVk9g4= -golang.org/x/sys v0.0.0-20201014080544-cc95f250f6bc/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/digest_test.go b/digest_test.go index 132d9e5..379e5a1 100644 --- a/digest_test.go +++ b/digest_test.go @@ -38,6 +38,11 @@ func TestParseDigest(t *testing.T) { Algorithm: "sha384", Encoded: "d3fc7881460b7e22e3d172954463dddd7866d17597e7248453c48b3e9d26d9596bf9c4a9cf8072c9d5bad76e19af801d", }, + { + Input: "blake3:af1349b9f5f9a1a6a0404dea36dcc9499bcb25c9adc112b7cc9a93cae41f3262", + Algorithm: "blake3", + Encoded: "af1349b9f5f9a1a6a0404dea36dcc9499bcb25c9adc112b7cc9a93cae41f3262", + }, { // empty Input: "", @@ -83,6 +88,11 @@ func TestParseDigest(t *testing.T) { Input: "sha512:abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789", Err: digest.ErrDigestInvalidLength, }, + { + // too short (from different algorithm) + Input: "blake3:abcdef0123456789abcdef0123456789abcdef01234", + Err: digest.ErrDigestInvalidLength, + }, { Input: "foo:d41d8cd98f00b204e9800998ecf8427e", Err: digest.ErrDigestUnsupported, diff --git a/go.mod b/go.mod index a8be38c..14e8bc0 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,10 @@ module github.com/opencontainers/go-digest -go 1.18 +go 1.22 + +require github.com/zeebo/blake3 v0.2.4 + +require ( + github.com/klauspost/cpuid/v2 v2.2.10 // indirect + golang.org/x/sys v0.32.0 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..834b23c --- /dev/null +++ b/go.sum @@ -0,0 +1,10 @@ +github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE= +github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= +github.com/zeebo/assert v1.1.0 h1:hU1L1vLTHsnO8x8c9KAR5GmM5QscxHg5RNU5z5qbUWY= +github.com/zeebo/assert v1.1.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0= +github.com/zeebo/blake3 v0.2.4 h1:KYQPkhpRtcqh0ssGYcKLG1JYvddkEA8QwCM/yBqhaZI= +github.com/zeebo/blake3 v0.2.4/go.mod h1:7eeQ6d2iXWRGF6npfaxl2CU+xy2Fjo2gxeyZGCRUjcE= +github.com/zeebo/pcg v1.0.1 h1:lyqfGeWiv4ahac6ttHs+I5hwtH/+1mrhlCtVNQM2kHo= +github.com/zeebo/pcg v1.0.1/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4= +golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= +golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= diff --git a/verifiers_test.go b/verifiers_test.go index 0e35115..9157a27 100644 --- a/verifiers_test.go +++ b/verifiers_test.go @@ -37,6 +37,15 @@ func TestDigestVerifier(t *testing.T) { } } +func TestDigestBlakeVector(t *testing.T) { + // From the BLAKE3 test vectors. + testvector := Blake3.FromBytes([]byte{0, 1, 2, 3, 4}) + expected := "blake3:b40b44dfd97e7a84a996a91af8b85188c66c126940ba7aad2e7ae6b385402aa2" + if string(testvector) != expected { + t.Fatalf("Expected: %s; Got: %s", expected, testvector) + } +} + // TestVerifierUnsupportedDigest ensures that unsupported digest validation is // flowing through verifier creation. func TestVerifierUnsupportedDigest(t *testing.T) {