You've already forked go-digest
mirror of
https://github.com/opencontainers/go-digest.git
synced 2025-07-30 00:21:10 +03:00
disallow upper characters (/A-F/) in hex-encoded portion
Signed-off-by: Akihiro Suda <suda.akihiro@lab.ntt.co.jp>
This commit is contained in:
32
algorithm.go
32
algorithm.go
@ -19,6 +19,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"hash"
|
"hash"
|
||||||
"io"
|
"io"
|
||||||
|
"regexp"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Algorithm identifies and implementation of a digester by an identifier.
|
// Algorithm identifies and implementation of a digester by an identifier.
|
||||||
@ -28,9 +29,9 @@ type Algorithm string
|
|||||||
|
|
||||||
// supported digest types
|
// supported digest types
|
||||||
const (
|
const (
|
||||||
SHA256 Algorithm = "sha256" // sha256 with hex encoding
|
SHA256 Algorithm = "sha256" // sha256 with hex encoding (lower case only)
|
||||||
SHA384 Algorithm = "sha384" // sha384 with hex encoding
|
SHA384 Algorithm = "sha384" // sha384 with hex encoding (lower case only)
|
||||||
SHA512 Algorithm = "sha512" // sha512 with hex encoding
|
SHA512 Algorithm = "sha512" // sha512 with hex encoding (lower case only)
|
||||||
|
|
||||||
// Canonical is the primary digest algorithm used with the distribution
|
// Canonical is the primary digest algorithm used with the distribution
|
||||||
// project. Other digests may be used but this one is the primary storage
|
// project. Other digests may be used but this one is the primary storage
|
||||||
@ -50,6 +51,14 @@ var (
|
|||||||
SHA384: crypto.SHA384,
|
SHA384: crypto.SHA384,
|
||||||
SHA512: crypto.SHA512,
|
SHA512: crypto.SHA512,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// anchoredEncodedRegexps contains anchored regular expressions for hex-encoded digests.
|
||||||
|
// Note that /A-F/ disallowed.
|
||||||
|
anchoredEncodedRegexps = map[Algorithm]*regexp.Regexp{
|
||||||
|
SHA256: regexp.MustCompile(`^[a-f0-9]{64}$`),
|
||||||
|
SHA384: regexp.MustCompile(`^[a-f0-9]{96}$`),
|
||||||
|
SHA512: regexp.MustCompile(`^[a-f0-9]{128}$`),
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// Available returns true if the digest type is available for use. If this
|
// Available returns true if the digest type is available for use. If this
|
||||||
@ -164,3 +173,20 @@ func (a Algorithm) FromBytes(p []byte) Digest {
|
|||||||
func (a Algorithm) FromString(s string) Digest {
|
func (a Algorithm) FromString(s string) Digest {
|
||||||
return a.FromBytes([]byte(s))
|
return a.FromBytes([]byte(s))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Validate validates the encoded portion string
|
||||||
|
func (a Algorithm) Validate(encoded string) error {
|
||||||
|
r, ok := anchoredEncodedRegexps[a]
|
||||||
|
if !ok {
|
||||||
|
return ErrDigestUnsupported
|
||||||
|
}
|
||||||
|
// Digests much always be hex-encoded, ensuring that their hex portion will
|
||||||
|
// always be size*2
|
||||||
|
if a.Size()*2 != len(encoded) {
|
||||||
|
return ErrDigestInvalidLength
|
||||||
|
}
|
||||||
|
if r.MatchString(encoded) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return ErrDigestInvalidFormat
|
||||||
|
}
|
||||||
|
20
digest.go
20
digest.go
@ -101,26 +101,18 @@ func FromString(s string) Digest {
|
|||||||
// error if not.
|
// error if not.
|
||||||
func (d Digest) Validate() error {
|
func (d Digest) Validate() error {
|
||||||
s := string(d)
|
s := string(d)
|
||||||
|
|
||||||
i := strings.Index(s, ":")
|
i := strings.Index(s, ":")
|
||||||
|
if i <= 0 || i+1 == len(s) {
|
||||||
// validate i then run through regexp
|
|
||||||
if i < 0 || i+1 == len(s) || !DigestRegexpAnchored.MatchString(s) {
|
|
||||||
return ErrDigestInvalidFormat
|
return ErrDigestInvalidFormat
|
||||||
}
|
}
|
||||||
|
algorithm, encoded := Algorithm(s[:i]), s[i+1:]
|
||||||
algorithm := Algorithm(s[:i])
|
|
||||||
if !algorithm.Available() {
|
if !algorithm.Available() {
|
||||||
|
if !DigestRegexpAnchored.MatchString(s) {
|
||||||
|
return ErrDigestInvalidFormat
|
||||||
|
}
|
||||||
return ErrDigestUnsupported
|
return ErrDigestUnsupported
|
||||||
}
|
}
|
||||||
|
return algorithm.Validate(encoded)
|
||||||
// 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
|
// Algorithm returns the algorithm portion of the digest. This will panic if
|
||||||
|
@ -93,6 +93,10 @@ func TestParseDigest(t *testing.T) {
|
|||||||
encoded: "LCa0a2j_xo_5m0U8HTBBNBNCLXBkg7-g-YpeiGJm564",
|
encoded: "LCa0a2j_xo_5m0U8HTBBNBNCLXBkg7-g-YpeiGJm564",
|
||||||
err: ErrDigestUnsupported,
|
err: ErrDigestUnsupported,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
input: "sha256:E58FCF7418D4390DEC8E8FB69D88C06EC07039D651FEDD3AA72AF9972E7D046B",
|
||||||
|
err: ErrDigestInvalidFormat,
|
||||||
|
},
|
||||||
} {
|
} {
|
||||||
digest, err := Parse(testcase.input)
|
digest, err := Parse(testcase.input)
|
||||||
if err != testcase.err {
|
if err != testcase.err {
|
||||||
|
Reference in New Issue
Block a user