mirror of
https://github.com/mainflux/mainflux.git
synced 2025-05-04 22:17:59 +08:00

* Use normalizer as stream source Renamed 'writer' service to 'normalizer' and dropped Cassandra facilities from it. Extracted the common dependencies to 'mainflux' package for easier sharing. Fixed the API docs and unified environment variables. Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Use docker build arguments to specify build Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Remove cassandra libraries Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Update go-kit version to 0.6.0 Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Fix manager configuration Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Refactor docker-compose Merged individual compose files and dropped external links. Remove CoAP container since it is not referenced from NginX config at the moment. Update port mapping in compose and nginx.conf. Dropped bin scripts. Updated service documentation. Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Drop content-type check Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Implement users data access layer in PostgreSQL Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Bump version to 0.1.0 Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Use go-kit logger everywhere (except CoAP) Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Improve factory methods naming Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Implement clients data access layer on PostgreSQL Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Make tests stateless All tests are refactored to use map-based table-driven tests. No cross-tests dependencies is present anymore. Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Remove gitignore Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Fix nginx proxying Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Mark client-user FK explicit Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Update API documentation Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Update channel model Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Add channel PostgreSQL repository tests Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Implement PostgreSQL channels DAO Replaced update queries with raw SQL. Explicitly defined M2M table due to difficulties of ensuring the referential integrity through GORM. Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Expose connection endpoints Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Fix swagger docs and remove DB logging Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Fix nested query remarks Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Add unique indices Signed-off-by: Dejan Mijic <dejan@mainflux.com>
193 lines
5.7 KiB
Go
193 lines
5.7 KiB
Go
// Copyright 2017 Docker, Inc.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// https://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package digest
|
|
|
|
import (
|
|
"crypto"
|
|
"fmt"
|
|
"hash"
|
|
"io"
|
|
"regexp"
|
|
)
|
|
|
|
// 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 (lower case only)
|
|
SHA384 Algorithm = "sha384" // sha384 with hex encoding (lower case only)
|
|
SHA512 Algorithm = "sha512" // sha512 with hex encoding (lower case only)
|
|
|
|
// 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,
|
|
}
|
|
|
|
// 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
|
|
// 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()
|
|
}
|
|
|
|
// Encode encodes the raw bytes of a digest, typically from a hash.Hash, into
|
|
// the encoded portion of the digest.
|
|
func (a Algorithm) Encode(d []byte) string {
|
|
// TODO(stevvooe): Currently, all algorithms use a hex encoding. When we
|
|
// add support for back registration, we can modify this accordingly.
|
|
return fmt.Sprintf("%x", d)
|
|
}
|
|
|
|
// 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))
|
|
}
|
|
|
|
// 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
|
|
}
|