diff --git a/crypto/hasher/coniks/coniks.go b/crypto/hasher/coniks/coniks.go deleted file mode 100644 index dab49ea..0000000 --- a/crypto/hasher/coniks/coniks.go +++ /dev/null @@ -1,75 +0,0 @@ -// TODO(huyvq): Remove package import. -// Other package shouldn't need to import this package, -// instead they should insert `hasher` and import this -// package using a blank import name. -// Should be adressed in #06. - -package coniks - -import ( - "crypto" - - "github.com/coniks-sys/coniks-go/crypto/hasher" - "github.com/coniks-sys/coniks-go/utils" -) - -func init() { - hasher.RegisterHasher(CONIKSHasher, New) -} - -const ( - // CONIKSHasher is the identity of the hashing algorithm - // specified in the CONIKSHasher paper. - CONIKSHasher = "CONIKS Hasher" - - emptyIdentifier = 'E' - leafIdentifier = 'L' -) - -type coniksHasher struct { - crypto.Hash -} - -// New returns an instance of CONIKS hasher. -func New() hasher.PADHasher { - return &coniksHasher{Hash: crypto.SHA512_256} -} - -func (ch *coniksHasher) Digest(ms ...[]byte) []byte { - h := ch.New() - for _, m := range ms { - h.Write(m) - } - return h.Sum(nil) -} - -func (coniksHasher) ID() string { - return CONIKSHasher -} - -func (ch *coniksHasher) Size() int { - return ch.Size() -} - -func (ch *coniksHasher) HashInterior(left, right []byte) []byte { - return ch.Digest(left, right) -} - -func (ch *coniksHasher) HashLeaf(nonce []byte, index []byte, level uint32, commit []byte) []byte { - return ch.Digest( - []byte{leafIdentifier}, - nonce, - index, - utils.UInt32ToBytes(level), - commit, - ) -} - -func (ch *coniksHasher) HashEmpty(nonce []byte, index []byte, level uint32) []byte { - return ch.Digest( - []byte{emptyIdentifier}, - nonce, - index, - utils.UInt32ToBytes(level), - ) -} diff --git a/crypto/hashers/coniks/coniks.go b/crypto/hashers/coniks/coniks.go new file mode 100644 index 0000000..1439b29 --- /dev/null +++ b/crypto/hashers/coniks/coniks.go @@ -0,0 +1,80 @@ +// TODO(huyvq): Remove package import. +// Other package shouldn't need to import this package, +// instead they should insert `hashers` and import this +// package using a blank import name. +// Should be adressed in #06. + +package coniks + +import ( + "crypto" + + "github.com/coniks-sys/coniks-go/crypto/hashers" + "github.com/coniks-sys/coniks-go/utils" +) + +func init() { + hashers.RegisterHasher(CONIKS_Hash_SHA512_256, New) +} + +const ( + // CONIKS_Hash_SHA512_256 is the identity of the hashing strategy + // specified in the Coniks paper with SHA512_256 as the hash algorithm. + CONIKS_Hash_SHA512_256 = "CONIKS_Hash_SHA512_256" + + emptyIdentifier = 'E' + leafIdentifier = 'L' +) + +type hasher struct { + crypto.Hash +} + +// New returns an instance of CONIKS_Hash_SHA512_256. +func New() hashers.PADHasher { + return &hasher{Hash: crypto.SHA512_256} +} + +func (ch *hasher) Digest(ms ...[]byte) []byte { + h := ch.New() + for _, m := range ms { + h.Write(m) + } + return h.Sum(nil) +} + +func (hasher) ID() string { + return CONIKS_Hash_SHA512_256 +} + +func (ch *hasher) Size() int { + return ch.Size() +} + +// HashInterior computes the hash of an interior node as: H(left || right). +func (ch *hasher) HashInterior(left, right []byte) []byte { + return ch.Digest(left, right) +} + +// HashLeaf computes the hash of a user leaf node as: +// H(Identifier || nonce || index || level || commit). +func (ch *hasher) HashLeaf(nonce []byte, index []byte, level uint32, commit []byte) []byte { + return ch.Digest( + []byte{leafIdentifier}, + nonce, + index, + utils.UInt32ToBytes(level), + commit, + ) +} + +// HashEmpty computes the hash of an empty leaf node as: +// H(Identifier || nonce || index || level). +func (ch *hasher) HashEmpty(nonce []byte, index []byte, level uint32) []byte { + return ch.Digest( + []byte{emptyIdentifier}, + nonce, + index, + utils.UInt32ToBytes(level), + ) +} diff --git a/crypto/hasher/coniks/coniks_test.go b/crypto/hashers/coniks/coniks_test.go similarity index 87% rename from crypto/hasher/coniks/coniks_test.go rename to crypto/hashers/coniks/coniks_test.go index 289374d..83960d2 100644 --- a/crypto/hasher/coniks/coniks_test.go +++ b/crypto/hashers/coniks/coniks_test.go @@ -4,23 +4,23 @@ import ( "encoding/hex" "testing" - "github.com/coniks-sys/coniks-go/crypto/hasher" + "github.com/coniks-sys/coniks-go/crypto/hashers" ) // h2h converts a hex string into its Hash object. -func h2h(h string) hasher.Hash { +func h2h(h string) hashers.Hash { b, err := hex.DecodeString(h) if err != nil { panic("invalid hex string") } - var ret hasher.Hash + var ret hashers.Hash copy(ret[:], b) return ret } // s2h converts a byte slice into its Hash object. -func s2h(s []byte) hasher.Hash { - var ret hasher.Hash +func s2h(s []byte) hashers.Hash { + var ret hashers.Hash copy(ret[:], s) return ret } @@ -31,7 +31,7 @@ func TestHashLeafVectors(t *testing.T) { index []byte depth uint32 leaf []byte - want hasher.Hash + want hashers.Hash }{ {treeNonce: [32]byte{0}, index: []byte("foo"), depth: 128, leaf: []byte("leaf"), want: h2h("65e7f29787a6168affd016656bb1f4f03af91cf7416270f5015005f8594d3eb6")}, } { @@ -46,7 +46,7 @@ func TestHashEmptyVectors(t *testing.T) { treeNonce [32]byte // treeNonce is treeID in KT, it should be a 32-byte array for cross-project compatibility index []byte depth uint32 - want hasher.Hash + want hashers.Hash }{ {treeNonce: [32]byte{0}, index: []byte("foo"), depth: 128, want: h2h("1a6b0eb739b32a46e7d679a9be03f522e907f53423aacb82e550bf657d1afb10")}, } { diff --git a/crypto/hasher/hasher.go b/crypto/hashers/hasher.go similarity index 67% rename from crypto/hasher/hasher.go rename to crypto/hashers/hasher.go index e33534f..9bd7ad2 100644 --- a/crypto/hasher/hasher.go +++ b/crypto/hashers/hasher.go @@ -1,4 +1,4 @@ -package hasher +package hashers import ( "fmt" @@ -9,7 +9,9 @@ import ( // Hash represents the output of the used hash function. type Hash [crypto.DefaultHashSizeByte]byte -// PADHasher provides hash functions for the PAD implementations. +// PADHasher provides hash functions for the PAD implementations, +// and defines the way empty / node / leaf hashes of the underlying tree +// are constructed. type PADHasher interface { // ID returns the name of the cryptographic hash function. ID() string @@ -17,20 +19,14 @@ type PADHasher interface { Size() int // Digest hashes all passed byte slices. The passed slices won't be mutated. Digest(ms ...[]byte) []byte - treeHasher -} -// treeHasher provides hash functions for tree implementations. -type treeHasher interface { - // HashInterior computes the hash of an interior node as: H(left || right) + // HashInterior computes the hash of an interior node. HashInterior(left, right []byte) []byte - // HashLeaf computes the hash of a user leaf node as: - // H(Identifier || nonce || index || level || commit) + // HashLeaf computes the hash of a user leaf node. HashLeaf(nonce []byte, index []byte, level uint32, data []byte) []byte - // HashEmpty computes the hash of an empty leaf node as: - // H(Identifier || nonce || index || level) + // HashEmpty computes the hash of an empty leaf node. HashEmpty(nonce []byte, index []byte, level uint32) []byte } @@ -44,8 +40,9 @@ func RegisterHasher(h string, f func() PADHasher) { hashers[h] = f() } -// Hasher returns a PADHasher. -func Hasher(h string) (PADHasher, error) { +// NewPADHasher returns a registered PADHasher identified by the given string. +// If no such PADHasher exists, it returns an error. +func NewPADHasher(h string) (PADHasher, error) { if f, ok := hashers[h]; ok { return f, nil } diff --git a/crypto/hasher/hasher_test.go b/crypto/hashers/hasher_test.go similarity index 90% rename from crypto/hasher/hasher_test.go rename to crypto/hashers/hasher_test.go index 0bd9d1c..44ae841 100644 --- a/crypto/hasher/hasher_test.go +++ b/crypto/hashers/hasher_test.go @@ -1,4 +1,4 @@ -package hasher +package hashers import ( "testing" @@ -25,7 +25,7 @@ func TestGetHasher(t *testing.T) { RegisterHasher(fakeHasherID, fakeHasher) } - _, err := Hasher(fakeHasherID) + _, err := NewPADHasher(fakeHasherID) if err != nil { t.Error("Expect a hasher.") } diff --git a/merkletree/merkletree.go b/merkletree/merkletree.go index 3fa3d22..d1c869f 100644 --- a/merkletree/merkletree.go +++ b/merkletree/merkletree.go @@ -5,7 +5,7 @@ import ( "errors" "github.com/coniks-sys/coniks-go/crypto" - "github.com/coniks-sys/coniks-go/crypto/hasher" + "github.com/coniks-sys/coniks-go/crypto/hashers" "github.com/coniks-sys/coniks-go/utils" ) @@ -63,7 +63,7 @@ func (m *MerkleTree) Get(lookupIndex []byte) *AuthenticationPath { break } direction := lookupIndexBits[depth] - var hashArr hasher.Hash + var hashArr hashers.Hash if direction { copy(hashArr[:], nodePointer.(*interiorNode).leftHash) nodePointer = nodePointer.(*interiorNode).rightChild diff --git a/merkletree/node.go b/merkletree/node.go index 7665ad8..c28c77a 100644 --- a/merkletree/node.go +++ b/merkletree/node.go @@ -2,7 +2,7 @@ package merkletree import ( "github.com/coniks-sys/coniks-go/crypto" - chasher "github.com/coniks-sys/coniks-go/crypto/hasher/coniks" + chasher "github.com/coniks-sys/coniks-go/crypto/hashers/coniks" "github.com/coniks-sys/coniks-go/utils" ) diff --git a/merkletree/pad.go b/merkletree/pad.go index cbbe912..8b4ed5c 100644 --- a/merkletree/pad.go +++ b/merkletree/pad.go @@ -5,7 +5,7 @@ import ( "errors" "github.com/coniks-sys/coniks-go/crypto" - chasher "github.com/coniks-sys/coniks-go/crypto/hasher/coniks" + chasher "github.com/coniks-sys/coniks-go/crypto/hashers/coniks" "github.com/coniks-sys/coniks-go/crypto/sign" "github.com/coniks-sys/coniks-go/crypto/vrf" ) diff --git a/merkletree/proof.go b/merkletree/proof.go index f830d1e..46d3614 100644 --- a/merkletree/proof.go +++ b/merkletree/proof.go @@ -5,8 +5,8 @@ import ( "errors" "github.com/coniks-sys/coniks-go/crypto" - "github.com/coniks-sys/coniks-go/crypto/hasher" - chasher "github.com/coniks-sys/coniks-go/crypto/hasher/coniks" + "github.com/coniks-sys/coniks-go/crypto/hashers" + chasher "github.com/coniks-sys/coniks-go/crypto/hashers/coniks" "github.com/coniks-sys/coniks-go/utils" ) @@ -74,7 +74,7 @@ const ( // equals the lookup index. type AuthenticationPath struct { TreeNonce []byte - PrunedTree []hasher.Hash + PrunedTree []hashers.Hash LookupIndex []byte VrfProof []byte Leaf *ProofNode diff --git a/merkletree/str.go b/merkletree/str.go index aa1be3f..b82febf 100644 --- a/merkletree/str.go +++ b/merkletree/str.go @@ -3,7 +3,7 @@ package merkletree import ( "bytes" - chasher "github.com/coniks-sys/coniks-go/crypto/hasher/coniks" + chasher "github.com/coniks-sys/coniks-go/crypto/hashers/coniks" "github.com/coniks-sys/coniks-go/crypto/sign" "github.com/coniks-sys/coniks-go/utils" ) diff --git a/protocol/policy.go b/protocol/policy.go index bac3d85..6e9b392 100644 --- a/protocol/policy.go +++ b/protocol/policy.go @@ -1,7 +1,7 @@ package protocol import ( - chasher "github.com/coniks-sys/coniks-go/crypto/hasher/coniks" + chasher "github.com/coniks-sys/coniks-go/crypto/hashers/coniks" "github.com/coniks-sys/coniks-go/crypto/vrf" "github.com/coniks-sys/coniks-go/merkletree" "github.com/coniks-sys/coniks-go/utils"