main
1// Copyright 2017 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package algorithm
6
7import (
8 "crypto"
9 "fmt"
10 "hash"
11)
12
13// Hash is an official hash function algorithm. See RFC 4880, section 9.4.
14type Hash interface {
15 // Id returns the algorithm ID, as a byte, of Hash.
16 Id() uint8
17 // Available reports whether the given hash function is linked into the binary.
18 Available() bool
19 // HashFunc simply returns the value of h so that Hash implements SignerOpts.
20 HashFunc() crypto.Hash
21 // New returns a new hash.Hash calculating the given hash function. New
22 // panics if the hash function is not linked into the binary.
23 New() hash.Hash
24 // Size returns the length, in bytes, of a digest resulting from the given
25 // hash function. It doesn't require that the hash function in question be
26 // linked into the program.
27 Size() int
28 // String is the name of the hash function corresponding to the given
29 // OpenPGP hash id.
30 String() string
31}
32
33// The following vars mirror the crypto/Hash supported hash functions.
34var (
35 SHA1 Hash = cryptoHash{2, crypto.SHA1}
36 SHA256 Hash = cryptoHash{8, crypto.SHA256}
37 SHA384 Hash = cryptoHash{9, crypto.SHA384}
38 SHA512 Hash = cryptoHash{10, crypto.SHA512}
39 SHA224 Hash = cryptoHash{11, crypto.SHA224}
40 SHA3_256 Hash = cryptoHash{12, crypto.SHA3_256}
41 SHA3_512 Hash = cryptoHash{14, crypto.SHA3_512}
42)
43
44// HashById represents the different hash functions specified for OpenPGP. See
45// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-14
46var (
47 HashById = map[uint8]Hash{
48 SHA256.Id(): SHA256,
49 SHA384.Id(): SHA384,
50 SHA512.Id(): SHA512,
51 SHA224.Id(): SHA224,
52 SHA3_256.Id(): SHA3_256,
53 SHA3_512.Id(): SHA3_512,
54 }
55)
56
57// cryptoHash contains pairs relating OpenPGP's hash identifier with
58// Go's crypto.Hash type. See RFC 4880, section 9.4.
59type cryptoHash struct {
60 id uint8
61 crypto.Hash
62}
63
64// Id returns the algorithm ID, as a byte, of cryptoHash.
65func (h cryptoHash) Id() uint8 {
66 return h.id
67}
68
69var hashNames = map[uint8]string{
70 SHA256.Id(): "SHA256",
71 SHA384.Id(): "SHA384",
72 SHA512.Id(): "SHA512",
73 SHA224.Id(): "SHA224",
74 SHA3_256.Id(): "SHA3-256",
75 SHA3_512.Id(): "SHA3-512",
76}
77
78func (h cryptoHash) String() string {
79 s, ok := hashNames[h.id]
80 if !ok {
81 panic(fmt.Sprintf("Unsupported hash function %d", h.id))
82 }
83 return s
84}
85
86// HashIdToHash returns a crypto.Hash which corresponds to the given OpenPGP
87// hash id.
88func HashIdToHash(id byte) (h crypto.Hash, ok bool) {
89 if hash, ok := HashById[id]; ok {
90 return hash.HashFunc(), true
91 }
92 return 0, false
93}
94
95// HashIdToHashWithSha1 returns a crypto.Hash which corresponds to the given OpenPGP
96// hash id, allowing sha1.
97func HashIdToHashWithSha1(id byte) (h crypto.Hash, ok bool) {
98 if hash, ok := HashById[id]; ok {
99 return hash.HashFunc(), true
100 }
101
102 if id == SHA1.Id() {
103 return SHA1.HashFunc(), true
104 }
105
106 return 0, false
107}
108
109// HashIdToString returns the name of the hash function corresponding to the
110// given OpenPGP hash id.
111func HashIdToString(id byte) (name string, ok bool) {
112 if hash, ok := HashById[id]; ok {
113 return hash.String(), true
114 }
115 return "", false
116}
117
118// HashToHashId returns an OpenPGP hash id which corresponds the given Hash.
119func HashToHashId(h crypto.Hash) (id byte, ok bool) {
120 for id, hash := range HashById {
121 if hash.HashFunc() == h {
122 return id, true
123 }
124 }
125
126 return 0, false
127}
128
129// HashToHashIdWithSha1 returns an OpenPGP hash id which corresponds the given Hash,
130// allowing instances of SHA1
131func HashToHashIdWithSha1(h crypto.Hash) (id byte, ok bool) {
132 for id, hash := range HashById {
133 if hash.HashFunc() == h {
134 return id, true
135 }
136 }
137
138 if h == SHA1.HashFunc() {
139 return SHA1.Id(), true
140 }
141
142 return 0, false
143}