Skip to content

Commit

Permalink
commit
Browse files Browse the repository at this point in the history
  • Loading branch information
bufdev committed Mar 1, 2024
1 parent 858b962 commit fc375e0
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 27 deletions.
44 changes: 17 additions & 27 deletions private/bufpkg/bufcas/digest.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,15 @@ import (
"strconv"
"strings"

"github.com/bufbuild/buf/private/pkg/shake256"
"github.com/bufbuild/buf/private/pkg/syserror"
"golang.org/x/crypto/sha3"
)

const (
// DigestTypeShake256 represents the shake256 digest type.
//
// This is both the default and the only currently-known value for DigestType.
DigestTypeShake256 DigestType = iota + 1

shake256Length = 64
)

var (
Expand Down Expand Up @@ -103,10 +101,17 @@ func NewDigest(value []byte, options ...DigestOption) (Digest, error) {
if digestOptions.digestType == 0 {
digestOptions.digestType = DigestTypeShake256
}
if err := validateDigestParameters(digestOptions.digestType, value); err != nil {
return nil, err
switch digestOptions.digestType {
case DigestTypeShake256:
shake256Digest, err := shake256.NewDigest(value)
if err != nil {
return nil, err
}
return newDigest(DigestTypeShake256, shake256Digest.Value()), nil
default:
// This is a system error.
return nil, syserror.Newf("unknown DigestType: %v", digestOptions.digestType)
}
return newDigest(digestOptions.digestType, value), nil
}

// NewDigestForContent creates a new Digest based on the given content read from the Reader.
Expand All @@ -124,22 +129,11 @@ func NewDigestForContent(reader io.Reader, options ...DigestOption) (Digest, err
}
switch digestOptions.digestType {
case DigestTypeShake256:
shakeHash := sha3.NewShake256()
// TODO: remove in the future, this should have no effect
shakeHash.Reset()
if _, err := io.Copy(shakeHash, reader); err != nil {
return nil, err
}
value := make([]byte, shake256Length)
if _, err := shakeHash.Read(value); err != nil {
// sha3.ShakeHash never errors or short reads. Something horribly wrong
// happened if your computer ended up here.
return nil, err
}
if err := validateDigestParameters(DigestTypeShake256, value); err != nil {
shake256Digest, err := shake256.NewDigestForContent(reader)
if err != nil {
return nil, err
}
return newDigest(DigestTypeShake256, value), nil
return newDigest(DigestTypeShake256, shake256Digest.Value()), nil
default:
// This is a system error.
return nil, syserror.Newf("unknown DigestType: %v", digestOptions.digestType)
Expand Down Expand Up @@ -265,13 +259,9 @@ func newDigestOptions() *digestOptions {
func validateDigestParameters(digestType DigestType, value []byte) error {
switch digestType {
case DigestTypeShake256:
if len(value) != shake256Length {
return fmt.Errorf(
`invalid %s digest value: expected %d bytes, got %d`,
digestType.String(),
shake256Length,
len(value),
)
_, err := shake256.NewDigest(value)
if err != nil {
return err
}
default:
// This is really always a system error, but little harm in including it here, even
Expand Down
76 changes: 76 additions & 0 deletions private/pkg/shake256/shake256.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// Copyright 2020-2024 Buf Technologies, Inc.
//
// 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
//
// http://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 shake256 provides simple utilities around shake256 digests.
package shake256

import (
"fmt"
"io"

"github.com/bufbuild/buf/private/pkg/slicesext"
"golang.org/x/crypto/sha3"
)

const shake256Length = 64

// Digest is a shake256 digest.
type Digest interface {
Value() []byte

isDigest()
}

// NewDigest returns a new Digest for the value.
func NewDigest(value []byte) (Digest, error) {
return newDigest(value)
}

// NewDigest returns a new Digest for the content read from the Reader.
func NewDigestForContent(reader io.Reader) (Digest, error) {
shakeHash := sha3.NewShake256()
// TODO: remove in the future, this should have no effect
shakeHash.Reset()
if _, err := io.Copy(shakeHash, reader); err != nil {
return nil, err
}
value := make([]byte, shake256Length)
if _, err := shakeHash.Read(value); err != nil {
// sha3.ShakeHash never errors or short reads. Something horribly wrong
// happened if your computer ended up here.
return nil, err
}
return newDigest(value)
}

// *** PRIVATE ***

type digest struct {
value []byte
}

func newDigest(value []byte) (*digest, error) {
if len(value) != shake256Length {
return nil, fmt.Errorf("invalid shake256 digest value: expected %d bytes, got %d", shake256Length, len(value))
}
return &digest{
value: value,
}, nil
}

func (d *digest) Value() []byte {
return slicesext.Copy(d.value)
}

func (*digest) isDigest() {}
19 changes: 19 additions & 0 deletions private/pkg/shake256/usage.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit fc375e0

Please sign in to comment.