mirror of
https://github.com/safing/portbase
synced 2025-09-01 18:19:57 +00:00
Move hash package to separate repo
This commit is contained in:
parent
9d71d109b2
commit
db28b35c99
5 changed files with 0 additions and 440 deletions
|
@ -1,145 +0,0 @@
|
|||
package hash
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"crypto/sha512"
|
||||
"hash"
|
||||
|
||||
"golang.org/x/crypto/sha3"
|
||||
)
|
||||
|
||||
type Algorithm uint8
|
||||
|
||||
const (
|
||||
SHA2_224 Algorithm = 1 + iota
|
||||
SHA2_256
|
||||
SHA2_512_224
|
||||
SHA2_512_256
|
||||
SHA2_384
|
||||
SHA2_512
|
||||
SHA3_224
|
||||
SHA3_256
|
||||
SHA3_384
|
||||
SHA3_512
|
||||
BLAKE2S_256
|
||||
BLAKE2B_256
|
||||
BLAKE2B_384
|
||||
BLAKE2B_512
|
||||
)
|
||||
|
||||
var (
|
||||
attributes = map[Algorithm][]uint8{
|
||||
// block size, output size, security strength - in bytes
|
||||
SHA2_224: []uint8{64, 28, 14},
|
||||
SHA2_256: []uint8{64, 32, 16},
|
||||
SHA2_512_224: []uint8{128, 28, 14},
|
||||
SHA2_512_256: []uint8{128, 32, 16},
|
||||
SHA2_384: []uint8{128, 48, 24},
|
||||
SHA2_512: []uint8{128, 64, 32},
|
||||
SHA3_224: []uint8{144, 28, 14},
|
||||
SHA3_256: []uint8{136, 32, 16},
|
||||
SHA3_384: []uint8{104, 48, 24},
|
||||
SHA3_512: []uint8{72, 64, 32},
|
||||
BLAKE2S_256: []uint8{64, 32, 16},
|
||||
BLAKE2B_256: []uint8{128, 32, 16},
|
||||
BLAKE2B_384: []uint8{128, 48, 24},
|
||||
BLAKE2B_512: []uint8{128, 64, 32},
|
||||
}
|
||||
|
||||
functions = map[Algorithm]func() hash.Hash{
|
||||
SHA2_224: sha256.New224,
|
||||
SHA2_256: sha256.New,
|
||||
SHA2_512_224: sha512.New512_224,
|
||||
SHA2_512_256: sha512.New512_256,
|
||||
SHA2_384: sha512.New384,
|
||||
SHA2_512: sha512.New,
|
||||
SHA3_224: sha3.New224,
|
||||
SHA3_256: sha3.New256,
|
||||
SHA3_384: sha3.New384,
|
||||
SHA3_512: sha3.New512,
|
||||
BLAKE2S_256: NewBlake2s256,
|
||||
BLAKE2B_256: NewBlake2b256,
|
||||
BLAKE2B_384: NewBlake2b384,
|
||||
BLAKE2B_512: NewBlake2b512,
|
||||
}
|
||||
|
||||
// just ordered by strength and establishment, no research conducted yet.
|
||||
orderedByRecommendation = []Algorithm{
|
||||
SHA3_512, // {72, 64, 32}
|
||||
SHA2_512, // {128, 64, 32}
|
||||
BLAKE2B_512, // {128, 64, 32}
|
||||
SHA3_384, // {104, 48, 24}
|
||||
SHA2_384, // {128, 48, 24}
|
||||
BLAKE2B_384, // {128, 48, 24}
|
||||
SHA3_256, // {136, 32, 16}
|
||||
SHA2_512_256, // {128, 32, 16}
|
||||
SHA2_256, // {64, 32, 16}
|
||||
BLAKE2B_256, // {128, 32, 16}
|
||||
BLAKE2S_256, // {64, 32, 16}
|
||||
SHA3_224, // {144, 28, 14}
|
||||
SHA2_512_224, // {128, 28, 14}
|
||||
SHA2_224, // {64, 28, 14}
|
||||
}
|
||||
|
||||
// names
|
||||
names = map[Algorithm]string{
|
||||
SHA2_224: "SHA2-224",
|
||||
SHA2_256: "SHA2-256",
|
||||
SHA2_512_224: "SHA2-512/224",
|
||||
SHA2_512_256: "SHA2-512/256",
|
||||
SHA2_384: "SHA2-384",
|
||||
SHA2_512: "SHA2-512",
|
||||
SHA3_224: "SHA3-224",
|
||||
SHA3_256: "SHA3-256",
|
||||
SHA3_384: "SHA3-384",
|
||||
SHA3_512: "SHA3-512",
|
||||
BLAKE2S_256: "Blake2s-256",
|
||||
BLAKE2B_256: "Blake2b-256",
|
||||
BLAKE2B_384: "Blake2b-384",
|
||||
BLAKE2B_512: "Blake2b-512",
|
||||
}
|
||||
)
|
||||
|
||||
func (a Algorithm) BlockSize() uint8 {
|
||||
att, ok := attributes[a]
|
||||
if !ok {
|
||||
return 0
|
||||
}
|
||||
return att[0]
|
||||
}
|
||||
|
||||
func (a Algorithm) Size() uint8 {
|
||||
att, ok := attributes[a]
|
||||
if !ok {
|
||||
return 0
|
||||
}
|
||||
return att[1]
|
||||
}
|
||||
|
||||
func (a Algorithm) SecurityStrength() uint8 {
|
||||
att, ok := attributes[a]
|
||||
if !ok {
|
||||
return 0
|
||||
}
|
||||
return att[2]
|
||||
}
|
||||
|
||||
func (a Algorithm) String() string {
|
||||
return a.Name()
|
||||
}
|
||||
|
||||
func (a Algorithm) Name() string {
|
||||
name, ok := names[a]
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
func (a Algorithm) New() hash.Hash {
|
||||
fn, ok := functions[a]
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
return fn()
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
package hash
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestAttributes(t *testing.T) {
|
||||
|
||||
for alg, att := range attributes {
|
||||
|
||||
name, ok := names[alg]
|
||||
if !ok {
|
||||
t.Errorf("hash test: name missing for Algorithm ID %d", alg)
|
||||
}
|
||||
_ = alg.String()
|
||||
|
||||
_, ok = functions[alg]
|
||||
if !ok {
|
||||
t.Errorf("hash test: function missing for Algorithm %s", name)
|
||||
}
|
||||
hash := alg.New()
|
||||
|
||||
if len(att) != 3 {
|
||||
t.Errorf("hash test: Algorithm %s does not have exactly 3 attributes", name)
|
||||
}
|
||||
|
||||
if hash.BlockSize() != int(alg.BlockSize()) {
|
||||
t.Errorf("hash test: block size mismatch at Algorithm %s", name)
|
||||
}
|
||||
if hash.Size() != int(alg.Size()) {
|
||||
t.Errorf("hash test: size mismatch at Algorithm %s", name)
|
||||
}
|
||||
if alg.Size()/2 != alg.SecurityStrength() {
|
||||
t.Errorf("hash test: possible strength error at Algorithm %s", name)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
noAlg := Algorithm(255)
|
||||
if noAlg.String() != "" {
|
||||
t.Error("hash test: invalid Algorithm error")
|
||||
}
|
||||
if noAlg.BlockSize() != 0 {
|
||||
t.Error("hash test: invalid Algorithm error")
|
||||
}
|
||||
if noAlg.Size() != 0 {
|
||||
t.Error("hash test: invalid Algorithm error")
|
||||
}
|
||||
if noAlg.SecurityStrength() != 0 {
|
||||
t.Error("hash test: invalid Algorithm error")
|
||||
}
|
||||
if noAlg.New() != nil {
|
||||
t.Error("hash test: invalid Algorithm error")
|
||||
}
|
||||
|
||||
}
|
|
@ -1,131 +0,0 @@
|
|||
package hash
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/safing/portbase/formats/varint"
|
||||
)
|
||||
|
||||
type Hash struct {
|
||||
Algorithm Algorithm
|
||||
Sum []byte
|
||||
}
|
||||
|
||||
func FromBytes(bytes []byte) (*Hash, int, error) {
|
||||
hash := &Hash{}
|
||||
alg, read, err := varint.Unpack8(bytes)
|
||||
hash.Algorithm = Algorithm(alg)
|
||||
if err != nil {
|
||||
return nil, 0, errors.New(fmt.Sprintf("hash: failed to parse: %s", err))
|
||||
}
|
||||
// TODO: check if length is correct
|
||||
hash.Sum = bytes[read:]
|
||||
return hash, 0, nil
|
||||
}
|
||||
|
||||
func (h *Hash) Bytes() []byte {
|
||||
return append(varint.Pack8(uint8(h.Algorithm)), h.Sum...)
|
||||
}
|
||||
|
||||
func FromSafe64(s string) (*Hash, error) {
|
||||
bytes, err := base64.RawURLEncoding.DecodeString(s)
|
||||
if err != nil {
|
||||
return nil, errors.New(fmt.Sprintf("hash: failed to parse: %s", err))
|
||||
}
|
||||
hash, _, err := FromBytes(bytes)
|
||||
return hash, err
|
||||
}
|
||||
|
||||
func (h *Hash) Safe64() string {
|
||||
return base64.RawURLEncoding.EncodeToString(h.Bytes())
|
||||
}
|
||||
|
||||
func FromHex(s string) (*Hash, error) {
|
||||
bytes, err := hex.DecodeString(s)
|
||||
if err != nil {
|
||||
return nil, errors.New(fmt.Sprintf("hash: failed to parse: %s", err))
|
||||
}
|
||||
hash, _, err := FromBytes(bytes)
|
||||
return hash, err
|
||||
}
|
||||
|
||||
func (h *Hash) Hex() string {
|
||||
return hex.EncodeToString(h.Bytes())
|
||||
}
|
||||
|
||||
func (h *Hash) Equal(other *Hash) bool {
|
||||
if h.Algorithm != other.Algorithm {
|
||||
return false
|
||||
}
|
||||
return bytes.Equal(h.Sum, other.Sum)
|
||||
}
|
||||
|
||||
func Sum(data []byte, alg Algorithm) *Hash {
|
||||
hasher := alg.New()
|
||||
hasher.Write(data)
|
||||
return &Hash{
|
||||
Algorithm: alg,
|
||||
Sum: hasher.Sum(nil),
|
||||
}
|
||||
}
|
||||
|
||||
func SumString(data string, alg Algorithm) *Hash {
|
||||
hasher := alg.New()
|
||||
io.WriteString(hasher, data)
|
||||
return &Hash{
|
||||
Algorithm: alg,
|
||||
Sum: hasher.Sum(nil),
|
||||
}
|
||||
}
|
||||
|
||||
func SumReader(reader io.Reader, alg Algorithm) (*Hash, error) {
|
||||
hasher := alg.New()
|
||||
_, err := io.Copy(hasher, reader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Hash{
|
||||
Algorithm: alg,
|
||||
Sum: hasher.Sum(nil),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func SumAndCompare(data []byte, other Hash) (bool, *Hash) {
|
||||
newHash := Sum(data, other.Algorithm)
|
||||
return other.Equal(newHash), newHash
|
||||
}
|
||||
|
||||
func SumReaderAndCompare(reader io.Reader, other Hash) (bool, *Hash, error) {
|
||||
newHash, err := SumReader(reader, other.Algorithm)
|
||||
if err != nil {
|
||||
return false, nil, err
|
||||
}
|
||||
return other.Equal(newHash), newHash, nil
|
||||
}
|
||||
|
||||
func RecommendedAlg(strengthInBits uint16) Algorithm {
|
||||
strengthInBytes := uint8(strengthInBits / 8)
|
||||
if strengthInBits%8 != 0 {
|
||||
strengthInBytes++
|
||||
}
|
||||
if strengthInBytes == 0 {
|
||||
strengthInBytes = uint8(0xFF)
|
||||
}
|
||||
chosenAlg := orderedByRecommendation[0]
|
||||
for _, alg := range orderedByRecommendation {
|
||||
strength := alg.SecurityStrength()
|
||||
if strength < strengthInBytes {
|
||||
break
|
||||
}
|
||||
chosenAlg = alg
|
||||
if strength == strengthInBytes {
|
||||
break
|
||||
}
|
||||
}
|
||||
return chosenAlg
|
||||
}
|
|
@ -1,82 +0,0 @@
|
|||
package hash
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var (
|
||||
testEmpty = []byte("")
|
||||
testFox = []byte("The quick brown fox jumps over the lazy dog")
|
||||
)
|
||||
|
||||
func testAlgorithm(t *testing.T, alg Algorithm, emptyHex, foxHex string) {
|
||||
|
||||
var err error
|
||||
|
||||
// testEmpty
|
||||
hash := Sum(testEmpty, alg)
|
||||
if err != nil {
|
||||
t.Errorf("test Sum %s (empty): error occured: %s", alg.String(), err)
|
||||
}
|
||||
if hash.Hex()[2:] != emptyHex {
|
||||
t.Errorf("test Sum %s (empty): hex sum mismatch, expected %s, got %s", alg.String(), emptyHex, hash.Hex())
|
||||
}
|
||||
|
||||
// testFox
|
||||
hash = Sum(testFox, alg)
|
||||
if err != nil {
|
||||
t.Errorf("test Sum %s (fox): error occured: %s", alg.String(), err)
|
||||
}
|
||||
if hash.Hex()[2:] != foxHex {
|
||||
t.Errorf("test Sum %s (fox): hex sum mismatch, expected %s, got %s", alg.String(), foxHex, hash.Hex())
|
||||
}
|
||||
|
||||
// testEmpty
|
||||
hash = SumString(string(testEmpty), alg)
|
||||
if err != nil {
|
||||
t.Errorf("test SumString %s (empty): error occured: %s", alg.String(), err)
|
||||
}
|
||||
if hash.Hex()[2:] != emptyHex {
|
||||
t.Errorf("test SumString %s (empty): hex sum mismatch, expected %s, got %s", alg.String(), emptyHex, hash.Hex())
|
||||
}
|
||||
|
||||
// testFox
|
||||
hash = SumString(string(testFox), alg)
|
||||
if err != nil {
|
||||
t.Errorf("test SumString %s (fox): error occured: %s", alg.String(), err)
|
||||
}
|
||||
if hash.Hex()[2:] != foxHex {
|
||||
t.Errorf("test SumString %s (fox): hex sum mismatch, expected %s, got %s", alg.String(), foxHex, hash.Hex())
|
||||
}
|
||||
|
||||
// testEmpty
|
||||
hash, err = SumReader(bytes.NewReader(testEmpty), alg)
|
||||
if err != nil {
|
||||
t.Errorf("test SumReader %s (empty): error occured: %s", alg.String(), err)
|
||||
}
|
||||
if hash.Hex()[2:] != emptyHex {
|
||||
t.Errorf("test SumReader %s (empty): hex sum mismatch, expected %s, got %s", alg.String(), emptyHex, hash.Hex())
|
||||
}
|
||||
|
||||
// testFox
|
||||
hash, err = SumReader(bytes.NewReader(testFox), alg)
|
||||
if err != nil {
|
||||
t.Errorf("test SumReader %s (fox): error occured: %s", alg.String(), err)
|
||||
}
|
||||
if hash.Hex()[2:] != foxHex {
|
||||
t.Errorf("test SumReader %s (fox): hex sum mismatch, expected %s, got %s", alg.String(), foxHex, hash.Hex())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestHash(t *testing.T) {
|
||||
testAlgorithm(t, SHA2_512,
|
||||
"cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e",
|
||||
"07e547d9586f6a73f73fbac0435ed76951218fb7d0c8d788a309d785436bbb642e93a252a954f23912547d1e8a3b5ed6e1bfd7097821233fa0538f3db854fee6",
|
||||
)
|
||||
testAlgorithm(t, SHA3_512,
|
||||
"a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26",
|
||||
"01dedd5de4ef14642445ba5f5b97c15e47b9ad931326e4b0727cd94cefc44fff23f07bf543139939b49128caf436dc1bdee54fcb24023a08d9403f9b4bf0d450",
|
||||
)
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
package hash
|
||||
|
||||
import (
|
||||
"hash"
|
||||
|
||||
"golang.org/x/crypto/blake2b"
|
||||
"golang.org/x/crypto/blake2s"
|
||||
)
|
||||
|
||||
func NewBlake2s256() hash.Hash {
|
||||
h, _ := blake2s.New256(nil)
|
||||
return h
|
||||
}
|
||||
|
||||
func NewBlake2b256() hash.Hash {
|
||||
h, _ := blake2b.New256(nil)
|
||||
return h
|
||||
}
|
||||
|
||||
func NewBlake2b384() hash.Hash {
|
||||
h, _ := blake2b.New384(nil)
|
||||
return h
|
||||
}
|
||||
|
||||
func NewBlake2b512() hash.Hash {
|
||||
h, _ := blake2b.New512(nil)
|
||||
return h
|
||||
}
|
Loading…
Add table
Reference in a new issue