vendor: add opencontainers/go-digest to vendor.conf
Signed-off-by: Stephen J Day <stephen.day@docker.com>master
							parent
							
								
									532ec9f036
								
							
						
					
					
						commit
						72150bef10
					
				|  | @ -37,3 +37,4 @@ gopkg.in/check.v1 64131543e7896d5bcc6bd5a76287eb75ea96c673 | |||
| gopkg.in/square/go-jose.v1 40d457b439244b546f023d056628e5184136899b | ||||
| gopkg.in/yaml.v2 bef53efd0c76e49e6de55ead051f886bea7e9420 | ||||
| rsc.io/letsencrypt e770c10b0f1a64775ae91d240407ce00d1a5bdeb https://github.com/dmcgowan/letsencrypt.git | ||||
| github.com/opencontainers/go-digest a6d0ee40d4207ea02364bd3b9e8e77b9159ba1eb | ||||
|  |  | |||
|  | @ -0,0 +1,144 @@ | |||
| package digest | ||||
| 
 | ||||
| import ( | ||||
| 	"crypto" | ||||
| 	"fmt" | ||||
| 	"hash" | ||||
| 	"io" | ||||
| ) | ||||
| 
 | ||||
| // Algorithm identifies and implementation of a digester by an identifier.
 | ||||
| // Note the that this defines both the hash algorithm used and the string
 | ||||
| // encoding.
 | ||||
| type Algorithm string | ||||
| 
 | ||||
| // supported digest types
 | ||||
| const ( | ||||
| 	SHA256 Algorithm = "sha256" // sha256 with hex encoding
 | ||||
| 	SHA384 Algorithm = "sha384" // sha384 with hex encoding
 | ||||
| 	SHA512 Algorithm = "sha512" // sha512 with hex encoding
 | ||||
| 
 | ||||
| 	// Canonical is the primary digest algorithm used with the distribution
 | ||||
| 	// project. Other digests may be used but this one is the primary storage
 | ||||
| 	// digest.
 | ||||
| 	Canonical = SHA256 | ||||
| ) | ||||
| 
 | ||||
| var ( | ||||
| 	// TODO(stevvooe): Follow the pattern of the standard crypto package for
 | ||||
| 	// registration of digests. Effectively, we are a registerable set and
 | ||||
| 	// common symbol access.
 | ||||
| 
 | ||||
| 	// algorithms maps values to hash.Hash implementations. Other algorithms
 | ||||
| 	// may be available but they cannot be calculated by the digest package.
 | ||||
| 	algorithms = map[Algorithm]crypto.Hash{ | ||||
| 		SHA256: crypto.SHA256, | ||||
| 		SHA384: crypto.SHA384, | ||||
| 		SHA512: crypto.SHA512, | ||||
| 	} | ||||
| ) | ||||
| 
 | ||||
| // Available returns true if the digest type is available for use. If this
 | ||||
| // returns false, Digester and Hash will return nil.
 | ||||
| func (a Algorithm) Available() bool { | ||||
| 	h, ok := algorithms[a] | ||||
| 	if !ok { | ||||
| 		return false | ||||
| 	} | ||||
| 
 | ||||
| 	// check availability of the hash, as well
 | ||||
| 	return h.Available() | ||||
| } | ||||
| 
 | ||||
| func (a Algorithm) String() string { | ||||
| 	return string(a) | ||||
| } | ||||
| 
 | ||||
| // Size returns number of bytes returned by the hash.
 | ||||
| func (a Algorithm) Size() int { | ||||
| 	h, ok := algorithms[a] | ||||
| 	if !ok { | ||||
| 		return 0 | ||||
| 	} | ||||
| 	return h.Size() | ||||
| } | ||||
| 
 | ||||
| // Set implemented to allow use of Algorithm as a command line flag.
 | ||||
