"Fossies" - the Fresh Open Source Software Archive

Member "buildah-1.23.1/vendor/github.com/opencontainers/go-digest/algorithm.go" (28 Sep 2021, 5880 Bytes) of package /linux/misc/buildah-1.23.1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Go source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 // Copyright 2019, 2020 OCI Contributors
    2 // Copyright 2017 Docker, Inc.
    3 //
    4 // Licensed under the Apache License, Version 2.0 (the "License");
    5 // you may not use this file except in compliance with the License.
    6 // You may obtain a copy of the License at
    7 //
    8 //     https://www.apache.org/licenses/LICENSE-2.0
    9 //
   10 // Unless required by applicable law or agreed to in writing, software
   11 // distributed under the License is distributed on an "AS IS" BASIS,
   12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   13 // See the License for the specific language governing permissions and
   14 // limitations under the License.
   15 
   16 package digest
   17 
   18 import (
   19     "crypto"
   20     "fmt"
   21     "hash"
   22     "io"
   23     "regexp"
   24 )
   25 
   26 // Algorithm identifies and implementation of a digester by an identifier.
   27 // Note the that this defines both the hash algorithm used and the string
   28 // encoding.
   29 type Algorithm string
   30 
   31 // supported digest types
   32 const (
   33     SHA256 Algorithm = "sha256" // sha256 with hex encoding (lower case only)
   34     SHA384 Algorithm = "sha384" // sha384 with hex encoding (lower case only)
   35     SHA512 Algorithm = "sha512" // sha512 with hex encoding (lower case only)
   36 
   37     // Canonical is the primary digest algorithm used with the distribution
   38     // project. Other digests may be used but this one is the primary storage
   39     // digest.
   40     Canonical = SHA256
   41 )
   42 
   43 var (
   44     // TODO(stevvooe): Follow the pattern of the standard crypto package for
   45     // registration of digests. Effectively, we are a registerable set and
   46     // common symbol access.
   47 
   48     // algorithms maps values to hash.Hash implementations. Other algorithms
   49     // may be available but they cannot be calculated by the digest package.
   50     algorithms = map[Algorithm]crypto.Hash{
   51         SHA256: crypto.SHA256,
   52         SHA384: crypto.SHA384,
   53         SHA512: crypto.SHA512,
   54     }
   55 
   56     // anchoredEncodedRegexps contains anchored regular expressions for hex-encoded digests.
   57     // Note that /A-F/ disallowed.
   58     anchoredEncodedRegexps = map[Algorithm]*regexp.Regexp{
   59         SHA256: regexp.MustCompile(`^[a-f0-9]{64}$`),
   60         SHA384: regexp.MustCompile(`^[a-f0-9]{96}$`),
   61         SHA512: regexp.MustCompile(`^[a-f0-9]{128}$`),
   62     }
   63 )
   64 
   65 // Available returns true if the digest type is available for use. If this
   66 // returns false, Digester and Hash will return nil.
   67 func (a Algorithm) Available() bool {
   68     h, ok := algorithms[a]
   69     if !ok {
   70         return false
   71     }
   72 
   73     // check availability of the hash, as well
   74     return h.Available()
   75 }
   76 
   77 func (a Algorithm) String() string {
   78     return string(a)
   79 }
   80 
   81 // Size returns number of bytes returned by the hash.
   82 func (a Algorithm) Size() int {
   83     h, ok := algorithms[a]
   84     if !ok {
   85         return 0
   86     }
   87     return h.Size()
   88 }
   89 
   90 // Set implemented to allow use of Algorithm as a command line flag.
   91 func (a *Algorithm) Set(value string) error {
   92     if value == "" {
   93         *a = Canonical
   94     } else {
   95         // just do a type conversion, support is queried with Available.
   96         *a = Algorithm(value)
   97     }
   98 
   99     if !a.Available() {
  100         return ErrDigestUnsupported
  101     }
  102 
  103     return nil
  104 }
  105 
  106 // Digester returns a new digester for the specified algorithm. If the algorithm
  107 // does not have a digester implementation, nil will be returned. This can be
  108 // checked by calling Available before calling Digester.
  109 func (a Algorithm) Digester() Digester {
  110     return &digester{
  111         alg:  a,
  112         hash: a.Hash(),
  113     }
  114 }
  115 
  116 // Hash returns a new hash as used by the algorithm. If not available, the
  117 // method will panic. Check Algorithm.Available() before calling.
  118 func (a Algorithm) Hash() hash.Hash {
  119     if !a.Available() {
  120         // Empty algorithm string is invalid
  121         if a == "" {
  122             panic(fmt.Sprintf("empty digest algorithm, validate before calling Algorithm.Hash()"))
  123         }
  124 
  125         // NOTE(stevvooe): A missing hash is usually a programming error that
  126         // must be resolved at compile time. We don't import in the digest
  127         // package to allow users to choose their hash implementation (such as
  128         // when using stevvooe/resumable or a hardware accelerated package).
  129         //
  130         // Applications that may want to resolve the hash at runtime should
  131         // call Algorithm.Available before call Algorithm.Hash().
  132         panic(fmt.Sprintf("%v not available (make sure it is imported)", a))
  133     }
  134 
  135     return algorithms[a].New()
  136 }
  137 
  138 // Encode encodes the raw bytes of a digest, typically from a hash.Hash, into
  139 // the encoded portion of the digest.
  140 func (a Algorithm) Encode(d []byte) string {
  141     // TODO(stevvooe): Currently, all algorithms use a hex encoding. When we
  142     // add support for back registration, we can modify this accordingly.
  143     return fmt.Sprintf("%x", d)
  144 }
  145 
  146 // FromReader returns the digest of the reader using the algorithm.
  147 func (a Algorithm) FromReader(rd io.Reader) (Digest, error) {
  148     digester := a.Digester()
  149 
  150     if _, err := io.Copy(digester.Hash(), rd); err != nil {
  151         return "", err
  152     }
  153 
  154     return digester.Digest(), nil
  155 }
  156 
  157 // FromBytes digests the input and returns a Digest.
  158 func (a Algorithm) FromBytes(p []byte) Digest {
  159     digester := a.Digester()
  160 
  161     if _, err := digester.Hash().Write(p); err != nil {
  162         // Writes to a Hash should never fail. None of the existing
  163         // hash implementations in the stdlib or hashes vendored
  164         // here can return errors from Write. Having a panic in this
  165         // condition instead of having FromBytes return an error value
  166         // avoids unnecessary error handling paths in all callers.
  167         panic("write to hash function returned error: " + err.Error())
  168     }
  169 
  170     return digester.Digest()
  171 }
  172 
  173 // FromString digests the string input and returns a Digest.
  174 func (a Algorithm) FromString(s string) Digest {
  175     return a.FromBytes([]byte(s))
  176 }
  177 
  178 // Validate validates the encoded portion string
  179 func (a Algorithm) Validate(encoded string) error {
  180     r, ok := anchoredEncodedRegexps[a]
  181     if !ok {
  182         return ErrDigestUnsupported
  183     }
  184     // Digests much always be hex-encoded, ensuring that their hex portion will
  185     // always be size*2
  186     if a.Size()*2 != len(encoded) {
  187         return ErrDigestInvalidLength
  188     }
  189     if r.MatchString(encoded) {
  190         return nil
  191     }
  192     return ErrDigestInvalidFormat
  193 }