2022-07-07 20:11:50 +00:00
|
|
|
// Copyright 2017 The Go Authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
package algorithm
|
|
|
|
|
|
|
|
import (
|
|
|
|
"crypto"
|
|
|
|
"fmt"
|
|
|
|
"hash"
|
|
|
|
)
|
|
|
|
|
|
|
|
// Hash is an official hash function algorithm. See RFC 4880, section 9.4.
|
|
|
|
type Hash interface {
|
|
|
|
// Id returns the algorithm ID, as a byte, of Hash.
|
|
|
|
Id() uint8
|
|
|
|
// Available reports whether the given hash function is linked into the binary.
|
|
|
|
Available() bool
|
|
|
|
// HashFunc simply returns the value of h so that Hash implements SignerOpts.
|
|
|
|
HashFunc() crypto.Hash
|
|
|
|
// New returns a new hash.Hash calculating the given hash function. New
|
|
|
|
// panics if the hash function is not linked into the binary.
|
|
|
|
New() hash.Hash
|
|
|
|
// Size returns the length, in bytes, of a digest resulting from the given
|
|
|
|
// hash function. It doesn't require that the hash function in question be
|
|
|
|
// linked into the program.
|
|
|
|
Size() int
|
|
|
|
// String is the name of the hash function corresponding to the given
|
|
|
|
// OpenPGP hash id.
|
|
|
|
String() string
|
|
|
|
}
|
|
|
|
|
|
|
|
// The following vars mirror the crypto/Hash supported hash functions.
|
|
|
|
var (
|
2024-10-16 10:54:40 +00:00
|
|
|
SHA1 Hash = cryptoHash{2, crypto.SHA1}
|
|
|
|
SHA256 Hash = cryptoHash{8, crypto.SHA256}
|
|
|
|
SHA384 Hash = cryptoHash{9, crypto.SHA384}
|
|
|
|
SHA512 Hash = cryptoHash{10, crypto.SHA512}
|
|
|
|
SHA224 Hash = cryptoHash{11, crypto.SHA224}
|
|
|
|
SHA3_256 Hash = cryptoHash{12, crypto.SHA3_256}
|
|
|
|
SHA3_512 Hash = cryptoHash{14, crypto.SHA3_512}
|
2022-07-07 20:11:50 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// HashById represents the different hash functions specified for OpenPGP. See
|
|
|
|
// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-14
|
|
|
|
var (
|
|
|
|
HashById = map[uint8]Hash{
|
2024-10-16 10:54:40 +00:00
|
|
|
SHA256.Id(): SHA256,
|
|
|
|
SHA384.Id(): SHA384,
|
|
|
|
SHA512.Id(): SHA512,
|
|
|
|
SHA224.Id(): SHA224,
|
|
|
|
SHA3_256.Id(): SHA3_256,
|
|
|
|
SHA3_512.Id(): SHA3_512,
|
2022-07-07 20:11:50 +00:00
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
// cryptoHash contains pairs relating OpenPGP's hash identifier with
|
|
|
|
// Go's crypto.Hash type. See RFC 4880, section 9.4.
|
|
|
|
type cryptoHash struct {
|
|
|
|
id uint8
|
|
|
|
crypto.Hash
|
|
|
|
}
|
|
|
|
|
|
|
|
// Id returns the algorithm ID, as a byte, of cryptoHash.
|
|
|
|
func (h cryptoHash) Id() uint8 {
|
|
|
|
return h.id
|
|
|
|
}
|
|
|
|
|
|
|
|
var hashNames = map[uint8]string{
|
2024-10-16 10:54:40 +00:00
|
|
|
SHA256.Id(): "SHA256",
|
|
|
|
SHA384.Id(): "SHA384",
|
|
|
|
SHA512.Id(): "SHA512",
|
|
|
|
SHA224.Id(): "SHA224",
|
|
|
|
SHA3_256.Id(): "SHA3-256",
|
|
|
|
SHA3_512.Id(): "SHA3-512",
|
2022-07-07 20:11:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (h cryptoHash) String() string {
|
|
|
|
s, ok := hashNames[h.id]
|
|
|
|
if !ok {
|
|
|
|
panic(fmt.Sprintf("Unsupported hash function %d", h.id))
|
|
|
|
}
|
|
|
|
return s
|
|
|
|
}
|
2024-10-16 10:54:40 +00:00
|
|
|
|
|
|
|
// HashIdToHash returns a crypto.Hash which corresponds to the given OpenPGP
|
|
|
|
// hash id.
|
|
|
|
func HashIdToHash(id byte) (h crypto.Hash, ok bool) {
|
|
|
|
if hash, ok := HashById[id]; ok {
|
|
|
|
return hash.HashFunc(), true
|
|
|
|
}
|
|
|
|
return 0, false
|
|
|
|
}
|
|
|
|
|
|
|
|
// HashIdToHashWithSha1 returns a crypto.Hash which corresponds to the given OpenPGP
|
|
|
|
// hash id, allowing sha1.
|
|
|
|
func HashIdToHashWithSha1(id byte) (h crypto.Hash, ok bool) {
|
|
|
|
if hash, ok := HashById[id]; ok {
|
|
|
|
return hash.HashFunc(), true
|
|
|
|
}
|
|
|
|
|
|
|
|
if id == SHA1.Id() {
|
|
|
|
return SHA1.HashFunc(), true
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0, false
|
|
|
|
}
|
|
|
|
|
|
|
|
// HashIdToString returns the name of the hash function corresponding to the
|
|
|
|
// given OpenPGP hash id.
|
|
|
|
func HashIdToString(id byte) (name string, ok bool) {
|
|
|
|
if hash, ok := HashById[id]; ok {
|
|
|
|
return hash.String(), true
|
|
|
|
}
|
|
|
|
return "", false
|
|
|
|
}
|
|
|
|
|
|
|
|
// HashToHashId returns an OpenPGP hash id which corresponds the given Hash.
|
|
|
|
func HashToHashId(h crypto.Hash) (id byte, ok bool) {
|
|
|
|
for id, hash := range HashById {
|
|
|
|
if hash.HashFunc() == h {
|
|
|
|
return id, true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0, false
|
|
|
|
}
|
|
|
|
|
|
|
|
// HashToHashIdWithSha1 returns an OpenPGP hash id which corresponds the given Hash,
|
|
|
|
// allowing instances of SHA1
|
|
|
|
func HashToHashIdWithSha1(h crypto.Hash) (id byte, ok bool) {
|
|
|
|
for id, hash := range HashById {
|
|
|
|
if hash.HashFunc() == h {
|
|
|
|
return id, true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if h == SHA1.HashFunc() {
|
|
|
|
return SHA1.Id(), true
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0, false
|
|
|
|
}
|