From eedd20f4d5d886628286b4b1b9985633fe04c1a3 Mon Sep 17 00:00:00 2001 From: Liamsi Date: Wed, 20 Jun 2018 15:37:45 -0700 Subject: [PATCH] Revert "delete everything" This reverts commit 96a3502126561f500ddfcfc98f2455a64ba3caba. # Conflicts: # CHANGELOG.md # Gopkg.lock # Gopkg.toml # LICENSE # Makefile # README.md --- amino.go | 37 ----- armor.go | 39 ----- armor_test.go | 20 --- doc.go | 48 ------ encode_test.go | 119 -------------- example_test.go | 35 ----- hash.go | 18 --- hkdfchacha20poly1305/hkdfchachapoly.go | 105 ------------- hkdfchacha20poly1305/hkdfchachapoly_test.go | 139 ----------------- merkle/README.md | 4 - merkle/doc.go | 31 ---- merkle/simple_map.go | 88 ----------- merkle/simple_map_test.go | 54 ------- merkle/simple_proof.go | 160 ------------------- merkle/simple_tree.go | 58 ------- merkle/simple_tree_test.go | 88 ----------- merkle/types.go | 38 ----- priv_key.go | 164 -------------------- priv_key_test.go | 60 ------- pub_key.go | 149 ------------------ pub_key_test.go | 50 ------ random.go | 108 ------------- signature.go | 88 ----------- signature_test.go | 46 ------ symmetric.go | 51 ------ symmetric_test.go | 42 ----- tmhash/hash.go | 48 ------ tmhash/hash_test.go | 23 --- version.go | 3 - 29 files changed, 1913 deletions(-) delete mode 100644 amino.go delete mode 100644 armor.go delete mode 100644 armor_test.go delete mode 100644 doc.go delete mode 100644 encode_test.go delete mode 100644 example_test.go delete mode 100644 hash.go delete mode 100644 hkdfchacha20poly1305/hkdfchachapoly.go delete mode 100644 hkdfchacha20poly1305/hkdfchachapoly_test.go delete mode 100644 merkle/README.md delete mode 100644 merkle/doc.go delete mode 100644 merkle/simple_map.go delete mode 100644 merkle/simple_map_test.go delete mode 100644 merkle/simple_proof.go delete mode 100644 merkle/simple_tree.go delete mode 100644 merkle/simple_tree_test.go delete mode 100644 merkle/types.go delete mode 100644 priv_key.go delete mode 100644 priv_key_test.go delete mode 100644 pub_key.go delete mode 100644 pub_key_test.go delete mode 100644 random.go delete mode 100644 signature.go delete mode 100644 signature_test.go delete mode 100644 symmetric.go delete mode 100644 symmetric_test.go delete mode 100644 tmhash/hash.go delete mode 100644 tmhash/hash_test.go delete mode 100644 version.go diff --git a/amino.go b/amino.go deleted file mode 100644 index 2a57afde..00000000 --- a/amino.go +++ /dev/null @@ -1,37 +0,0 @@ -package crypto - -import ( - amino "github.com/tendermint/go-amino" -) - -var cdc = amino.NewCodec() - -func init() { - // NOTE: It's important that there be no conflicts here, - // as that would change the canonical representations, - // and therefore change the address. - // TODO: Add feature to go-amino to ensure that there - // are no conflicts. - RegisterAmino(cdc) -} - -// RegisterAmino registers all go-crypto related types in the given (amino) codec. -func RegisterAmino(cdc *amino.Codec) { - cdc.RegisterInterface((*PubKey)(nil), nil) - cdc.RegisterConcrete(PubKeyEd25519{}, - "tendermint/PubKeyEd25519", nil) - cdc.RegisterConcrete(PubKeySecp256k1{}, - "tendermint/PubKeySecp256k1", nil) - - cdc.RegisterInterface((*PrivKey)(nil), nil) - cdc.RegisterConcrete(PrivKeyEd25519{}, - "tendermint/PrivKeyEd25519", nil) - cdc.RegisterConcrete(PrivKeySecp256k1{}, - "tendermint/PrivKeySecp256k1", nil) - - cdc.RegisterInterface((*Signature)(nil), nil) - cdc.RegisterConcrete(SignatureEd25519{}, - "tendermint/SignatureEd25519", nil) - cdc.RegisterConcrete(SignatureSecp256k1{}, - "tendermint/SignatureSecp256k1", nil) -} diff --git a/armor.go b/armor.go deleted file mode 100644 index 4146048a..00000000 --- a/armor.go +++ /dev/null @@ -1,39 +0,0 @@ -package crypto - -import ( - "bytes" - "fmt" - "io/ioutil" - - "golang.org/x/crypto/openpgp/armor" -) - -func EncodeArmor(blockType string, headers map[string]string, data []byte) string { - buf := new(bytes.Buffer) - w, err := armor.Encode(buf, blockType, headers) - if err != nil { - panic(fmt.Errorf("could not encode ascii armor: %s", err)) - } - _, err = w.Write(data) - if err != nil { - panic(fmt.Errorf("could not encode ascii armor: %s", err)) - } - err = w.Close() - if err != nil { - panic(fmt.Errorf("could not encode ascii armor: %s", err)) - } - return buf.String() -} - -func DecodeArmor(armorStr string) (blockType string, headers map[string]string, data []byte, err error) { - buf := bytes.NewBufferString(armorStr) - block, err := armor.Decode(buf) - if err != nil { - return "", nil, nil, err - } - data, err = ioutil.ReadAll(block.Body) - if err != nil { - return "", nil, nil, err - } - return block.Type, block.Header, data, nil -} diff --git a/armor_test.go b/armor_test.go deleted file mode 100644 index 5eae87c0..00000000 --- a/armor_test.go +++ /dev/null @@ -1,20 +0,0 @@ -package crypto - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestSimpleArmor(t *testing.T) { - blockType := "MINT TEST" - data := []byte("somedata") - armorStr := EncodeArmor(blockType, nil, data) - - // Decode armorStr and test for equivalence. - blockType2, _, data2, err := DecodeArmor(armorStr) - require.Nil(t, err, "%+v", err) - assert.Equal(t, blockType, blockType2) - assert.Equal(t, data, data2) -} diff --git a/doc.go b/doc.go deleted file mode 100644 index c6701bc5..00000000 --- a/doc.go +++ /dev/null @@ -1,48 +0,0 @@ -/* -go-crypto is a customized/convenience cryptography package -for supporting Tendermint. - -It wraps select functionality of equivalent functions in the -Go standard library, for easy usage with our libraries. - -Keys: - -All key generation functions return an instance of the PrivKey interface -which implements methods - - AssertIsPrivKeyInner() - Bytes() []byte - Sign(msg []byte) Signature - PubKey() PubKey - Equals(PrivKey) bool - Wrap() PrivKey - -From the above method we can: -a) Retrieve the public key if needed - - pubKey := key.PubKey() - -For example: - privKey, err := crypto.GenPrivKeyEd25519() - if err != nil { - ... - } - pubKey := privKey.PubKey() - ... - // And then you can use the private and public key - doSomething(privKey, pubKey) - - -We also provide hashing wrappers around algorithms: - -Sha256 - sum := crypto.Sha256([]byte("This is Tendermint")) - fmt.Printf("%x\n", sum) - -Ripemd160 - sum := crypto.Ripemd160([]byte("This is consensus")) - fmt.Printf("%x\n", sum) -*/ -package crypto - -// TODO: Add more docs in here diff --git a/encode_test.go b/encode_test.go deleted file mode 100644 index a122f20e..00000000 --- a/encode_test.go +++ /dev/null @@ -1,119 +0,0 @@ -package crypto - -import ( - "os" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -type byter interface { - Bytes() []byte -} - -func checkAminoBinary(t *testing.T, src byter, dst interface{}, size int) { - // Marshal to binary bytes. - bz, err := cdc.MarshalBinaryBare(src) - require.Nil(t, err, "%+v", err) - // Make sure this is compatible with current (Bytes()) encoding. - assert.Equal(t, src.Bytes(), bz, "Amino binary vs Bytes() mismatch") - // Make sure we have the expected length. - if size != -1 { - assert.Equal(t, size, len(bz), "Amino binary size mismatch") - } - // Unmarshal. - err = cdc.UnmarshalBinaryBare(bz, dst) - require.Nil(t, err, "%+v", err) -} - -func checkAminoJSON(t *testing.T, src interface{}, dst interface{}, isNil bool) { - // Marshal to JSON bytes. - js, err := cdc.MarshalJSON(src) - require.Nil(t, err, "%+v", err) - if isNil { - assert.Equal(t, string(js), `null`) - } else { - assert.Contains(t, string(js), `"type":`) - assert.Contains(t, string(js), `"value":`) - } - // Unmarshal. - err = cdc.UnmarshalJSON(js, dst) - require.Nil(t, err, "%+v", err) -} - -func ExamplePrintRegisteredTypes() { - cdc.PrintTypes(os.Stdout) - // Output: | Type | Name | Prefix | Length | Notes | - //| ---- | ---- | ------ | ----- | ------ | - //| PubKeyEd25519 | tendermint/PubKeyEd25519 | 0x1624DE64 | 0x20 | | - //| PubKeySecp256k1 | tendermint/PubKeySecp256k1 | 0xEB5AE987 | 0x21 | | - //| PrivKeyEd25519 | tendermint/PrivKeyEd25519 | 0xA3288910 | 0x40 | | - //| PrivKeySecp256k1 | tendermint/PrivKeySecp256k1 | 0xE1B0F79B | 0x20 | | - //| SignatureEd25519 | tendermint/SignatureEd25519 | 0x2031EA53 | 0x40 | | - //| SignatureSecp256k1 | tendermint/SignatureSecp256k1 | 0x7FC4A495 | variable | | -} - -func TestKeyEncodings(t *testing.T) { - cases := []struct { - privKey PrivKey - privSize, pubSize int // binary sizes - }{ - { - privKey: GenPrivKeyEd25519(), - privSize: 69, - pubSize: 37, - }, - { - privKey: GenPrivKeySecp256k1(), - privSize: 37, - pubSize: 38, - }, - } - - for _, tc := range cases { - - // Check (de/en)codings of PrivKeys. - var priv2, priv3 PrivKey - checkAminoBinary(t, tc.privKey, &priv2, tc.privSize) - assert.EqualValues(t, tc.privKey, priv2) - checkAminoJSON(t, tc.privKey, &priv3, false) // TODO also check Prefix bytes. - assert.EqualValues(t, tc.privKey, priv3) - - // Check (de/en)codings of Signatures. - var sig1, sig2, sig3 Signature - sig1, err := tc.privKey.Sign([]byte("something")) - assert.NoError(t, err) - checkAminoBinary(t, sig1, &sig2, -1) // Siganture size changes for Secp anyways. - assert.EqualValues(t, sig1, sig2) - checkAminoJSON(t, sig1, &sig3, false) // TODO also check Prefix bytes. - assert.EqualValues(t, sig1, sig3) - - // Check (de/en)codings of PubKeys. - pubKey := tc.privKey.PubKey() - var pub2, pub3 PubKey - checkAminoBinary(t, pubKey, &pub2, tc.pubSize) - assert.EqualValues(t, pubKey, pub2) - checkAminoJSON(t, pubKey, &pub3, false) // TODO also check Prefix bytes. - assert.EqualValues(t, pubKey, pub3) - } -} - -func TestNilEncodings(t *testing.T) { - - // Check nil Signature. - var a, b Signature - checkAminoJSON(t, &a, &b, true) - assert.EqualValues(t, a, b) - - // Check nil PubKey. - var c, d PubKey - checkAminoJSON(t, &c, &d, true) - assert.EqualValues(t, c, d) - - // Check nil PrivKey. - var e, f PrivKey - checkAminoJSON(t, &e, &f, true) - assert.EqualValues(t, e, f) - -} diff --git a/example_test.go b/example_test.go deleted file mode 100644 index 2c8b9454..00000000 --- a/example_test.go +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2017 Tendermint. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package crypto_test - -import ( - "fmt" - - "github.com/tendermint/go-crypto" -) - -func ExampleSha256() { - sum := crypto.Sha256([]byte("This is Tendermint")) - fmt.Printf("%x\n", sum) - // Output: - // f91afb642f3d1c87c17eb01aae5cb65c242dfdbe7cf1066cc260f4ce5d33b94e -} - -func ExampleRipemd160() { - sum := crypto.Ripemd160([]byte("This is Tendermint")) - fmt.Printf("%x\n", sum) - // Output: - // 051e22663e8f0fd2f2302f1210f954adff009005 -} diff --git a/hash.go b/hash.go deleted file mode 100644 index 165b1e15..00000000 --- a/hash.go +++ /dev/null @@ -1,18 +0,0 @@ -package crypto - -import ( - "crypto/sha256" - "golang.org/x/crypto/ripemd160" -) - -func Sha256(bytes []byte) []byte { - hasher := sha256.New() - hasher.Write(bytes) - return hasher.Sum(nil) -} - -func Ripemd160(bytes []byte) []byte { - hasher := ripemd160.New() - hasher.Write(bytes) - return hasher.Sum(nil) -} diff --git a/hkdfchacha20poly1305/hkdfchachapoly.go b/hkdfchacha20poly1305/hkdfchachapoly.go deleted file mode 100644 index ab3b9df3..00000000 --- a/hkdfchacha20poly1305/hkdfchachapoly.go +++ /dev/null @@ -1,105 +0,0 @@ -// Package hkdfchacha20poly1305 creates an AEAD using hkdf, chacha20, and poly1305 -// When sealing and opening, the hkdf is used to obtain the nonce and subkey for -// chacha20. Other than the change for the how the subkey and nonce for chacha -// are obtained, this is the same as chacha20poly1305 -package hkdfchacha20poly1305 - -import ( - "crypto/cipher" - "crypto/sha256" - "errors" - "io" - - "golang.org/x/crypto/chacha20poly1305" - "golang.org/x/crypto/hkdf" -) - -type hkdfchacha20poly1305 struct { - key [KeySize]byte -} - -const ( - // KeySize is the size of the key used by this AEAD, in bytes. - KeySize = 32 - // NonceSize is the size of the nonce used with this AEAD, in bytes. - NonceSize = 24 - // TagSize is the size added from poly1305 - TagSize = 16 - // MaxPlaintextSize is the max size that can be passed into a single call of Seal - MaxPlaintextSize = (1 << 38) - 64 - // MaxCiphertextSize is the max size that can be passed into a single call of Open, - // this differs from plaintext size due to the tag - MaxCiphertextSize = (1 << 38) - 48 - // HkdfInfo is the parameter used internally for Hkdf's info parameter. - HkdfInfo = "TENDERMINT_SECRET_CONNECTION_FRAME_KEY_DERIVE" -) - -//New xChaChapoly1305 AEAD with 24 byte nonces -func New(key []byte) (cipher.AEAD, error) { - if len(key) != KeySize { - return nil, errors.New("chacha20poly1305: bad key length") - } - ret := new(hkdfchacha20poly1305) - copy(ret.key[:], key) - return ret, nil - -} -func (c *hkdfchacha20poly1305) NonceSize() int { - return NonceSize -} - -func (c *hkdfchacha20poly1305) Overhead() int { - return TagSize -} - -func (c *hkdfchacha20poly1305) Seal(dst, nonce, plaintext, additionalData []byte) []byte { - if len(nonce) != NonceSize { - panic("hkdfchacha20poly1305: bad nonce length passed to Seal") - } - - if uint64(len(plaintext)) > MaxPlaintextSize { - panic("hkdfchacha20poly1305: plaintext too large") - } - - subKey, chachaNonce := getSubkeyAndChachaNonceFromHkdf(&c.key, &nonce) - - aead, err := chacha20poly1305.New(subKey[:]) - if err != nil { - panic("hkdfchacha20poly1305: failed to initialize chacha20poly1305") - } - - return aead.Seal(dst, chachaNonce[:], plaintext, additionalData) -} - -func (c *hkdfchacha20poly1305) Open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) { - if len(nonce) != NonceSize { - return nil, errors.New("hkdfchacha20poly1305: bad nonce length passed to Open") - } - if uint64(len(ciphertext)) > MaxCiphertextSize { - return nil, errors.New("hkdfchacha20poly1305: ciphertext too large") - } - - subKey, chachaNonce := getSubkeyAndChachaNonceFromHkdf(&c.key, &nonce) - - aead, err := chacha20poly1305.New(subKey[:]) - if err != nil { - panic("hkdfchacha20poly1305: failed to initialize chacha20poly1305") - } - - return aead.Open(dst, chachaNonce[:], ciphertext, additionalData) -} - -func getSubkeyAndChachaNonceFromHkdf(cKey *[32]byte, nonce *[]byte) ( - subKey [KeySize]byte, chachaNonce [chacha20poly1305.NonceSize]byte) { - hash := sha256.New - hkdf := hkdf.New(hash, (*cKey)[:], *nonce, []byte(HkdfInfo)) - _, err := io.ReadFull(hkdf, subKey[:]) - if err != nil { - panic("hkdfchacha20poly1305: failed to read subkey from hkdf") - } - _, err = io.ReadFull(hkdf, chachaNonce[:]) - if err != nil { - panic("hkdfchacha20poly1305: failed to read chachaNonce from hkdf") - } - return -} diff --git a/hkdfchacha20poly1305/hkdfchachapoly_test.go b/hkdfchacha20poly1305/hkdfchachapoly_test.go deleted file mode 100644 index 66b770a1..00000000 --- a/hkdfchacha20poly1305/hkdfchachapoly_test.go +++ /dev/null @@ -1,139 +0,0 @@ -package hkdfchacha20poly1305 - -import ( - "bytes" - cr "crypto/rand" - "encoding/hex" - mr "math/rand" - "testing" - - "github.com/stretchr/testify/assert" -) - -// Test that a test vector we generated is valid. (Ensures backwards -// compatability) -func TestVector(t *testing.T) { - key, _ := hex.DecodeString("56f8de45d3c294c7675bcaf457bdd4b71c380b9b2408ce9412b348d0f08b69ee") - aead, err := New(key[:]) - if err != nil { - t.Fatal(err) - } - cts := []string{"e20a8bf42c535ac30125cfc52031577f0b", - "657695b37ba30f67b25860d90a6f1d00d8", - "e9aa6f3b7f625d957fd50f05bcdf20d014", - "8a00b3b5a6014e0d2033bebc5935086245", - "aadd74867b923879e6866ea9e03c009039", - "fc59773c2c864ee3b4cc971876b3c7bed4", - "caec14e3a9a52ce1a2682c6737defa4752", - "0b89511ffe490d2049d6950494ee51f919", - "7de854ea71f43ca35167a07566c769083d", - "cd477327f4ea4765c71e311c5fec1edbfb"} - - for i := 0; i < 10; i++ { - ct, _ := hex.DecodeString(cts[i]) - - byteArr := []byte{byte(i)} - nonce := make([]byte, 24, 24) - nonce[0] = byteArr[0] - - plaintext, err := aead.Open(nil, nonce, ct, byteArr) - if err != nil { - t.Errorf("%dth Open failed", i) - continue - } - assert.Equal(t, byteArr, plaintext) - } -} - -// The following test is taken from -// https://github.com/golang/crypto/blob/master/chacha20poly1305/chacha20poly1305_test.go#L69 -// It requires the below copyright notice, where "this source code" refers to the following function. -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found at the bottom of this file. -func TestRandom(t *testing.T) { - // Some random tests to verify Open(Seal) == Plaintext - for i := 0; i < 256; i++ { - var nonce [24]byte - var key [32]byte - - al := mr.Intn(128) - pl := mr.Intn(16384) - ad := make([]byte, al) - plaintext := make([]byte, pl) - cr.Read(key[:]) - cr.Read(nonce[:]) - cr.Read(ad) - cr.Read(plaintext) - - aead, err := New(key[:]) - if err != nil { - t.Fatal(err) - } - - ct := aead.Seal(nil, nonce[:], plaintext, ad) - - plaintext2, err := aead.Open(nil, nonce[:], ct, ad) - if err != nil { - t.Errorf("Random #%d: Open failed", i) - continue - } - - if !bytes.Equal(plaintext, plaintext2) { - t.Errorf("Random #%d: plaintext's don't match: got %x vs %x", i, plaintext2, plaintext) - continue - } - - if len(ad) > 0 { - alterAdIdx := mr.Intn(len(ad)) - ad[alterAdIdx] ^= 0x80 - if _, err := aead.Open(nil, nonce[:], ct, ad); err == nil { - t.Errorf("Random #%d: Open was successful after altering additional data", i) - } - ad[alterAdIdx] ^= 0x80 - } - - alterNonceIdx := mr.Intn(aead.NonceSize()) - nonce[alterNonceIdx] ^= 0x80 - if _, err := aead.Open(nil, nonce[:], ct, ad); err == nil { - t.Errorf("Random #%d: Open was successful after altering nonce", i) - } - nonce[alterNonceIdx] ^= 0x80 - - alterCtIdx := mr.Intn(len(ct)) - ct[alterCtIdx] ^= 0x80 - if _, err := aead.Open(nil, nonce[:], ct, ad); err == nil { - t.Errorf("Random #%d: Open was successful after altering ciphertext", i) - } - ct[alterCtIdx] ^= 0x80 - } -} - -// AFOREMENTIONED LICENCE -// Copyright (c) 2009 The Go Authors. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/merkle/README.md b/merkle/README.md deleted file mode 100644 index c4497836..00000000 --- a/merkle/README.md +++ /dev/null @@ -1,4 +0,0 @@ -## Simple Merkle Tree - -For smaller static data structures that don't require immutable snapshots or mutability; -for instance the transactions and validation signatures of a block can be hashed using this simple merkle tree logic. diff --git a/merkle/doc.go b/merkle/doc.go deleted file mode 100644 index da65dd85..00000000 --- a/merkle/doc.go +++ /dev/null @@ -1,31 +0,0 @@ -/* -Package merkle computes a deterministic minimal height Merkle tree hash. -If the number of items is not a power of two, some leaves -will be at different levels. Tries to keep both sides of -the tree the same size, but the left may be one greater. - -Use this for short deterministic trees, such as the validator list. -For larger datasets, use IAVLTree. - -Be aware that the current implementation by itself does not prevent -second pre-image attacks. Hence, use this library with caution. -Otherwise you might run into similar issues as, e.g., in early Bitcoin: -https://bitcointalk.org/?topic=102395 - - * - / \ - / \ - / \ - / \ - * * - / \ / \ - / \ / \ - / \ / \ - * * * h6 - / \ / \ / \ - h0 h1 h2 h3 h4 h5 - -TODO(ismail): add 2nd pre-image protection or clarify further on how we use this and why this secure. - -*/ -package merkle \ No newline at end of file diff --git a/merkle/simple_map.go b/merkle/simple_map.go deleted file mode 100644 index 24863267..00000000 --- a/merkle/simple_map.go +++ /dev/null @@ -1,88 +0,0 @@ -package merkle - -import ( - "github.com/tendermint/go-crypto/tmhash" - cmn "github.com/tendermint/tmlibs/common" -) - -// Merkle tree from a map. -// Leaves are `hash(key) | hash(value)`. -// Leaves are sorted before Merkle hashing. -type simpleMap struct { - kvs cmn.KVPairs - sorted bool -} - -func newSimpleMap() *simpleMap { - return &simpleMap{ - kvs: nil, - sorted: false, - } -} - -// Set hashes the key and value and appends it to the kv pairs. -func (sm *simpleMap) Set(key string, value Hasher) { - sm.sorted = false - - // The value is hashed, so you can - // check for equality with a cached value (say) - // and make a determination to fetch or not. - vhash := value.Hash() - - sm.kvs = append(sm.kvs, cmn.KVPair{ - Key: []byte(key), - Value: vhash, - }) -} - -// Hash Merkle root hash of items sorted by key -// (UNSTABLE: and by value too if duplicate key). -func (sm *simpleMap) Hash() []byte { - sm.Sort() - return hashKVPairs(sm.kvs) -} - -func (sm *simpleMap) Sort() { - if sm.sorted { - return - } - sm.kvs.Sort() - sm.sorted = true -} - -// Returns a copy of sorted KVPairs. -// NOTE these contain the hashed key and value. -func (sm *simpleMap) KVPairs() cmn.KVPairs { - sm.Sort() - kvs := make(cmn.KVPairs, len(sm.kvs)) - copy(kvs, sm.kvs) - return kvs -} - -//---------------------------------------- - -// A local extension to KVPair that can be hashed. -// Key and value are length prefixed and concatenated, -// then hashed. -type KVPair cmn.KVPair - -func (kv KVPair) Hash() []byte { - hasher := tmhash.New() - err := encodeByteSlice(hasher, kv.Key) - if err != nil { - panic(err) - } - err = encodeByteSlice(hasher, kv.Value) - if err != nil { - panic(err) - } - return hasher.Sum(nil) -} - -func hashKVPairs(kvs cmn.KVPairs) []byte { - kvsH := make([]Hasher, len(kvs)) - for i, kvp := range kvs { - kvsH[i] = KVPair(kvp) - } - return SimpleHashFromHashers(kvsH) -} diff --git a/merkle/simple_map_test.go b/merkle/simple_map_test.go deleted file mode 100644 index d9d63511..00000000 --- a/merkle/simple_map_test.go +++ /dev/null @@ -1,54 +0,0 @@ -package merkle - -import ( - "fmt" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/tendermint/go-crypto/tmhash" -) - -type strHasher string - -func (str strHasher) Hash() []byte { - return tmhash.Sum([]byte(str)) -} - -func TestSimpleMap(t *testing.T) { - { - db := newSimpleMap() - db.Set("key1", strHasher("value1")) - assert.Equal(t, "fa9bc106ffd932d919bee935ceb6cf2b3dd72d8f", fmt.Sprintf("%x", db.Hash()), "Hash didn't match") - } - { - db := newSimpleMap() - db.Set("key1", strHasher("value2")) - assert.Equal(t, "e00e7dcfe54e9fafef5111e813a587f01ba9c3e8", fmt.Sprintf("%x", db.Hash()), "Hash didn't match") - } - { - db := newSimpleMap() - db.Set("key1", strHasher("value1")) - db.Set("key2", strHasher("value2")) - assert.Equal(t, "eff12d1c703a1022ab509287c0f196130123d786", fmt.Sprintf("%x", db.Hash()), "Hash didn't match") - } - { - db := newSimpleMap() - db.Set("key2", strHasher("value2")) // NOTE: out of order - db.Set("key1", strHasher("value1")) - assert.Equal(t, "eff12d1c703a1022ab509287c0f196130123d786", fmt.Sprintf("%x", db.Hash()), "Hash didn't match") - } - { - db := newSimpleMap() - db.Set("key1", strHasher("value1")) - db.Set("key2", strHasher("value2")) - db.Set("key3", strHasher("value3")) - assert.Equal(t, "b2c62a277c08dbd2ad73ca53cd1d6bfdf5830d26", fmt.Sprintf("%x", db.Hash()), "Hash didn't match") - } - { - db := newSimpleMap() - db.Set("key2", strHasher("value2")) // NOTE: out of order - db.Set("key1", strHasher("value1")) - db.Set("key3", strHasher("value3")) - assert.Equal(t, "b2c62a277c08dbd2ad73ca53cd1d6bfdf5830d26", fmt.Sprintf("%x", db.Hash()), "Hash didn't match") - } -} diff --git a/merkle/simple_proof.go b/merkle/simple_proof.go deleted file mode 100644 index 2541b6d3..00000000 --- a/merkle/simple_proof.go +++ /dev/null @@ -1,160 +0,0 @@ -package merkle - -import ( - "bytes" - "fmt" -) - -// SimpleProof represents a simple merkle proof. -type SimpleProof struct { - Aunts [][]byte `json:"aunts"` // Hashes from leaf's sibling to a root's child. -} - -// SimpleProofsFromHashers computes inclusion proof for given items. -// proofs[0] is the proof for items[0]. -func SimpleProofsFromHashers(items []Hasher) (rootHash []byte, proofs []*SimpleProof) { - trails, rootSPN := trailsFromHashers(items) - rootHash = rootSPN.Hash - proofs = make([]*SimpleProof, len(items)) - for i, trail := range trails { - proofs[i] = &SimpleProof{ - Aunts: trail.FlattenAunts(), - } - } - return -} - -// SimpleProofsFromMap generates proofs from a map. The keys/values of the map will be used as the keys/values -// in the underlying key-value pairs. -// The keys are sorted before the proofs are computed. -func SimpleProofsFromMap(m map[string]Hasher) (rootHash []byte, proofs map[string]*SimpleProof, keys []string) { - sm := newSimpleMap() - for k, v := range m { - sm.Set(k, v) - } - sm.Sort() - kvs := sm.kvs - kvsH := make([]Hasher, 0, len(kvs)) - for _, kvp := range kvs { - kvsH = append(kvsH, KVPair(kvp)) - } - - rootHash, proofList := SimpleProofsFromHashers(kvsH) - proofs = make(map[string]*SimpleProof) - keys = make([]string, len(proofList)) - for i, kvp := range kvs { - proofs[string(kvp.Key)] = proofList[i] - keys[i] = string(kvp.Key) - } - return -} - -// Verify that leafHash is a leaf hash of the simple-merkle-tree -// which hashes to rootHash. -func (sp *SimpleProof) Verify(index int, total int, leafHash []byte, rootHash []byte) bool { - computedHash := computeHashFromAunts(index, total, leafHash, sp.Aunts) - return computedHash != nil && bytes.Equal(computedHash, rootHash) -} - -// String implements the stringer interface for SimpleProof. -// It is a wrapper around StringIndented. -func (sp *SimpleProof) String() string { - return sp.StringIndented("") -} - -// StringIndented generates a canonical string representation of a SimpleProof. -func (sp *SimpleProof) StringIndented(indent string) string { - return fmt.Sprintf(`SimpleProof{ -%s Aunts: %X -%s}`, - indent, sp.Aunts, - indent) -} - -// Use the leafHash and innerHashes to get the root merkle hash. -// If the length of the innerHashes slice isn't exactly correct, the result is nil. -// Recursive impl. -func computeHashFromAunts(index int, total int, leafHash []byte, innerHashes [][]byte) []byte { - if index >= total || index < 0 || total <= 0 { - return nil - } - switch total { - case 0: - panic("Cannot call computeHashFromAunts() with 0 total") - case 1: - if len(innerHashes) != 0 { - return nil - } - return leafHash - default: - if len(innerHashes) == 0 { - return nil - } - numLeft := (total + 1) / 2 - if index < numLeft { - leftHash := computeHashFromAunts(index, numLeft, leafHash, innerHashes[:len(innerHashes)-1]) - if leftHash == nil { - return nil - } - return SimpleHashFromTwoHashes(leftHash, innerHashes[len(innerHashes)-1]) - } - rightHash := computeHashFromAunts(index-numLeft, total-numLeft, leafHash, innerHashes[:len(innerHashes)-1]) - if rightHash == nil { - return nil - } - return SimpleHashFromTwoHashes(innerHashes[len(innerHashes)-1], rightHash) - } -} - -// SimpleProofNode is a helper structure to construct merkle proof. -// The node and the tree is thrown away afterwards. -// Exactly one of node.Left and node.Right is nil, unless node is the root, in which case both are nil. -// node.Parent.Hash = hash(node.Hash, node.Right.Hash) or -// hash(node.Left.Hash, node.Hash), depending on whether node is a left/right child. -type SimpleProofNode struct { - Hash []byte - Parent *SimpleProofNode - Left *SimpleProofNode // Left sibling (only one of Left,Right is set) - Right *SimpleProofNode // Right sibling (only one of Left,Right is set) -} - -// FlattenAunts will return the inner hashes for the item corresponding to the leaf, -// starting from a leaf SimpleProofNode. -func (spn *SimpleProofNode) FlattenAunts() [][]byte { - // Nonrecursive impl. - innerHashes := [][]byte{} - for spn != nil { - if spn.Left != nil { - innerHashes = append(innerHashes, spn.Left.Hash) - } else if spn.Right != nil { - innerHashes = append(innerHashes, spn.Right.Hash) - } else { - break - } - spn = spn.Parent - } - return innerHashes -} - -// trails[0].Hash is the leaf hash for items[0]. -// trails[i].Parent.Parent....Parent == root for all i. -func trailsFromHashers(items []Hasher) (trails []*SimpleProofNode, root *SimpleProofNode) { - // Recursive impl. - switch len(items) { - case 0: - return nil, nil - case 1: - trail := &SimpleProofNode{items[0].Hash(), nil, nil, nil} - return []*SimpleProofNode{trail}, trail - default: - lefts, leftRoot := trailsFromHashers(items[:(len(items)+1)/2]) - rights, rightRoot := trailsFromHashers(items[(len(items)+1)/2:]) - rootHash := SimpleHashFromTwoHashes(leftRoot.Hash, rightRoot.Hash) - root := &SimpleProofNode{rootHash, nil, nil, nil} - leftRoot.Parent = root - leftRoot.Right = rightRoot - rightRoot.Parent = root - rightRoot.Left = leftRoot - return append(lefts, rights...), root - } -} diff --git a/merkle/simple_tree.go b/merkle/simple_tree.go deleted file mode 100644 index c23f8426..00000000 --- a/merkle/simple_tree.go +++ /dev/null @@ -1,58 +0,0 @@ -package merkle - -import ( - "github.com/tendermint/go-crypto/tmhash" -) - -// SimpleHashFromTwoHashes is the basic operation of the Merkle tree: Hash(left | right). -func SimpleHashFromTwoHashes(left, right []byte) []byte { - var hasher = tmhash.New() - err := encodeByteSlice(hasher, left) - if err != nil { - panic(err) - } - err = encodeByteSlice(hasher, right) - if err != nil { - panic(err) - } - return hasher.Sum(nil) -} - -// SimpleHashFromHashers computes a Merkle tree from items that can be hashed. -func SimpleHashFromHashers(items []Hasher) []byte { - hashes := make([][]byte, len(items)) - for i, item := range items { - hash := item.Hash() - hashes[i] = hash - } - return simpleHashFromHashes(hashes) -} - -// SimpleHashFromMap computes a Merkle tree from sorted map. -// Like calling SimpleHashFromHashers with -// `item = []byte(Hash(key) | Hash(value))`, -// sorted by `item`. -func SimpleHashFromMap(m map[string]Hasher) []byte { - sm := newSimpleMap() - for k, v := range m { - sm.Set(k, v) - } - return sm.Hash() -} - -//---------------------------------------------------------------- - -// Expects hashes! -func simpleHashFromHashes(hashes [][]byte) []byte { - // Recursive impl. - switch len(hashes) { - case 0: - return nil - case 1: - return hashes[0] - default: - left := simpleHashFromHashes(hashes[:(len(hashes)+1)/2]) - right := simpleHashFromHashes(hashes[(len(hashes)+1)/2:]) - return SimpleHashFromTwoHashes(left, right) - } -} diff --git a/merkle/simple_tree_test.go b/merkle/simple_tree_test.go deleted file mode 100644 index db8e3d7f..00000000 --- a/merkle/simple_tree_test.go +++ /dev/null @@ -1,88 +0,0 @@ -package merkle - -import ( - "bytes" - - cmn "github.com/tendermint/tmlibs/common" - . "github.com/tendermint/tmlibs/test" - - "testing" - "github.com/tendermint/go-crypto/tmhash" -) - -type testItem []byte - -func (tI testItem) Hash() []byte { - return []byte(tI) -} - -func TestSimpleProof(t *testing.T) { - - total := 100 - - items := make([]Hasher, total) - for i := 0; i < total; i++ { - items[i] = testItem(cmn.RandBytes(tmhash.Size)) - } - - rootHash := SimpleHashFromHashers(items) - - rootHash2, proofs := SimpleProofsFromHashers(items) - - if !bytes.Equal(rootHash, rootHash2) { - t.Errorf("Unmatched root hashes: %X vs %X", rootHash, rootHash2) - } - - // For each item, check the trail. - for i, item := range items { - itemHash := item.Hash() - proof := proofs[i] - - // Verify success - ok := proof.Verify(i, total, itemHash, rootHash) - if !ok { - t.Errorf("Verification failed for index %v.", i) - } - - // Wrong item index should make it fail - { - ok = proof.Verify((i+1)%total, total, itemHash, rootHash) - if ok { - t.Errorf("Expected verification to fail for wrong index %v.", i) - } - } - - // Trail too long should make it fail - origAunts := proof.Aunts - proof.Aunts = append(proof.Aunts, cmn.RandBytes(32)) - { - ok = proof.Verify(i, total, itemHash, rootHash) - if ok { - t.Errorf("Expected verification to fail for wrong trail length.") - } - } - proof.Aunts = origAunts - - // Trail too short should make it fail - proof.Aunts = proof.Aunts[0 : len(proof.Aunts)-1] - { - ok = proof.Verify(i, total, itemHash, rootHash) - if ok { - t.Errorf("Expected verification to fail for wrong trail length.") - } - } - proof.Aunts = origAunts - - // Mutating the itemHash should make it fail. - ok = proof.Verify(i, total, MutateByteSlice(itemHash), rootHash) - if ok { - t.Errorf("Expected verification to fail for mutated leaf hash") - } - - // Mutating the rootHash should make it fail. - ok = proof.Verify(i, total, itemHash, MutateByteSlice(rootHash)) - if ok { - t.Errorf("Expected verification to fail for mutated root hash") - } - } -} diff --git a/merkle/types.go b/merkle/types.go deleted file mode 100644 index 2fcb3f39..00000000 --- a/merkle/types.go +++ /dev/null @@ -1,38 +0,0 @@ -package merkle - -import ( - "io" - - amino "github.com/tendermint/go-amino" -) - -// Tree is a Merkle tree interface. -type Tree interface { - Size() (size int) - Height() (height int8) - Has(key []byte) (has bool) - Proof(key []byte) (value []byte, proof []byte, exists bool) // TODO make it return an index - Get(key []byte) (index int, value []byte, exists bool) - GetByIndex(index int) (key []byte, value []byte) - Set(key []byte, value []byte) (updated bool) - Remove(key []byte) (value []byte, removed bool) - HashWithCount() (hash []byte, count int) - Hash() (hash []byte) - Save() (hash []byte) - Load(hash []byte) - Copy() Tree - Iterate(func(key []byte, value []byte) (stop bool)) (stopped bool) - IterateRange(start []byte, end []byte, ascending bool, fx func(key []byte, value []byte) (stop bool)) (stopped bool) -} - -// Hasher represents a hashable piece of data which can be hashed in the Tree. -type Hasher interface { - Hash() []byte -} - -//----------------------------------------------------------------------- - -// Uvarint length prefixed byteslice -func encodeByteSlice(w io.Writer, bz []byte) (err error) { - return amino.EncodeByteSlice(w, bz) -} diff --git a/priv_key.go b/priv_key.go deleted file mode 100644 index dbfe64c3..00000000 --- a/priv_key.go +++ /dev/null @@ -1,164 +0,0 @@ -package crypto - -import ( - "crypto/subtle" - - secp256k1 "github.com/btcsuite/btcd/btcec" - "github.com/tendermint/ed25519" - "github.com/tendermint/ed25519/extra25519" -) - -func PrivKeyFromBytes(privKeyBytes []byte) (privKey PrivKey, err error) { - err = cdc.UnmarshalBinaryBare(privKeyBytes, &privKey) - return -} - -//---------------------------------------- - -type PrivKey interface { - Bytes() []byte - Sign(msg []byte) (Signature, error) - PubKey() PubKey - Equals(PrivKey) bool -} - -//------------------------------------- - -var _ PrivKey = PrivKeyEd25519{} - -// Implements PrivKey -type PrivKeyEd25519 [64]byte - -func (privKey PrivKeyEd25519) Bytes() []byte { - return cdc.MustMarshalBinaryBare(privKey) -} - -func (privKey PrivKeyEd25519) Sign(msg []byte) (Signature, error) { - privKeyBytes := [64]byte(privKey) - signatureBytes := ed25519.Sign(&privKeyBytes, msg) - return SignatureEd25519(*signatureBytes), nil -} - -func (privKey PrivKeyEd25519) PubKey() PubKey { - privKeyBytes := [64]byte(privKey) - pubBytes := *ed25519.MakePublicKey(&privKeyBytes) - return PubKeyEd25519(pubBytes) -} - -// Equals - you probably don't need to use this. -// Runs in constant time based on length of the keys. -func (privKey PrivKeyEd25519) Equals(other PrivKey) bool { - if otherEd, ok := other.(PrivKeyEd25519); ok { - return subtle.ConstantTimeCompare(privKey[:], otherEd[:]) == 1 - } else { - return false - } -} - -func (privKey PrivKeyEd25519) ToCurve25519() *[32]byte { - keyCurve25519 := new([32]byte) - privKeyBytes := [64]byte(privKey) - extra25519.PrivateKeyToCurve25519(keyCurve25519, &privKeyBytes) - return keyCurve25519 -} - -// Deterministically generates new priv-key bytes from key. -func (privKey PrivKeyEd25519) Generate(index int) PrivKeyEd25519 { - bz, err := cdc.MarshalBinaryBare(struct { - PrivKey [64]byte - Index int - }{privKey, index}) - if err != nil { - panic(err) - } - newBytes := Sha256(bz) - newKey := new([64]byte) - copy(newKey[:32], newBytes) - ed25519.MakePublicKey(newKey) - return PrivKeyEd25519(*newKey) -} - -func GenPrivKeyEd25519() PrivKeyEd25519 { - privKeyBytes := new([64]byte) - copy(privKeyBytes[:32], CRandBytes(32)) - ed25519.MakePublicKey(privKeyBytes) - return PrivKeyEd25519(*privKeyBytes) -} - -// NOTE: secret should be the output of a KDF like bcrypt, -// if it's derived from user input. -func GenPrivKeyEd25519FromSecret(secret []byte) PrivKeyEd25519 { - privKey32 := Sha256(secret) // Not Ripemd160 because we want 32 bytes. - privKeyBytes := new([64]byte) - copy(privKeyBytes[:32], privKey32) - ed25519.MakePublicKey(privKeyBytes) - return PrivKeyEd25519(*privKeyBytes) -} - -//------------------------------------- - -var _ PrivKey = PrivKeySecp256k1{} - -// Implements PrivKey -type PrivKeySecp256k1 [32]byte - -func (privKey PrivKeySecp256k1) Bytes() []byte { - return cdc.MustMarshalBinaryBare(privKey) -} - -func (privKey PrivKeySecp256k1) Sign(msg []byte) (Signature, error) { - priv__, _ := secp256k1.PrivKeyFromBytes(secp256k1.S256(), privKey[:]) - sig__, err := priv__.Sign(Sha256(msg)) - if err != nil { - return nil, err - } - return SignatureSecp256k1(sig__.Serialize()), nil -} - -func (privKey PrivKeySecp256k1) PubKey() PubKey { - _, pub__ := secp256k1.PrivKeyFromBytes(secp256k1.S256(), privKey[:]) - var pub PubKeySecp256k1 - copy(pub[:], pub__.SerializeCompressed()) - return pub -} - -// Equals - you probably don't need to use this. -// Runs in constant time based on length of the keys. -func (privKey PrivKeySecp256k1) Equals(other PrivKey) bool { - if otherSecp, ok := other.(PrivKeySecp256k1); ok { - return subtle.ConstantTimeCompare(privKey[:], otherSecp[:]) == 1 - } else { - return false - } -} - -/* -// Deterministically generates new priv-key bytes from key. -func (key PrivKeySecp256k1) Generate(index int) PrivKeySecp256k1 { - newBytes := cdc.BinarySha256(struct { - PrivKey [64]byte - Index int - }{key, index}) - var newKey [64]byte - copy(newKey[:], newBytes) - return PrivKeySecp256k1(newKey) -} -*/ - -func GenPrivKeySecp256k1() PrivKeySecp256k1 { - privKeyBytes := [32]byte{} - copy(privKeyBytes[:], CRandBytes(32)) - priv, _ := secp256k1.PrivKeyFromBytes(secp256k1.S256(), privKeyBytes[:]) - copy(privKeyBytes[:], priv.Serialize()) - return PrivKeySecp256k1(privKeyBytes) -} - -// NOTE: secret should be the output of a KDF like bcrypt, -// if it's derived from user input. -func GenPrivKeySecp256k1FromSecret(secret []byte) PrivKeySecp256k1 { - privKey32 := Sha256(secret) // Not Ripemd160 because we want 32 bytes. - priv, _ := secp256k1.PrivKeyFromBytes(secp256k1.S256(), privKey32) - privKeyBytes := [32]byte{} - copy(privKeyBytes[:], priv.Serialize()) - return PrivKeySecp256k1(privKeyBytes) -} diff --git a/priv_key_test.go b/priv_key_test.go deleted file mode 100644 index c43a6d1b..00000000 --- a/priv_key_test.go +++ /dev/null @@ -1,60 +0,0 @@ -package crypto_test - -import ( - "testing" - - "github.com/stretchr/testify/assert" - crypto "github.com/tendermint/go-crypto" -) - -func TestGeneratePrivKey(t *testing.T) { - testPriv := crypto.GenPrivKeyEd25519() - testGenerate := testPriv.Generate(1) - signBytes := []byte("something to sign") - pub := testGenerate.PubKey() - sig, err := testGenerate.Sign(signBytes) - assert.NoError(t, err) - assert.True(t, pub.VerifyBytes(signBytes, sig)) -} - -/* - -type BadKey struct { - PrivKeyEd25519 -} - -func TestReadPrivKey(t *testing.T) { - assert, require := assert.New(t), require.New(t) - - // garbage in, garbage out - garbage := []byte("hjgewugfbiewgofwgewr") - XXX This test wants to register BadKey globally to go-crypto, - but we don't want to support that. - _, err := PrivKeyFromBytes(garbage) - require.Error(err) - - edKey := GenPrivKeyEd25519() - badKey := BadKey{edKey} - - cases := []struct { - key PrivKey - valid bool - }{ - {edKey, true}, - {badKey, false}, - } - - for i, tc := range cases { - data := tc.key.Bytes() - fmt.Println(">>>", data) - key, err := PrivKeyFromBytes(data) - fmt.Printf("!!! %#v\n", key, err) - if tc.valid { - assert.NoError(err, "%d", i) - assert.Equal(tc.key, key, "%d", i) - } else { - assert.Error(err, "%d: %#v", i, key) - } - } -} -*/ diff --git a/pub_key.go b/pub_key.go deleted file mode 100644 index c509ff8d..00000000 --- a/pub_key.go +++ /dev/null @@ -1,149 +0,0 @@ -package crypto - -import ( - "bytes" - "crypto/sha256" - "fmt" - - "golang.org/x/crypto/ripemd160" - - secp256k1 "github.com/btcsuite/btcd/btcec" - - "github.com/tendermint/ed25519" - "github.com/tendermint/ed25519/extra25519" - - cmn "github.com/tendermint/tmlibs/common" - - "github.com/tendermint/go-crypto/tmhash" -) - -// An address is a []byte, but hex-encoded even in JSON. -// []byte leaves us the option to change the address length. -// Use an alias so Unmarshal methods (with ptr receivers) are available too. -type Address = cmn.HexBytes - -func PubKeyFromBytes(pubKeyBytes []byte) (pubKey PubKey, err error) { - err = cdc.UnmarshalBinaryBare(pubKeyBytes, &pubKey) - return -} - -//---------------------------------------- - -type PubKey interface { - Address() Address - Bytes() []byte - VerifyBytes(msg []byte, sig Signature) bool - Equals(PubKey) bool -} - -//------------------------------------- - -var _ PubKey = PubKeyEd25519{} - -// Implements PubKeyInner -type PubKeyEd25519 [32]byte - -// Address is the SHA256-20 of the raw pubkey bytes. -func (pubKey PubKeyEd25519) Address() Address { - return Address(tmhash.Sum(pubKey[:])) -} - -func (pubKey PubKeyEd25519) Bytes() []byte { - bz, err := cdc.MarshalBinaryBare(pubKey) - if err != nil { - panic(err) - } - return bz -} - -func (pubKey PubKeyEd25519) VerifyBytes(msg []byte, sig_ Signature) bool { - // make sure we use the same algorithm to sign - sig, ok := sig_.(SignatureEd25519) - if !ok { - return false - } - pubKeyBytes := [32]byte(pubKey) - sigBytes := [64]byte(sig) - return ed25519.Verify(&pubKeyBytes, msg, &sigBytes) -} - -// For use with golang/crypto/nacl/box -// If error, returns nil. -func (pubKey PubKeyEd25519) ToCurve25519() *[32]byte { - keyCurve25519, pubKeyBytes := new([32]byte), [32]byte(pubKey) - ok := extra25519.PublicKeyToCurve25519(keyCurve25519, &pubKeyBytes) - if !ok { - return nil - } - return keyCurve25519 -} - -func (pubKey PubKeyEd25519) String() string { - return fmt.Sprintf("PubKeyEd25519{%X}", pubKey[:]) -} - -func (pubKey PubKeyEd25519) Equals(other PubKey) bool { - if otherEd, ok := other.(PubKeyEd25519); ok { - return bytes.Equal(pubKey[:], otherEd[:]) - } else { - return false - } -} - -//------------------------------------- - -var _ PubKey = PubKeySecp256k1{} - -// Implements PubKey. -// Compressed pubkey (just the x-cord), -// prefixed with 0x02 or 0x03, depending on the y-cord. -type PubKeySecp256k1 [33]byte - -// Implements Bitcoin style addresses: RIPEMD160(SHA256(pubkey)) -func (pubKey PubKeySecp256k1) Address() Address { - hasherSHA256 := sha256.New() - hasherSHA256.Write(pubKey[:]) // does not error - sha := hasherSHA256.Sum(nil) - - hasherRIPEMD160 := ripemd160.New() - hasherRIPEMD160.Write(sha) // does not error - return Address(hasherRIPEMD160.Sum(nil)) -} - -func (pubKey PubKeySecp256k1) Bytes() []byte { - bz, err := cdc.MarshalBinaryBare(pubKey) - if err != nil { - panic(err) - } - return bz -} - -func (pubKey PubKeySecp256k1) VerifyBytes(msg []byte, sig_ Signature) bool { - // and assert same algorithm to sign and verify - sig, ok := sig_.(SignatureSecp256k1) - if !ok { - return false - } - - pub__, err := secp256k1.ParsePubKey(pubKey[:], secp256k1.S256()) - if err != nil { - return false - } - sig__, err := secp256k1.ParseDERSignature(sig[:], secp256k1.S256()) - if err != nil { - return false - } - return sig__.Verify(Sha256(msg), pub__) -} - -func (pubKey PubKeySecp256k1) String() string { - return fmt.Sprintf("PubKeySecp256k1{%X}", pubKey[:]) -} - -func (pubKey PubKeySecp256k1) Equals(other PubKey) bool { - if otherSecp, ok := other.(PubKeySecp256k1); ok { - return bytes.Equal(pubKey[:], otherSecp[:]) - } else { - return false - } -} diff --git a/pub_key_test.go b/pub_key_test.go deleted file mode 100644 index 7b856cf1..00000000 --- a/pub_key_test.go +++ /dev/null @@ -1,50 +0,0 @@ -package crypto - -import ( - "encoding/hex" - "testing" - - "github.com/btcsuite/btcutil/base58" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -type keyData struct { - priv string - pub string - addr string -} - -var secpDataTable = []keyData{ - { - priv: "a96e62ed3955e65be32703f12d87b6b5cf26039ecfa948dc5107a495418e5330", - pub: "02950e1cdfcb133d6024109fd489f734eeb4502418e538c28481f22bce276f248c", - addr: "1CKZ9Nx4zgds8tU7nJHotKSDr4a9bYJCa3", - }, -} - -func TestPubKeySecp256k1Address(t *testing.T) { - for _, d := range secpDataTable { - privB, _ := hex.DecodeString(d.priv) - pubB, _ := hex.DecodeString(d.pub) - addrBbz, _, _ := base58.CheckDecode(d.addr) - addrB := Address(addrBbz) - - var priv PrivKeySecp256k1 - copy(priv[:], privB) - - pubKey := priv.PubKey() - pubT, _ := pubKey.(PubKeySecp256k1) - pub := pubT[:] - addr := pubKey.Address() - - assert.Equal(t, pub, pubB, "Expected pub keys to match") - assert.Equal(t, addr, addrB, "Expected addresses to match") - } -} - -func TestPubKeyInvalidDataProperReturnsEmpty(t *testing.T) { - pk, err := PubKeyFromBytes([]byte("foo")) - require.NotNil(t, err, "expecting a non-nil error") - require.Nil(t, pk, "expecting an empty public key on error") -} diff --git a/random.go b/random.go deleted file mode 100644 index 66da035a..00000000 --- a/random.go +++ /dev/null @@ -1,108 +0,0 @@ -package crypto - -import ( - "crypto/aes" - "crypto/cipher" - crand "crypto/rand" - "crypto/sha256" - "encoding/hex" - "io" - "sync" - - . "github.com/tendermint/tmlibs/common" -) - -var gRandInfo *randInfo - -func init() { - gRandInfo = &randInfo{} - gRandInfo.MixEntropy(randBytes(32)) // Init -} - -// Mix additional bytes of randomness, e.g. from hardware, user-input, etc. -// It is OK to call it multiple times. It does not diminish security. -func MixEntropy(seedBytes []byte) { - gRandInfo.MixEntropy(seedBytes) -} - -// This only uses the OS's randomness -func randBytes(numBytes int) []byte { - b := make([]byte, numBytes) - _, err := crand.Read(b) - if err != nil { - PanicCrisis(err) - } - return b -} - -// This uses the OS and the Seed(s). -func CRandBytes(numBytes int) []byte { - b := make([]byte, numBytes) - _, err := gRandInfo.Read(b) - if err != nil { - PanicCrisis(err) - } - return b -} - -// CRandHex returns a hex encoded string that's floor(numDigits/2) * 2 long. -// -// Note: CRandHex(24) gives 96 bits of randomness that -// are usually strong enough for most purposes. -func CRandHex(numDigits int) string { - return hex.EncodeToString(CRandBytes(numDigits / 2)) -} - -// Returns a crand.Reader mixed with user-supplied entropy -func CReader() io.Reader { - return gRandInfo -} - -//-------------------------------------------------------------------------------- - -type randInfo struct { - mtx sync.Mutex - seedBytes [32]byte - cipherAES256 cipher.Block - streamAES256 cipher.Stream - reader io.Reader -} - -// You can call this as many times as you'd like. -// XXX TODO review -func (ri *randInfo) MixEntropy(seedBytes []byte) { - ri.mtx.Lock() - defer ri.mtx.Unlock() - // Make new ri.seedBytes using passed seedBytes and current ri.seedBytes: - // ri.seedBytes = sha256( seedBytes || ri.seedBytes ) - h := sha256.New() - h.Write(seedBytes) - h.Write(ri.seedBytes[:]) - hashBytes := h.Sum(nil) - hashBytes32 := [32]byte{} - copy(hashBytes32[:], hashBytes) - ri.seedBytes = xorBytes32(ri.seedBytes, hashBytes32) - // Create new cipher.Block - var err error - ri.cipherAES256, err = aes.NewCipher(ri.seedBytes[:]) - if err != nil { - PanicSanity("Error creating AES256 cipher: " + err.Error()) - } - // Create new stream - ri.streamAES256 = cipher.NewCTR(ri.cipherAES256, randBytes(aes.BlockSize)) - // Create new reader - ri.reader = &cipher.StreamReader{S: ri.streamAES256, R: crand.Reader} -} - -func (ri *randInfo) Read(b []byte) (n int, err error) { - ri.mtx.Lock() - defer ri.mtx.Unlock() - return ri.reader.Read(b) -} - -func xorBytes32(bytesA [32]byte, bytesB [32]byte) (res [32]byte) { - for i, b := range bytesA { - res[i] = b ^ bytesB[i] - } - return res -} diff --git a/signature.go b/signature.go deleted file mode 100644 index 1ffb45ea..00000000 --- a/signature.go +++ /dev/null @@ -1,88 +0,0 @@ -package crypto - -import ( - "fmt" - - "crypto/subtle" - - . "github.com/tendermint/tmlibs/common" -) - -func SignatureFromBytes(pubKeyBytes []byte) (pubKey Signature, err error) { - err = cdc.UnmarshalBinaryBare(pubKeyBytes, &pubKey) - return -} - -//---------------------------------------- - -type Signature interface { - Bytes() []byte - IsZero() bool - Equals(Signature) bool -} - -//------------------------------------- - -var _ Signature = SignatureEd25519{} - -// Implements Signature -type SignatureEd25519 [64]byte - -func (sig SignatureEd25519) Bytes() []byte { - bz, err := cdc.MarshalBinaryBare(sig) - if err != nil { - panic(err) - } - return bz -} - -func (sig SignatureEd25519) IsZero() bool { return len(sig) == 0 } - -func (sig SignatureEd25519) String() string { return fmt.Sprintf("/%X.../", Fingerprint(sig[:])) } - -func (sig SignatureEd25519) Equals(other Signature) bool { - if otherEd, ok := other.(SignatureEd25519); ok { - return subtle.ConstantTimeCompare(sig[:], otherEd[:]) == 1 - } else { - return false - } -} - -func SignatureEd25519FromBytes(data []byte) Signature { - var sig SignatureEd25519 - copy(sig[:], data) - return sig -} - -//------------------------------------- - -var _ Signature = SignatureSecp256k1{} - -// Implements Signature -type SignatureSecp256k1 []byte - -func (sig SignatureSecp256k1) Bytes() []byte { - bz, err := cdc.MarshalBinaryBare(sig) - if err != nil { - panic(err) - } - return bz -} - -func (sig SignatureSecp256k1) IsZero() bool { return len(sig) == 0 } - -func (sig SignatureSecp256k1) String() string { return fmt.Sprintf("/%X.../", Fingerprint(sig[:])) } - -func (sig SignatureSecp256k1) Equals(other Signature) bool { - if otherSecp, ok := other.(SignatureSecp256k1); ok { - return subtle.ConstantTimeCompare(sig[:], otherSecp[:]) == 1 - } else { - return false - } -} - -func SignatureSecp256k1FromBytes(data []byte) Signature { - sig := make(SignatureSecp256k1, len(data)) - copy(sig[:], data) - return sig -} diff --git a/signature_test.go b/signature_test.go deleted file mode 100644 index d6ae2b7a..00000000 --- a/signature_test.go +++ /dev/null @@ -1,46 +0,0 @@ -package crypto - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestSignAndValidateEd25519(t *testing.T) { - - privKey := GenPrivKeyEd25519() - pubKey := privKey.PubKey() - - msg := CRandBytes(128) - sig, err := privKey.Sign(msg) - require.Nil(t, err) - - // Test the signature - assert.True(t, pubKey.VerifyBytes(msg, sig)) - - // Mutate the signature, just one bit. - sigEd := sig.(SignatureEd25519) - sigEd[7] ^= byte(0x01) - sig = sigEd - - assert.False(t, pubKey.VerifyBytes(msg, sig)) -} - -func TestSignAndValidateSecp256k1(t *testing.T) { - privKey := GenPrivKeySecp256k1() - pubKey := privKey.PubKey() - - msg := CRandBytes(128) - sig, err := privKey.Sign(msg) - require.Nil(t, err) - - assert.True(t, pubKey.VerifyBytes(msg, sig)) - - // Mutate the signature, just one bit. - sigEd := sig.(SignatureSecp256k1) - sigEd[3] ^= byte(0x01) - sig = sigEd - - assert.False(t, pubKey.VerifyBytes(msg, sig)) -} diff --git a/symmetric.go b/symmetric.go deleted file mode 100644 index d4ac9b55..00000000 --- a/symmetric.go +++ /dev/null @@ -1,51 +0,0 @@ -package crypto - -import ( - "errors" - - . "github.com/tendermint/tmlibs/common" - "golang.org/x/crypto/nacl/secretbox" -) - -const nonceLen = 24 -const secretLen = 32 - -// secret must be 32 bytes long. Use something like Sha256(Bcrypt(passphrase)) -// The ciphertext is (secretbox.Overhead + 24) bytes longer than the plaintext. -// NOTE: call crypto.MixEntropy() first. -func EncryptSymmetric(plaintext []byte, secret []byte) (ciphertext []byte) { - if len(secret) != secretLen { - PanicSanity(Fmt("Secret must be 32 bytes long, got len %v", len(secret))) - } - nonce := CRandBytes(nonceLen) - nonceArr := [nonceLen]byte{} - copy(nonceArr[:], nonce) - secretArr := [secretLen]byte{} - copy(secretArr[:], secret) - ciphertext = make([]byte, nonceLen+secretbox.Overhead+len(plaintext)) - copy(ciphertext, nonce) - secretbox.Seal(ciphertext[nonceLen:nonceLen], plaintext, &nonceArr, &secretArr) - return ciphertext -} - -// secret must be 32 bytes long. Use something like Sha256(Bcrypt(passphrase)) -// The ciphertext is (secretbox.Overhead + 24) bytes longer than the plaintext. -func DecryptSymmetric(ciphertext []byte, secret []byte) (plaintext []byte, err error) { - if len(secret) != secretLen { - PanicSanity(Fmt("Secret must be 32 bytes long, got len %v", len(secret))) - } - if len(ciphertext) <= secretbox.Overhead+nonceLen { - return nil, errors.New("Ciphertext is too short") - } - nonce := ciphertext[:nonceLen] - nonceArr := [nonceLen]byte{} - copy(nonceArr[:], nonce) - secretArr := [secretLen]byte{} - copy(secretArr[:], secret) - plaintext = make([]byte, len(ciphertext)-nonceLen-secretbox.Overhead) - _, ok := secretbox.Open(plaintext[:0], ciphertext[nonceLen:], &nonceArr, &secretArr) - if !ok { - return nil, errors.New("Ciphertext decryption failed") - } - return plaintext, nil -} diff --git a/symmetric_test.go b/symmetric_test.go deleted file mode 100644 index d92bff1a..00000000 --- a/symmetric_test.go +++ /dev/null @@ -1,42 +0,0 @@ -package crypto - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "golang.org/x/crypto/bcrypt" -) - -func TestSimple(t *testing.T) { - - MixEntropy([]byte("someentropy")) - - plaintext := []byte("sometext") - secret := []byte("somesecretoflengththirtytwo===32") - ciphertext := EncryptSymmetric(plaintext, secret) - plaintext2, err := DecryptSymmetric(ciphertext, secret) - - require.Nil(t, err, "%+v", err) - assert.Equal(t, plaintext, plaintext2) -} - -func TestSimpleWithKDF(t *testing.T) { - - MixEntropy([]byte("someentropy")) - - plaintext := []byte("sometext") - secretPass := []byte("somesecret") - secret, err := bcrypt.GenerateFromPassword(secretPass, 12) - if err != nil { - t.Error(err) - } - secret = Sha256(secret) - - ciphertext := EncryptSymmetric(plaintext, secret) - plaintext2, err := DecryptSymmetric(ciphertext, secret) - - require.Nil(t, err, "%+v", err) - assert.Equal(t, plaintext, plaintext2) -} diff --git a/tmhash/hash.go b/tmhash/hash.go deleted file mode 100644 index 1b29d868..00000000 --- a/tmhash/hash.go +++ /dev/null @@ -1,48 +0,0 @@ -package tmhash - -import ( - "crypto/sha256" - "hash" -) - -const ( - Size = 20 - BlockSize = sha256.BlockSize -) - -type sha256trunc struct { - sha256 hash.Hash -} - -func (h sha256trunc) Write(p []byte) (n int, err error) { - return h.sha256.Write(p) -} -func (h sha256trunc) Sum(b []byte) []byte { - shasum := h.sha256.Sum(b) - return shasum[:Size] -} - -func (h sha256trunc) Reset() { - h.sha256.Reset() -} - -func (h sha256trunc) Size() int { - return Size -} - -func (h sha256trunc) BlockSize() int { - return h.sha256.BlockSize() -} - -// New returns a new hash.Hash. -func New() hash.Hash { - return sha256trunc{ - sha256: sha256.New(), - } -} - -// Sum returns the first 20 bytes of SHA256 of the bz. -func Sum(bz []byte) []byte { - hash := sha256.Sum256(bz) - return hash[:Size] -} diff --git a/tmhash/hash_test.go b/tmhash/hash_test.go deleted file mode 100644 index abf0247a..00000000 --- a/tmhash/hash_test.go +++ /dev/null @@ -1,23 +0,0 @@ -package tmhash_test - -import ( - "crypto/sha256" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/tendermint/go-crypto/tmhash" -) - -func TestHash(t *testing.T) { - testVector := []byte("abc") - hasher := tmhash.New() - hasher.Write(testVector) - bz := hasher.Sum(nil) - - hasher = sha256.New() - hasher.Write(testVector) - bz2 := hasher.Sum(nil) - bz2 = bz2[:20] - - assert.Equal(t, bz, bz2) -} diff --git a/version.go b/version.go deleted file mode 100644 index 77c0bed8..00000000 --- a/version.go +++ /dev/null @@ -1,3 +0,0 @@ -package crypto - -const Version = "0.9.0-dev"