Skip to content

Commit

Permalink
descriptor: sha{256,512}: disallow /[A-F]/ characters
Browse files Browse the repository at this point in the history
Signed-off-by: Akihiro Suda <suda.akihiro@lab.ntt.co.jp>
  • Loading branch information
AkihiroSuda committed May 10, 2017
1 parent a7d6fe6 commit b030295
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 2 deletions.
9 changes: 9 additions & 0 deletions descriptor.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ algorithm-separator := /[+._-]/
encoded := /[a-zA-Z0-9=_-]+/
```

Note that _algorithm_ MAY impose algorithm-specific restriction on the grammar of the _encoded_ portion.
See also [Registered Algorithms](#registered-identifiers).

Some example digest strings include the following:

digest | algorithm | Supported |
Expand Down Expand Up @@ -137,11 +140,17 @@ If a useful algorithm is not included in the above table, it SHOULD be submitted
[SHA-256][rfc4634-s4.1] is a collision-resistant hash function, chosen for ubiquity, reasonable size and secure characteristics.
Implementations MUST implement SHA-256 digest verification for use in descriptors.

When the _algorithm identifier_ is `sha256`, the _encoded_ portion MUST match `/[a-f0-9]{64}/`.
Note that `[A-F]` MUST NOT be used here.

#### SHA-512

[SHA-512][rfc4634-s4.2] is a collision-resistant hash function which [may be more perfomant][sha256-vs-sha512] than [SHA-256](#sha-256) on some CPUs.
Implementations MAY implement SHA-512 digest verification for use in descriptors.

When the _algorithm identifier_ is `sha512`, the _encoded_ portion MUST match `/[a-f0-9]{128}/`.
Note that `[A-F]` MUST NOT be used here.

## Examples

The following example describes a [_Manifest_](manifest.md#image-manifest) with a content identifier of "sha256:5b0bcabd1ed22e9fb1310cf6c2dec7cdef19f0ad69efa1f392e94a4333501270" and a size of 7682 bytes:
Expand Down
3 changes: 2 additions & 1 deletion schema/descriptor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ func TestDescriptor(t *testing.T) {
fail: true,
},

// expected failure: digest does not match pattern (invalid hash characters)
// expected failure: digest does not match pattern (characters needs to be lower for sha256)
{
descriptor: `
{
Expand All @@ -200,6 +200,7 @@ func TestDescriptor(t *testing.T) {
"digest": "sha256:5B0BCABD1ED22E9FB1310CF6C2DEC7CDEF19F0AD69EFA1F392E94A4333501270"
}
`,
fail: true,
},

// expected success: valid URL entry
Expand Down
41 changes: 40 additions & 1 deletion schema/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ import (
"fmt"
"io"
"io/ioutil"
"regexp"

digest "github.com/opencontainers/go-digest"
"github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
"github.com/xeipuuv/gojsonschema"
Expand All @@ -33,7 +35,8 @@ type Validator string
type validateDescendantsFunc func(r io.Reader) error

var mapValidateDescendants = map[Validator]validateDescendantsFunc{
ValidatorMediaTypeManifest: validateManifestDescendants,
ValidatorMediaTypeManifest: validateManifestDescendants,
ValidatorMediaTypeDescriptor: validateDescriptorDescendants,
}

// ValidationError contains all the errors that happened during validation.
Expand Down Expand Up @@ -119,3 +122,39 @@ func validateManifestDescendants(r io.Reader) error {
}
return nil
}

var (
sha256EncodedRegexp = regexp.MustCompile(`^[a-f0-9]{64}$`)
sha512EncodedRegexp = regexp.MustCompile(`^[a-f0-9]{128}$`)
)

func validateDescriptorDescendants(r io.Reader) error {
header := v1.Descriptor{}

buf, err := ioutil.ReadAll(r)
if err != nil {
return errors.Wrapf(err, "error reading the io stream")
}

err = json.Unmarshal(buf, &header)
if err != nil {
return errors.Wrap(err, "descriptor format mismatch")
}

if header.Digest.Validate() != nil {
// we ignore unsupported algorithms
fmt.Printf("warning: unsupported digest: %q", header.Digest)
return nil
}
switch header.Digest.Algorithm() {
case digest.SHA256:
if !sha256EncodedRegexp.MatchString(header.Digest.Hex()) {
return errors.Errorf("unexpected sha256 digest: %q", header.Digest)
}
case digest.SHA512:
if !sha512EncodedRegexp.MatchString(header.Digest.Hex()) {
return errors.Errorf("unexpected sha512 digest: %q", header.Digest)
}
}
return nil
}

0 comments on commit b030295

Please sign in to comment.