init: v1.0.0
This commit is contained in:
+101
@@ -0,0 +1,101 @@
|
||||
package sm
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"hash"
|
||||
)
|
||||
|
||||
// Hash identifies a cryptographic hash function that is implemented in another
|
||||
// package.
|
||||
// I try to keep it consistent with the standard library
|
||||
type Hash struct {
|
||||
crypto.Hash
|
||||
}
|
||||
|
||||
// HashFunc simply returns the value of h so that Hash implements SignerOpts.
|
||||
func (h Hash) HashFunc() crypto.Hash {
|
||||
return h.Hash
|
||||
}
|
||||
|
||||
func (h Hash) String() string {
|
||||
switch h {
|
||||
case SM3:
|
||||
return "SM3"
|
||||
case SM3WithID:
|
||||
return "SM3WithID"
|
||||
default:
|
||||
// return ""
|
||||
return h.Hash.String()
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
SM3 Hash
|
||||
SM3WithID Hash
|
||||
maxHash Hash
|
||||
)
|
||||
var SHA1 = Hash{crypto.SHA1}
|
||||
var SHA256 = Hash{crypto.SHA256}
|
||||
|
||||
func init() {
|
||||
// A hack to get the maxHash in crypto.
|
||||
i := new(crypto.Hash)
|
||||
*i = 1
|
||||
defer func() {
|
||||
_ = recover()
|
||||
SM3 = Hash{Hash: *i}
|
||||
SM3WithID = Hash{Hash: *i + 1}
|
||||
maxHash = Hash{Hash: *i + 2}
|
||||
}()
|
||||
for {
|
||||
(*i).Size()
|
||||
*i++
|
||||
}
|
||||
}
|
||||
|
||||
// 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.
|
||||
func (h Hash) Size() int {
|
||||
switch h {
|
||||
case SM3, SM3WithID:
|
||||
return 32
|
||||
default:
|
||||
return h.Hash.Size()
|
||||
}
|
||||
}
|
||||
|
||||
var hashes = make(map[Hash]func() hash.Hash)
|
||||
|
||||
// New returns a new hash.Hash calculating the given hash function. New panics
|
||||
// if the hash function is not linked into the binary.
|
||||
func (h Hash) New() hash.Hash {
|
||||
if h.Hash >= SM3.Hash && h.Hash < maxHash.Hash {
|
||||
f := hashes[h]
|
||||
if f != nil {
|
||||
return f()
|
||||
}
|
||||
}
|
||||
return h.Hash.New()
|
||||
}
|
||||
|
||||
// Available reports whether the given hash function is linked into the binary.
|
||||
func (h Hash) Available() bool {
|
||||
if h.Hash >= SM3.Hash && h.Hash < maxHash.Hash {
|
||||
return true
|
||||
}
|
||||
return h.Hash.Available()
|
||||
}
|
||||
|
||||
// RegisterHash registers a function that returns a new instance of the given
|
||||
// hash function. This is intended to be called from the init function in
|
||||
// packages that implement hash functions.
|
||||
func RegisterHash(h Hash, f func() hash.Hash) {
|
||||
if h.Hash >= maxHash.Hash {
|
||||
panic("crypto: RegisterHash of unknown hash function")
|
||||
}
|
||||
// if h.Hash < SM3.Hash {
|
||||
// crypto.RegisterHash(h.Hash, f)
|
||||
// }
|
||||
hashes[h] = f
|
||||
}
|
||||
Reference in New Issue
Block a user