File: hash.go

package info (click to toggle)
golang-github-juju-utils 0.0~git20171220.f38c0b0-5
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 1,748 kB
  • sloc: makefile: 20
file content (76 lines) | stat: -rw-r--r-- 2,261 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
// Copyright 2016 Canonical Ltd.
// Licensed under the LGPLv3, see LICENCE file for details.

// The hash package provides utilities that support use of the stdlib
// hash.Hash. Most notably is the Fingerprint type that wraps the
// checksum of a hash.
//
// Conversion between checksums and strings are facailitated through
// Fingerprint.
//
// Here are some hash-related recipes that bring it all together:
//
// * Extract the SHA384 hash while writing to elsewhere, then get the
//   raw checksum:
//
//     newHash, _ := hash.SHA384()
//     h := newHash()
//     hashingWriter := io.MultiWriter(writer, h)
//     if err := writeAll(hashingWriter); err != nil { ... }
//     fp := hash.NewValidFingerprint(h)
//     checksum := fp.Bytes()
//
// * Extract the SHA384 hash while reading from elsewhere, then get the
//   hex-encoded checksum to send over the wire:
//
//     newHash, _ := hash.SHA384()
//     h := newHash()
//     hashingReader := io.TeeReader(reader, h)
//     if err := processStream(hashingReader); err != nil { ... }
//     fp := hash.NewValidFingerprint(h)
//     hexSum := fp.Hex()
//     req.Header.Set("Content-Sha384", hexSum)
//
// * Turn a checksum sent over the wire back into a fingerprint:
//
//     _, validate := hash.SHA384()
//     hexSum := req.Header.Get("Content-Sha384")
//     var fp hash.Fingerprint
//     if len(hexSum) != 0 {
//         fp, err = hash.ParseHexFingerprint(hexSum, validate)
//         ...
//     }
//     if fp.IsZero() {
//         ...
//     }
package hash

import (
	"crypto/sha512"
	"hash"

	"github.com/juju/errors"
	"github.com/juju/loggo"
)

var logger = loggo.GetLogger("utils.hash")

// SHA384 returns the newHash and validate functions for use
// with SHA384 hashes. SHA384 is used in several key places in Juju.
func SHA384() (newHash func() hash.Hash, validate func([]byte) error) {
	const digestLenBytes = 384 / 8
	validate = newSizeChecker(digestLenBytes)
	return sha512.New384, validate
}

func newSizeChecker(size int) func([]byte) error {
	return func(sum []byte) error {
		if len(sum) < size {
			return errors.NewNotValid(nil, "invalid fingerprint (too small)")
		}
		if len(sum) > size {
			return errors.NewNotValid(nil, "invalid fingerprint (too big)")
		}
		return nil
	}
}