| func (a *Algorithm) Set(value string) error { | ||||
| 	if value == "" { | ||||
| 		*a = Canonical | ||||
| 	} else { | ||||
| 		// just do a type conversion, support is queried with Available.
 | ||||
| 		*a = Algorithm(value) | ||||
| 	} | ||||
| 
 | ||||
| 	if !a.Available() { | ||||
| 		return ErrDigestUnsupported | ||||
| 	} | ||||
| 
 | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // Digester returns a new digester for the specified algorithm. If the algorithm
 | ||||
| // does not have a digester implementation, nil will be returned. This can be
 | ||||
| // checked by calling Available before calling Digester.
 | ||||
| func (a Algorithm) Digester() Digester { | ||||
| 	return &digester{ | ||||
| 		alg:  a, | ||||
| 		hash: a.Hash(), | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // Hash returns a new hash as used by the algorithm. If not available, the
 | ||||
| // method will panic. Check Algorithm.Available() before calling.
 | ||||
| func (a Algorithm) Hash() hash.Hash { | ||||
| 	if !a.Available() { | ||||
| 		// Empty algorithm string is invalid
 | ||||
| 		if a == "" { | ||||
| 			panic(fmt.Sprintf("empty digest algorithm, validate before calling Algorithm.Hash()")) | ||||
| 		} | ||||
| 
 | ||||
| 		// NOTE(stevvooe): A missing hash is usually a programming error that
 | ||||
| 		// must be resolved at compile time. We don't import in the digest
 | ||||
| 		// package to allow users to choose their hash implementation (such as
 | ||||
| 		// when using stevvooe/resumable or a hardware accelerated package).
 | ||||
| 		//
 | ||||
| 		// Applications that may want to resolve the hash at runtime should
 | ||||
| 		// call Algorithm.Available before call Algorithm.Hash().
 | ||||
| 		panic(fmt.Sprintf("%v not available (make sure it is imported)", a)) | ||||
| 	} | ||||
| 
 | ||||
| 	return algorithms[a].New() | ||||
| } | ||||
| 
 | ||||
| // FromReader returns the digest of the reader using the algorithm.
 | ||||
| func (a Algorithm) FromReader(rd io.Reader) (Digest, error) { | ||||
| 	digester := a.Digester() | ||||
| 
 | ||||
| 	if _, err := io.Copy(digester.Hash(), rd); err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 
 | ||||
| 	return digester.Digest(), nil | ||||
| } | ||||
| 
 | ||||
| // FromBytes digests the input and returns a Digest.
 | ||||
| func (a Algorithm) FromBytes(p []byte) Digest { | ||||
| 	digester := a.Digester() | ||||
| 
 | ||||
| 	if _, err := digester.Hash().Write(p); err != nil { | ||||
| 		// Writes to a Hash should never fail. None of the existing
 | ||||
| 		// hash implementations in the stdlib or hashes vendored
 | ||||
| 		// here can return errors from Write. Having a panic in this
 | ||||
| 		// condition instead of having FromBytes return an error value
 | ||||
| 		// avoids unnecessary error handling paths in all callers.
 | ||||
| 		panic("write to hash function returned error: " + err.Error()) | ||||
| 	} | ||||
| 
 | ||||
| 	return digester.Digest() | ||||
| } | ||||
| 
 | ||||
| // FromString digests the string input and returns a Digest.
 | ||||
| func (a Algorithm) FromString(s string) Digest { | ||||
| 	return a.FromBytes([]byte(s)) | ||||
| } | ||||
|  | @ -0,0 +1,140 @@ | |||
| package digest | ||||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"hash" | ||||
| 	"io" | ||||
| 	"regexp" | ||||
| 	"strings" | ||||
| ) | ||||
| 
 | ||||
| // Digest allows simple protection of hex formatted digest strings, prefixed
 | ||||
| // by their algorithm. Strings of type Digest have some guarantee of being in
 | ||||
| // the correct format and it provides quick access to the components of a
 | ||||
| // digest string.
 | ||||
| //
 | ||||
| // The following is an example of the contents of Digest types:
 | ||||
| //
 | ||||
| // 	sha256:7173b809ca12ec5dee4506cd86be934c4596dd234ee82c0662eac04a8c2c71dc
 | ||||
| //
 | ||||
| // This allows to abstract the digest behind this type and work only in those
 | ||||
| // terms.
 | ||||
| type Digest string | ||||
| 
 | ||||
| // NewDigest returns a Digest from alg and a hash.Hash object.
 | ||||
| func NewDigest(alg Algorithm, h hash.Hash) Digest { | ||||
| 	return NewDigestFromBytes(alg, h.Sum(nil)) | ||||
| } | ||||
| 
 | ||||
| // NewDigestFromBytes returns a new digest from the byte contents of p.
 | ||||
| // Typically, this can come from hash.Hash.Sum(...) or xxx.SumXXX(...)
 | ||||
| // functions. This is also useful for rebuilding digests from binary
 | ||||
| // serializations.
 | ||||
| func NewDigestFromBytes(alg Algorithm, p []byte) Digest { | ||||
| 	return Digest(fmt.Sprintf("%s:%x", alg, p)) | ||||
| } | ||||
| 
 | ||||
| // NewDigestFromHex returns a Digest from alg and a the hex encoded digest.
 | ||||
| func NewDigestFromHex(alg, hex string) Digest { | ||||
| 	return Digest(fmt.Sprintf("%s:%s", alg, hex)) | ||||
| } | ||||
| 
 | ||||
| // DigestRegexp matches valid digest types.
 | ||||
| var DigestRegexp = regexp.MustCompile(`[a-zA-Z0-9-_+.]+:[a-fA-F0-9]+`) | ||||
| 
 | ||||
| // DigestRegexpAnchored matches valid digest types, anchored to the start and end of the match.
 | ||||
| var DigestRegexpAnchored = regexp.MustCompile(`^` + DigestRegexp.String() + `$`) | ||||
| 
 | ||||
| var ( | ||||
| 	// ErrDigestInvalidFormat returned when digest format invalid.
 | ||||
| 	ErrDigestInvalidFormat = fmt.Errorf("invalid checksum digest format") | ||||
| 
 | ||||
| 	// ErrDigestInvalidLength returned when digest has invalid length.
 | ||||
| 	ErrDigestInvalidLength = fmt.Errorf("invalid checksum digest length") | ||||
| 
 | ||||
| 	// ErrDigestUnsupported returned when the digest algorithm is unsupported.
 | ||||
| 	ErrDigestUnsupported = fmt.Errorf("unsupported digest algorithm") | ||||
| ) | ||||
| 
 | ||||
| // Parse parses s and returns the validated digest object. An error will
 | ||||
| // be returned if the format is invalid.
 | ||||
| func Parse(s string) (Digest, error) { | ||||
| 	d := Digest(s) | ||||
| 	return d, d.Validate() | ||||
| } | ||||
| 
 | ||||
| // FromReader consumes the content of rd until io.EOF, returning canonical digest.
 | ||||
| func FromReader(rd io.Reader) (Digest, error) { | ||||
| 	return Canonical.FromReader(rd) | ||||
| } | ||||
| 
 | ||||
| // FromBytes digests the input and returns a Digest.
 | ||||
| func FromBytes(p []byte) Digest { | ||||
| 	return Canonical.FromBytes(p) | ||||
| } | ||||
| 
 | ||||
| // FromString digests the input and returns a Digest.
 | ||||
| func FromString(s string) Digest { | ||||
| 	return Canonical.FromString(s) | ||||
| } | ||||
| 
 | ||||
| // Validate checks that the contents of d is a valid digest, returning an
 | ||||
| // error if not.
 | ||||
| func (d Digest) Validate() error { | ||||
| 	s := string(d) | ||||
| 
 | ||||
| 	i := strings.Index(s, ":") | ||||
| 
 | ||||
| 	// validate i then run through regexp
 | ||||
| 	if i < 0 || i+1 == len(s) || !DigestRegexpAnchored.MatchString(s) { | ||||
| 		return ErrDigestInvalidFormat | ||||
| 	} | ||||
| 
 | ||||
| 	algorithm := Algorithm(s[:i]) | ||||
| 	if !algorithm.Available() { | ||||
| 		return ErrDigestUnsupported | ||||
| 	} | ||||
| 
 | ||||
| 	// Digests much always be hex-encoded, ensuring that their hex portion will
 | ||||
| 	// always be size*2
 | ||||
| 	if algorithm.Size()*2 != len(s[i+1:]) { | ||||
| 		return ErrDigestInvalidLength | ||||
| 	} | ||||
| 
 | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // Algorithm returns the algorithm portion of the digest. This will panic if
 | ||||
| // the underlying digest is not in a valid format.
 | ||||
| func (d Digest) Algorithm() Algorithm { | ||||
| 	return Algorithm(d[:d.sepIndex()]) | ||||
| } | ||||
| 
 | ||||
| // Verifier returns a writer object that can be used to verify a stream of
 | ||||
| // content against the digest. If the digest is invalid, the method will panic.
 | ||||
| func (d Digest) Verifier() Verifier { | ||||
| 	return hashVerifier{ | ||||
| 		hash:   d.Algorithm().Hash(), | ||||
| 		digest: d, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // Hex returns the hex digest portion of the digest. This will panic if the
 | ||||
| // underlying digest is not in a valid format.
 | ||||
| func (d Digest) Hex() string { | ||||
| 	return string(d[d.sepIndex()+1:]) | ||||
| } | ||||
| 
 | ||||
| func (d Digest) String() string { | ||||
| 	return string(d) | ||||
| } | ||||
| 
 | ||||
| func (d Digest) sepIndex() int { | ||||
| 	i := strings.Index(string(d), ":") | ||||
| 
 | ||||
| 	if i < 0 { | ||||
| 		panic(fmt.Sprintf("no ':' separator in digest %q", d)) | ||||
| 	} | ||||
| 
 | ||||
| 	return i | ||||
| } | ||||
|  | @ -0,0 +1,25 @@ | |||
| package digest | ||||
| 
 | ||||
| import "hash" | ||||
| 
 | ||||
| // Digester calculates the digest of written data. Writes should go directly
 | ||||
| // to the return value of Hash, while calling Digest will return the current
 | ||||
| // value of the digest.
 | ||||
| type Digester interface { | ||||
| 	Hash() hash.Hash // provides direct access to underlying hash instance.
 | ||||
| 	Digest() Digest | ||||
| } | ||||
| 
 | ||||
| // digester provides a simple digester definition that embeds a hasher.
 | ||||
| type digester struct { | ||||
| 	alg  Algorithm | ||||
| 	hash hash.Hash | ||||
| } | ||||
| 
 | ||||
| func (d *digester) Hash() hash.Hash { | ||||
| 	return d.hash | ||||
| } | ||||
| 
 | ||||
| func (d *digester) Digest() Digest { | ||||
| 	return NewDigest(d.alg, d.hash) | ||||
| } | ||||
|  | @ -0,0 +1,42 @@ | |||
| // Package digest provides a generalized type to opaquely represent message
 | ||||
| // digests and their operations within the registry. The Digest type is
 | ||||
| // designed to serve as a flexible identifier in a content-addressable system.
 | ||||
| // More importantly, it provides tools and wrappers to work with
 | ||||
| // hash.Hash-based digests with little effort.
 | ||||
| //
 | ||||
| // Basics
 | ||||
| //
 | ||||
| // The format of a digest is simply a string with two parts, dubbed the
 | ||||
| // "algorithm" and the "digest", separated by a colon:
 | ||||
| //
 | ||||
| // 	<algorithm>:<digest>
 | ||||
| //
 | ||||
| // An example of a sha256 digest representation follows:
 | ||||
| //
 | ||||
| // 	sha256:7173b809ca12ec5dee4506cd86be934c4596dd234ee82c0662eac04a8c2c71dc
 | ||||
| //
 | ||||
| // In this case, the string "sha256" is the algorithm and the hex bytes are
 | ||||
| // the "digest".
 | ||||
| //
 | ||||
| // Because the Digest type is simply a string, once a valid Digest is
 | ||||
| // obtained, comparisons are cheap, quick and simple to express with the
 | ||||
| // standard equality operator.
 | ||||
| //
 | ||||
| // Verification
 | ||||
| //
 | ||||
| // The main benefit of using the Digest type is simple verification against a
 | ||||
| // given digest. The Verifier interface, modeled after the stdlib hash.Hash
 | ||||
| // interface, provides a common write sink for digest verification. After
 | ||||
| // writing is complete, calling the Verifier.Verified method will indicate
 | ||||
| // whether or not the stream of bytes matches the target digest.
 | ||||
| //
 | ||||
| // Missing Features
 | ||||
| //
 | ||||
| // In addition to the above, we intend to add the following features to this
 | ||||
| // package:
 | ||||
| //
 | ||||
| // 1. A Digester type that supports write sink digest calculation.
 | ||||
| //
 | ||||
| // 2. Suspend and resume of ongoing digest calculations to support efficient digest verification in the registry.
 | ||||
| //
 | ||||
| package digest | ||||
|  | @ -0,0 +1,31 @@ | |||
| package digest | ||||
| 
 | ||||
| import ( | ||||
| 	"hash" | ||||
| 	"io" | ||||
| ) | ||||
| 
 | ||||
| // Verifier presents a general verification interface to be used with message
 | ||||
| // digests and other byte stream verifications. Users instantiate a Verifier
 | ||||
| // from one of the various methods, write the data under test to it then check
 | ||||
| // the result with the Verified method.
 | ||||
| type Verifier interface { | ||||
| 	io.Writer | ||||
| 
 | ||||
| 	// Verified will return true if the content written to Verifier matches
 | ||||
| 	// the digest.
 | ||||
| 	Verified() bool | ||||
| } | ||||
| 
 | ||||
| type hashVerifier struct { | ||||
| 	digest Digest | ||||
| 	hash   hash.Hash | ||||
| } | ||||
| 
 | ||||
| func (hv hashVerifier) Write(p []byte) (n int, err error) { | ||||
| 	return hv.hash.Write(p) | ||||
| } | ||||
| 
 | ||||
| func (hv hashVerifier) Verified() bool { | ||||
| 	return hv.digest == NewDigest(hv.digest.Algorithm(), hv.hash) | ||||
| } | ||||
		Loading…
	
		Reference in New Issue