Skip to content

Commit

Permalink
Add BLAKE3 support
Browse files Browse the repository at this point in the history
This adds support for the BLAKE3 hash family with a default output
size of 256-bit.

Signed-off-by: Sargun Dhillon <sargun@sargun.me>
  • Loading branch information
sargun committed Apr 22, 2021
1 parent 404628e commit eec210a
Show file tree
Hide file tree
Showing 6 changed files with 290 additions and 152 deletions.
44 changes: 44 additions & 0 deletions blake3/blake3.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// 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 (
"hash"

"github.com/opencontainers/go-digest"
"github.com/zeebo/blake3"
)

const (
// BLAKE3 is the blake3 algorithm with the default 256-bit output size
BLAKE3 digest.Algorithm = "blake3"
)

func init() {
digest.RegisterAlgorithm(BLAKE3, &blake3hash{})
}

type blake3hash struct{}

func (blake3hash) Available() bool {
return true
}

func (blake3hash) Size() int {
return blake3.New().Size()
}

func (blake3hash) New() hash.Hash {
return blake3.New()
}
38 changes: 38 additions & 0 deletions blake3/blake3_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// 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/testdigest"
_ "github.com/zeebo/blake3"
)

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 := BLAKE3.FromBytes([]byte{0, 1, 2, 3, 4})
expected := "blake3:b40b44dfd97e7a84a996a91af8b85188c66c126940ba7aad2e7ae6b385402aa2"
if string(testvector) != expected {
t.Fatalf("Expected: %s; Got: %s", expected, testvector)
}
}
12 changes: 12 additions & 0 deletions blake3/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
module github.com/opencontainers/go-digest/blake3

go 1.15

require (
github.com/opencontainers/go-digest v0.0.0
github.com/zeebo/blake3 v0.1.1
)

replace (
github.com/opencontainers/go-digest => ../
)
152 changes: 0 additions & 152 deletions digest_test.go

This file was deleted.

80 changes: 80 additions & 0 deletions testdigest/testdigest.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// 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.

// testdigest is a separate package, because it has some testing utilities in it that may be useful
// to other internal Algorithm implementors.
//
// It is not a stable interface and not meant for consumption outside of digest developers.

package testdigest

import (
"testing"

pkgdigest "github.com/opencontainers/go-digest"
)

type TestCase struct {
// Input the formal format of the hash, for example sha256:e58fcf7418d4390dec8e8fb69d88c06ec07039d651fedd3aa72af9972e7d046b
Input string
// If err is non-nil, then the parsing of Input is expected to return this error
Err error
// Algorithm should be an available or registered algorithm
Algorithm pkgdigest.Algorithm
// Encoded is the the encoded portion of the digest to expect, for example e58fcf7418d4390dec8e8fb69d88c06ec07039d651fedd3aa72af9972e7d046b
Encoded string
}

func RunTestCase(t *testing.T, testcase TestCase) {
digest, err := pkgdigest.Parse(testcase.Input)
if err != testcase.Err {
t.Fatalf("error differed from expected while parsing %q: %v != %v", testcase.Input, err, testcase.Err)
}

if testcase.Err != nil {
return
}

if digest.Algorithm() != testcase.Algorithm {
t.Fatalf("incorrect Algorithm for parsed digest: %q != %q", digest.Algorithm(), testcase.Algorithm)
}

if digest.Encoded() != testcase.Encoded {
t.Fatalf("incorrect hex for parsed digest: %q != %q", digest.Encoded(), testcase.Encoded)
}

// Parse string return value and check equality
newParsed, err := pkgdigest.Parse(digest.String())

if err != nil {
t.Fatalf("unexpected error parsing Input %q: %v", testcase.Input, err)
}

if newParsed != digest {
t.Fatalf("expected equal: %q != %q", newParsed, digest)
}

newFromHex := pkgdigest.NewDigestFromEncoded(newParsed.Algorithm(), newParsed.Encoded())
if newFromHex != digest {
t.Fatalf("%v != %v", newFromHex, digest)
}
}

func RunTestCases(t *testing.T, testcases []TestCase) {
for _, testcase := range testcases {
t.Run(testcase.Input, func(t *testing.T) {
RunTestCase(t, testcase)
})
}
}
Loading

0 comments on commit eec210a

Please sign in to comment.