Changes included:
- digest: allow separators in algorithm field
- disallow upper characters (/A-F/) in hex-encoded portion
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
| ... | ... |
@@ -61,7 +61,7 @@ github.com/ishidawataru/sctp 07191f837fedd2f13d1ec7b5f885f0f3ec54b1cb |
| 61 | 61 |
# get graph and distribution packages |
| 62 | 62 |
github.com/docker/distribution edc3ab29cdff8694dd6feb85cfeb4b5f1b38ed9c |
| 63 | 63 |
github.com/vbatts/tar-split v0.10.2 |
| 64 |
-github.com/opencontainers/go-digest a6d0ee40d4207ea02364bd3b9e8e77b9159ba1eb |
|
| 64 |
+github.com/opencontainers/go-digest v1.0.0-rc1 |
|
| 65 | 65 |
|
| 66 | 66 |
# get go-zfs packages |
| 67 | 67 |
github.com/mistifyio/go-zfs 22c9b32c84eb0d0c6f4043b6e90fc94073de92fa |
| ... | ... |
@@ -1,10 +1,10 @@ |
| 1 | 1 |
# go-digest |
| 2 | 2 |
|
| 3 |
-[](https://godoc.org/github.com/docker/go-digest) [](https://goreportcard.com/report/github.com/docker/go-digest) [](https://travis-ci.org/docker/go-digest) |
|
| 3 |
+[](https://godoc.org/github.com/opencontainers/go-digest) [](https://goreportcard.com/report/github.com/opencontainers/go-digest) [](https://travis-ci.org/opencontainers/go-digest) |
|
| 4 | 4 |
|
| 5 | 5 |
Common digest package used across the container ecosystem. |
| 6 | 6 |
|
| 7 |
-Please see the [godoc](https://godoc.org/github.com/docker/go-digest) for more information. |
|
| 7 |
+Please see the [godoc](https://godoc.org/github.com/opencontainers/go-digest) for more information. |
|
| 8 | 8 |
|
| 9 | 9 |
# What is a digest? |
| 10 | 10 |
|
| ... | ... |
@@ -49,7 +49,7 @@ can power a rich, safe, content distribution system. |
| 49 | 49 |
|
| 50 | 50 |
# Usage |
| 51 | 51 |
|
| 52 |
-While the [godoc](https://godoc.org/github.com/docker/go-digest) is |
|
| 52 |
+While the [godoc](https://godoc.org/github.com/opencontainers/go-digest) is |
|
| 53 | 53 |
considered the best resource, a few important items need to be called |
| 54 | 54 |
out when using this package. |
| 55 | 55 |
|
| ... | ... |
@@ -76,7 +76,7 @@ out when using this package. |
| 76 | 76 |
|
| 77 | 77 |
The Go API, at this stage, is considered stable, unless otherwise noted. |
| 78 | 78 |
|
| 79 |
-As always, before using a package export, read the [godoc](https://godoc.org/github.com/docker/go-digest). |
|
| 79 |
+As always, before using a package export, read the [godoc](https://godoc.org/github.com/opencontainers/go-digest). |
|
| 80 | 80 |
|
| 81 | 81 |
# Contributing |
| 82 | 82 |
|
| ... | ... |
@@ -88,16 +88,16 @@ the alternatives you tried before submitting a PR. |
| 88 | 88 |
|
| 89 | 89 |
# Reporting security issues |
| 90 | 90 |
|
| 91 |
-The maintainers take security seriously. If you discover a security |
|
| 92 |
-issue, please bring it to their attention right away! |
|
| 91 |
+Please DO NOT file a public issue, instead send your report privately to |
|
| 92 |
+security@opencontainers.org. |
|
| 93 | 93 |
|
| 94 |
-Please DO NOT file a public issue, instead send your report privately |
|
| 95 |
-to security@docker.com. |
|
| 94 |
+The maintainers take security seriously. If you discover a security issue, |
|
| 95 |
+please bring it to their attention right away! |
|
| 96 | 96 |
|
| 97 |
-Security reports are greatly appreciated and we will publicly thank you |
|
| 98 |
-for it. We also like to send gifts—if you're into Docker schwag, make |
|
| 99 |
-sure to let us know. We currently do not offer a paid security bounty |
|
| 100 |
-program, but are not ruling it out in the future. |
|
| 97 |
+If you are reporting a security issue, do not create an issue or file a pull |
|
| 98 |
+request on GitHub. Instead, disclose the issue responsibly by sending an email |
|
| 99 |
+to security@opencontainers.org (which is inhabited only by the maintainers of |
|
| 100 |
+the various OCI projects). |
|
| 101 | 101 |
|
| 102 | 102 |
# Copyright and license |
| 103 | 103 |
|
| ... | ... |
@@ -1,3 +1,17 @@ |
| 1 |
+// Copyright 2017 Docker, Inc. |
|
| 2 |
+// |
|
| 3 |
+// Licensed under the Apache License, Version 2.0 (the "License"); |
|
| 4 |
+// you may not use this file except in compliance with the License. |
|
| 5 |
+// You may obtain a copy of the License at |
|
| 6 |
+// |
|
| 7 |
+// https://www.apache.org/licenses/LICENSE-2.0 |
|
| 8 |
+// |
|
| 9 |
+// Unless required by applicable law or agreed to in writing, software |
|
| 10 |
+// distributed under the License is distributed on an "AS IS" BASIS, |
|
| 11 |
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
| 12 |
+// See the License for the specific language governing permissions and |
|
| 13 |
+// limitations under the License. |
|
| 14 |
+ |
|
| 1 | 15 |
package digest |
| 2 | 16 |
|
| 3 | 17 |
import ( |
| ... | ... |
@@ -5,6 +19,7 @@ import ( |
| 5 | 5 |
"fmt" |
| 6 | 6 |
"hash" |
| 7 | 7 |
"io" |
| 8 |
+ "regexp" |
|
| 8 | 9 |
) |
| 9 | 10 |
|
| 10 | 11 |
// Algorithm identifies and implementation of a digester by an identifier. |
| ... | ... |
@@ -14,9 +29,9 @@ type Algorithm string |
| 14 | 14 |
|
| 15 | 15 |
// supported digest types |
| 16 | 16 |
const ( |
| 17 |
- SHA256 Algorithm = "sha256" // sha256 with hex encoding |
|
| 18 |
- SHA384 Algorithm = "sha384" // sha384 with hex encoding |
|
| 19 |
- SHA512 Algorithm = "sha512" // sha512 with hex encoding |
|
| 17 |
+ SHA256 Algorithm = "sha256" // sha256 with hex encoding (lower case only) |
|
| 18 |
+ SHA384 Algorithm = "sha384" // sha384 with hex encoding (lower case only) |
|
| 19 |
+ SHA512 Algorithm = "sha512" // sha512 with hex encoding (lower case only) |
|
| 20 | 20 |
|
| 21 | 21 |
// Canonical is the primary digest algorithm used with the distribution |
| 22 | 22 |
// project. Other digests may be used but this one is the primary storage |
| ... | ... |
@@ -36,6 +51,14 @@ var ( |
| 36 | 36 |
SHA384: crypto.SHA384, |
| 37 | 37 |
SHA512: crypto.SHA512, |
| 38 | 38 |
} |
| 39 |
+ |
|
| 40 |
+ // anchoredEncodedRegexps contains anchored regular expressions for hex-encoded digests. |
|
| 41 |
+ // Note that /A-F/ disallowed. |
|
| 42 |
+ anchoredEncodedRegexps = map[Algorithm]*regexp.Regexp{
|
|
| 43 |
+ SHA256: regexp.MustCompile(`^[a-f0-9]{64}$`),
|
|
| 44 |
+ SHA384: regexp.MustCompile(`^[a-f0-9]{96}$`),
|
|
| 45 |
+ SHA512: regexp.MustCompile(`^[a-f0-9]{128}$`),
|
|
| 46 |
+ } |
|
| 39 | 47 |
) |
| 40 | 48 |
|
| 41 | 49 |
// Available returns true if the digest type is available for use. If this |
| ... | ... |
@@ -111,6 +134,14 @@ func (a Algorithm) Hash() hash.Hash {
|
| 111 | 111 |
return algorithms[a].New() |
| 112 | 112 |
} |
| 113 | 113 |
|
| 114 |
+// Encode encodes the raw bytes of a digest, typically from a hash.Hash, into |
|
| 115 |
+// the encoded portion of the digest. |
|
| 116 |
+func (a Algorithm) Encode(d []byte) string {
|
|
| 117 |
+ // TODO(stevvooe): Currently, all algorithms use a hex encoding. When we |
|
| 118 |
+ // add support for back registration, we can modify this accordingly. |
|
| 119 |
+ return fmt.Sprintf("%x", d)
|
|
| 120 |
+} |
|
| 121 |
+ |
|
| 114 | 122 |
// FromReader returns the digest of the reader using the algorithm. |
| 115 | 123 |
func (a Algorithm) FromReader(rd io.Reader) (Digest, error) {
|
| 116 | 124 |
digester := a.Digester() |
| ... | ... |
@@ -142,3 +173,20 @@ func (a Algorithm) FromBytes(p []byte) Digest {
|
| 142 | 142 |
func (a Algorithm) FromString(s string) Digest {
|
| 143 | 143 |
return a.FromBytes([]byte(s)) |
| 144 | 144 |
} |
| 145 |
+ |
|
| 146 |
+// Validate validates the encoded portion string |
|
| 147 |
+func (a Algorithm) Validate(encoded string) error {
|
|
| 148 |
+ r, ok := anchoredEncodedRegexps[a] |
|
| 149 |
+ if !ok {
|
|
| 150 |
+ return ErrDigestUnsupported |
|
| 151 |
+ } |
|
| 152 |
+ // Digests much always be hex-encoded, ensuring that their hex portion will |
|
| 153 |
+ // always be size*2 |
|
| 154 |
+ if a.Size()*2 != len(encoded) {
|
|
| 155 |
+ return ErrDigestInvalidLength |
|
| 156 |
+ } |
|
| 157 |
+ if r.MatchString(encoded) {
|
|
| 158 |
+ return nil |
|
| 159 |
+ } |
|
| 160 |
+ return ErrDigestInvalidFormat |
|
| 161 |
+} |
| ... | ... |
@@ -1,3 +1,17 @@ |
| 1 |
+// Copyright 2017 Docker, Inc. |
|
| 2 |
+// |
|
| 3 |
+// Licensed under the Apache License, Version 2.0 (the "License"); |
|
| 4 |
+// you may not use this file except in compliance with the License. |
|
| 5 |
+// You may obtain a copy of the License at |
|
| 6 |
+// |
|
| 7 |
+// https://www.apache.org/licenses/LICENSE-2.0 |
|
| 8 |
+// |
|
| 9 |
+// Unless required by applicable law or agreed to in writing, software |
|
| 10 |
+// distributed under the License is distributed on an "AS IS" BASIS, |
|
| 11 |
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
| 12 |
+// See the License for the specific language governing permissions and |
|
| 13 |
+// limitations under the License. |
|
| 14 |
+ |
|
| 1 | 15 |
package digest |
| 2 | 16 |
|
| 3 | 17 |
import ( |
| ... | ... |
@@ -31,16 +45,21 @@ func NewDigest(alg Algorithm, h hash.Hash) Digest {
|
| 31 | 31 |
// functions. This is also useful for rebuilding digests from binary |
| 32 | 32 |
// serializations. |
| 33 | 33 |
func NewDigestFromBytes(alg Algorithm, p []byte) Digest {
|
| 34 |
- return Digest(fmt.Sprintf("%s:%x", alg, p))
|
|
| 34 |
+ return NewDigestFromEncoded(alg, alg.Encode(p)) |
|
| 35 | 35 |
} |
| 36 | 36 |
|
| 37 |
-// NewDigestFromHex returns a Digest from alg and a the hex encoded digest. |
|
| 37 |
+// NewDigestFromHex is deprecated. Please use NewDigestFromEncoded. |
|
| 38 | 38 |
func NewDigestFromHex(alg, hex string) Digest {
|
| 39 |
- return Digest(fmt.Sprintf("%s:%s", alg, hex))
|
|
| 39 |
+ return NewDigestFromEncoded(Algorithm(alg), hex) |
|
| 40 |
+} |
|
| 41 |
+ |
|
| 42 |
+// NewDigestFromEncoded returns a Digest from alg and the encoded digest. |
|
| 43 |
+func NewDigestFromEncoded(alg Algorithm, encoded string) Digest {
|
|
| 44 |
+ return Digest(fmt.Sprintf("%s:%s", alg, encoded))
|
|
| 40 | 45 |
} |
| 41 | 46 |
|
| 42 | 47 |
// DigestRegexp matches valid digest types. |
| 43 |
-var DigestRegexp = regexp.MustCompile(`[a-zA-Z0-9-_+.]+:[a-fA-F0-9]+`) |
|
| 48 |
+var DigestRegexp = regexp.MustCompile(`[a-z0-9]+(?:[.+_-][a-z0-9]+)*:[a-zA-Z0-9=_-]+`) |
|
| 44 | 49 |
|
| 45 | 50 |
// DigestRegexpAnchored matches valid digest types, anchored to the start and end of the match. |
| 46 | 51 |
var DigestRegexpAnchored = regexp.MustCompile(`^` + DigestRegexp.String() + `$`) |
| ... | ... |
@@ -82,26 +101,18 @@ func FromString(s string) Digest {
|
| 82 | 82 |
// error if not. |
| 83 | 83 |
func (d Digest) Validate() error {
|
| 84 | 84 |
s := string(d) |
| 85 |
- |
|
| 86 | 85 |
i := strings.Index(s, ":") |
| 87 |
- |
|
| 88 |
- // validate i then run through regexp |
|
| 89 |
- if i < 0 || i+1 == len(s) || !DigestRegexpAnchored.MatchString(s) {
|
|
| 86 |
+ if i <= 0 || i+1 == len(s) {
|
|
| 90 | 87 |
return ErrDigestInvalidFormat |
| 91 | 88 |
} |
| 92 |
- |
|
| 93 |
- algorithm := Algorithm(s[:i]) |
|
| 89 |
+ algorithm, encoded := Algorithm(s[:i]), s[i+1:] |
|
| 94 | 90 |
if !algorithm.Available() {
|
| 91 |
+ if !DigestRegexpAnchored.MatchString(s) {
|
|
| 92 |
+ return ErrDigestInvalidFormat |
|
| 93 |
+ } |
|
| 95 | 94 |
return ErrDigestUnsupported |
| 96 | 95 |
} |
| 97 |
- |
|
| 98 |
- // Digests much always be hex-encoded, ensuring that their hex portion will |
|
| 99 |
- // always be size*2 |
|
| 100 |
- if algorithm.Size()*2 != len(s[i+1:]) {
|
|
| 101 |
- return ErrDigestInvalidLength |
|
| 102 |
- } |
|
| 103 |
- |
|
| 104 |
- return nil |
|
| 96 |
+ return algorithm.Validate(encoded) |
|
| 105 | 97 |
} |
| 106 | 98 |
|
| 107 | 99 |
// Algorithm returns the algorithm portion of the digest. This will panic if |
| ... | ... |
@@ -119,12 +130,17 @@ func (d Digest) Verifier() Verifier {
|
| 119 | 119 |
} |
| 120 | 120 |
} |
| 121 | 121 |
|
| 122 |
-// Hex returns the hex digest portion of the digest. This will panic if the |
|
| 122 |
+// Encoded returns the encoded portion of the digest. This will panic if the |
|
| 123 | 123 |
// underlying digest is not in a valid format. |
| 124 |
-func (d Digest) Hex() string {
|
|
| 124 |
+func (d Digest) Encoded() string {
|
|
| 125 | 125 |
return string(d[d.sepIndex()+1:]) |
| 126 | 126 |
} |
| 127 | 127 |
|
| 128 |
+// Hex is deprecated. Please use Digest.Encoded. |
|
| 129 |
+func (d Digest) Hex() string {
|
|
| 130 |
+ return d.Encoded() |
|
| 131 |
+} |
|
| 132 |
+ |
|
| 128 | 133 |
func (d Digest) String() string {
|
| 129 | 134 |
return string(d) |
| 130 | 135 |
} |
| ... | ... |
@@ -1,3 +1,17 @@ |
| 1 |
+// Copyright 2017 Docker, Inc. |
|
| 2 |
+// |
|
| 3 |
+// Licensed under the Apache License, Version 2.0 (the "License"); |
|
| 4 |
+// you may not use this file except in compliance with the License. |
|
| 5 |
+// You may obtain a copy of the License at |
|
| 6 |
+// |
|
| 7 |
+// https://www.apache.org/licenses/LICENSE-2.0 |
|
| 8 |
+// |
|
| 9 |
+// Unless required by applicable law or agreed to in writing, software |
|
| 10 |
+// distributed under the License is distributed on an "AS IS" BASIS, |
|
| 11 |
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
| 12 |
+// See the License for the specific language governing permissions and |
|
| 13 |
+// limitations under the License. |
|
| 14 |
+ |
|
| 1 | 15 |
package digest |
| 2 | 16 |
|
| 3 | 17 |
import "hash" |
| ... | ... |
@@ -1,3 +1,17 @@ |
| 1 |
+// Copyright 2017 Docker, Inc. |
|
| 2 |
+// |
|
| 3 |
+// Licensed under the Apache License, Version 2.0 (the "License"); |
|
| 4 |
+// you may not use this file except in compliance with the License. |
|
| 5 |
+// You may obtain a copy of the License at |
|
| 6 |
+// |
|
| 7 |
+// https://www.apache.org/licenses/LICENSE-2.0 |
|
| 8 |
+// |
|
| 9 |
+// Unless required by applicable law or agreed to in writing, software |
|
| 10 |
+// distributed under the License is distributed on an "AS IS" BASIS, |
|
| 11 |
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
| 12 |
+// See the License for the specific language governing permissions and |
|
| 13 |
+// limitations under the License. |
|
| 14 |
+ |
|
| 1 | 15 |
// Package digest provides a generalized type to opaquely represent message |
| 2 | 16 |
// digests and their operations within the registry. The Digest type is |
| 3 | 17 |
// designed to serve as a flexible identifier in a content-addressable system. |
| ... | ... |
@@ -1,3 +1,17 @@ |
| 1 |
+// Copyright 2017 Docker, Inc. |
|
| 2 |
+// |
|
| 3 |
+// Licensed under the Apache License, Version 2.0 (the "License"); |
|
| 4 |
+// you may not use this file except in compliance with the License. |
|
| 5 |
+// You may obtain a copy of the License at |
|
| 6 |
+// |
|
| 7 |
+// https://www.apache.org/licenses/LICENSE-2.0 |
|
| 8 |
+// |
|
| 9 |
+// Unless required by applicable law or agreed to in writing, software |
|
| 10 |
+// distributed under the License is distributed on an "AS IS" BASIS, |
|
| 11 |
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
| 12 |
+// See the License for the specific language governing permissions and |
|
| 13 |
+// limitations under the License. |
|
| 14 |
+ |
|
| 1 | 15 |
package digest |
| 2 | 16 |
|
| 3 | 17 |
import ( |