move go-crypto files pre-keys merge

This commit is contained in:
Ethan Frey
2017-04-19 16:51:29 +02:00
parent 8bb25ec5ed
commit 17ed6d178d
24 changed files with 0 additions and 0 deletions
+193
View File
@@ -0,0 +1,193 @@
Tendermint Go-Crypto
Copyright (C) 2015 Tendermint
Apache License
Version 2.0, January 2004
https://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
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
https://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.
+9
View File
@@ -0,0 +1,9 @@
.PHONY: docs
REPO:=github.com/tendermint/go-crypto
docs:
@go get github.com/davecheney/godoc2md
godoc2md $(REPO) > README.md
test:
go test `glide novendor`
+837
View File
@@ -0,0 +1,837 @@
# crypto
`import "github.com/tendermint/go-crypto"`
* [Overview](#pkg-overview)
* [Index](#pkg-index)
* [Subdirectories](#pkg-subdirectories)
## <a name="pkg-overview">Overview</a>
## <a name="pkg-index">Index</a>
* [Constants](#pkg-constants)
* [func CRandBytes(numBytes int) []byte](#CRandBytes)
* [func CRandHex(numDigits int) string](#CRandHex)
* [func CReader() io.Reader](#CReader)
* [func DecodeArmor(armorStr string) (blockType string, headers map[string]string, data []byte, err error)](#DecodeArmor)
* [func DecryptSymmetric(ciphertext []byte, secret []byte) (plaintext []byte, err error)](#DecryptSymmetric)
* [func EncodeArmor(blockType string, headers map[string]string, data []byte) string](#EncodeArmor)
* [func EncryptSymmetric(plaintext []byte, secret []byte) (ciphertext []byte)](#EncryptSymmetric)
* [func MixEntropy(seedBytes []byte)](#MixEntropy)
* [func Ripemd160(bytes []byte) []byte](#Ripemd160)
* [func Sha256(bytes []byte) []byte](#Sha256)
* [type PrivKey](#PrivKey)
* [func PrivKeyFromBytes(privKeyBytes []byte) (privKey PrivKey, err error)](#PrivKeyFromBytes)
* [type PrivKeyEd25519](#PrivKeyEd25519)
* [func GenPrivKeyEd25519() PrivKeyEd25519](#GenPrivKeyEd25519)
* [func GenPrivKeyEd25519FromSecret(secret []byte) PrivKeyEd25519](#GenPrivKeyEd25519FromSecret)
* [func (privKey PrivKeyEd25519) Bytes() []byte](#PrivKeyEd25519.Bytes)
* [func (privKey PrivKeyEd25519) Equals(other PrivKey) bool](#PrivKeyEd25519.Equals)
* [func (privKey PrivKeyEd25519) Generate(index int) PrivKeyEd25519](#PrivKeyEd25519.Generate)
* [func (p PrivKeyEd25519) MarshalJSON() ([]byte, error)](#PrivKeyEd25519.MarshalJSON)
* [func (privKey PrivKeyEd25519) PubKey() PubKey](#PrivKeyEd25519.PubKey)
* [func (privKey PrivKeyEd25519) Sign(msg []byte) Signature](#PrivKeyEd25519.Sign)
* [func (privKey PrivKeyEd25519) String() string](#PrivKeyEd25519.String)
* [func (privKey PrivKeyEd25519) ToCurve25519() *[32]byte](#PrivKeyEd25519.ToCurve25519)
* [func (p *PrivKeyEd25519) UnmarshalJSON(enc []byte) error](#PrivKeyEd25519.UnmarshalJSON)
* [type PrivKeyS](#PrivKeyS)
* [func (p PrivKeyS) Empty() bool](#PrivKeyS.Empty)
* [func (p PrivKeyS) MarshalJSON() ([]byte, error)](#PrivKeyS.MarshalJSON)
* [func (p *PrivKeyS) UnmarshalJSON(data []byte) (err error)](#PrivKeyS.UnmarshalJSON)
* [type PrivKeySecp256k1](#PrivKeySecp256k1)
* [func GenPrivKeySecp256k1() PrivKeySecp256k1](#GenPrivKeySecp256k1)
* [func GenPrivKeySecp256k1FromSecret(secret []byte) PrivKeySecp256k1](#GenPrivKeySecp256k1FromSecret)
* [func (privKey PrivKeySecp256k1) Bytes() []byte](#PrivKeySecp256k1.Bytes)
* [func (privKey PrivKeySecp256k1) Equals(other PrivKey) bool](#PrivKeySecp256k1.Equals)
* [func (p PrivKeySecp256k1) MarshalJSON() ([]byte, error)](#PrivKeySecp256k1.MarshalJSON)
* [func (privKey PrivKeySecp256k1) PubKey() PubKey](#PrivKeySecp256k1.PubKey)
* [func (privKey PrivKeySecp256k1) Sign(msg []byte) Signature](#PrivKeySecp256k1.Sign)
* [func (privKey PrivKeySecp256k1) String() string](#PrivKeySecp256k1.String)
* [func (p *PrivKeySecp256k1) UnmarshalJSON(enc []byte) error](#PrivKeySecp256k1.UnmarshalJSON)
* [type PubKey](#PubKey)
* [func PubKeyFromBytes(pubKeyBytes []byte) (pubKey PubKey, err error)](#PubKeyFromBytes)
* [type PubKeyEd25519](#PubKeyEd25519)
* [func (pubKey PubKeyEd25519) Address() []byte](#PubKeyEd25519.Address)
* [func (pubKey PubKeyEd25519) Bytes() []byte](#PubKeyEd25519.Bytes)
* [func (pubKey PubKeyEd25519) Equals(other PubKey) bool](#PubKeyEd25519.Equals)
* [func (pubKey PubKeyEd25519) KeyString() string](#PubKeyEd25519.KeyString)
* [func (p PubKeyEd25519) MarshalJSON() ([]byte, error)](#PubKeyEd25519.MarshalJSON)
* [func (pubKey PubKeyEd25519) String() string](#PubKeyEd25519.String)
* [func (pubKey PubKeyEd25519) ToCurve25519() *[32]byte](#PubKeyEd25519.ToCurve25519)
* [func (p *PubKeyEd25519) UnmarshalJSON(enc []byte) error](#PubKeyEd25519.UnmarshalJSON)
* [func (pubKey PubKeyEd25519) VerifyBytes(msg []byte, sig_ Signature) bool](#PubKeyEd25519.VerifyBytes)
* [type PubKeyS](#PubKeyS)
* [func (p PubKeyS) Empty() bool](#PubKeyS.Empty)
* [func (p PubKeyS) MarshalJSON() ([]byte, error)](#PubKeyS.MarshalJSON)
* [func (p *PubKeyS) UnmarshalJSON(data []byte) (err error)](#PubKeyS.UnmarshalJSON)
* [type PubKeySecp256k1](#PubKeySecp256k1)
* [func (pubKey PubKeySecp256k1) Address() []byte](#PubKeySecp256k1.Address)
* [func (pubKey PubKeySecp256k1) Bytes() []byte](#PubKeySecp256k1.Bytes)
* [func (pubKey PubKeySecp256k1) Equals(other PubKey) bool](#PubKeySecp256k1.Equals)
* [func (pubKey PubKeySecp256k1) KeyString() string](#PubKeySecp256k1.KeyString)
* [func (p PubKeySecp256k1) MarshalJSON() ([]byte, error)](#PubKeySecp256k1.MarshalJSON)
* [func (pubKey PubKeySecp256k1) String() string](#PubKeySecp256k1.String)
* [func (p *PubKeySecp256k1) UnmarshalJSON(enc []byte) error](#PubKeySecp256k1.UnmarshalJSON)
* [func (pubKey PubKeySecp256k1) VerifyBytes(msg []byte, sig_ Signature) bool](#PubKeySecp256k1.VerifyBytes)
* [type Signature](#Signature)
* [func SignatureFromBytes(sigBytes []byte) (sig Signature, err error)](#SignatureFromBytes)
* [type SignatureEd25519](#SignatureEd25519)
* [func (sig SignatureEd25519) Bytes() []byte](#SignatureEd25519.Bytes)
* [func (sig SignatureEd25519) Equals(other Signature) bool](#SignatureEd25519.Equals)
* [func (sig SignatureEd25519) IsZero() bool](#SignatureEd25519.IsZero)
* [func (p SignatureEd25519) MarshalJSON() ([]byte, error)](#SignatureEd25519.MarshalJSON)
* [func (sig SignatureEd25519) String() string](#SignatureEd25519.String)
* [func (p *SignatureEd25519) UnmarshalJSON(enc []byte) error](#SignatureEd25519.UnmarshalJSON)
* [type SignatureS](#SignatureS)
* [func (p SignatureS) Empty() bool](#SignatureS.Empty)
* [func (p SignatureS) MarshalJSON() ([]byte, error)](#SignatureS.MarshalJSON)
* [func (p *SignatureS) UnmarshalJSON(data []byte) (err error)](#SignatureS.UnmarshalJSON)
* [type SignatureSecp256k1](#SignatureSecp256k1)
* [func (sig SignatureSecp256k1) Bytes() []byte](#SignatureSecp256k1.Bytes)
* [func (sig SignatureSecp256k1) Equals(other Signature) bool](#SignatureSecp256k1.Equals)
* [func (sig SignatureSecp256k1) IsZero() bool](#SignatureSecp256k1.IsZero)
* [func (p SignatureSecp256k1) MarshalJSON() ([]byte, error)](#SignatureSecp256k1.MarshalJSON)
* [func (sig SignatureSecp256k1) String() string](#SignatureSecp256k1.String)
* [func (p *SignatureSecp256k1) UnmarshalJSON(enc []byte) error](#SignatureSecp256k1.UnmarshalJSON)
#### <a name="pkg-files">Package files</a>
[armor.go](/src/github.com/tendermint/go-crypto/armor.go) [hash.go](/src/github.com/tendermint/go-crypto/hash.go) [priv_key.go](/src/github.com/tendermint/go-crypto/priv_key.go) [pub_key.go](/src/github.com/tendermint/go-crypto/pub_key.go) [random.go](/src/github.com/tendermint/go-crypto/random.go) [signature.go](/src/github.com/tendermint/go-crypto/signature.go) [symmetric.go](/src/github.com/tendermint/go-crypto/symmetric.go)
## <a name="pkg-constants">Constants</a>
``` go
const (
TypeEd25519 = byte(0x01)
TypeSecp256k1 = byte(0x02)
NameEd25519 = "ed25519"
NameSecp256k1 = "secp256k1"
)
```
Types of implementations
## <a name="CRandBytes">func</a> [CRandBytes](/src/target/random.go?s=698:734#L28)
``` go
func CRandBytes(numBytes int) []byte
```
This uses the OS and the Seed(s).
## <a name="CRandHex">func</a> [CRandHex](/src/target/random.go?s=924:959#L38)
``` go
func CRandHex(numDigits int) string
```
RandHex(24) gives 96 bits of randomness, strong enough for most purposes.
## <a name="CReader">func</a> [CReader](/src/target/random.go?s=1078:1102#L43)
``` go
func CReader() io.Reader
```
Returns a crand.Reader mixed with user-supplied entropy
## <a name="DecodeArmor">func</a> [DecodeArmor](/src/target/armor.go?s=596:699#L18)
``` go
func DecodeArmor(armorStr string) (blockType string, headers map[string]string, data []byte, err error)
```
## <a name="DecryptSymmetric">func</a> [DecryptSymmetric](/src/target/symmetric.go?s=1048:1133#L23)
``` go
func DecryptSymmetric(ciphertext []byte, secret []byte) (plaintext []byte, err error)
```
secret must be 32 bytes long. Use something like Sha256(Bcrypt(passphrase))
The ciphertext is (secretbox.Overhead + 24) bytes longer than the plaintext.
## <a name="EncodeArmor">func</a> [EncodeArmor](/src/target/armor.go?s=125:206#L1)
``` go
func EncodeArmor(blockType string, headers map[string]string, data []byte) string
```
## <a name="EncryptSymmetric">func</a> [EncryptSymmetric](/src/target/symmetric.go?s=356:430#L6)
``` go
func EncryptSymmetric(plaintext []byte, secret []byte) (ciphertext []byte)
```
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.
## <a name="MixEntropy">func</a> [MixEntropy](/src/target/random.go?s=407:440#L13)
``` go
func MixEntropy(seedBytes []byte)
```
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.
## <a name="Ripemd160">func</a> [Ripemd160](/src/target/hash.go?s=185:220#L4)
``` go
func Ripemd160(bytes []byte) []byte
```
## <a name="Sha256">func</a> [Sha256](/src/target/hash.go?s=78:110#L1)
``` go
func Sha256(bytes []byte) []byte
```
## <a name="PrivKey">type</a> [PrivKey](/src/target/priv_key.go?s=326:435#L5)
``` go
type PrivKey interface {
Bytes() []byte
Sign(msg []byte) Signature
PubKey() PubKey
Equals(PrivKey) bool
}
```
PrivKey is part of PrivAccount and state.PrivValidator.
### <a name="PrivKeyFromBytes">func</a> [PrivKeyFromBytes](/src/target/priv_key.go?s=1302:1373#L50)
``` go
func PrivKeyFromBytes(privKeyBytes []byte) (privKey PrivKey, err error)
```
## <a name="PrivKeyEd25519">type</a> [PrivKeyEd25519](/src/target/priv_key.go?s=1502:1530#L58)
``` go
type PrivKeyEd25519 [64]byte
```
Implements PrivKey
### <a name="GenPrivKeyEd25519">func</a> [GenPrivKeyEd25519](/src/target/priv_key.go?s=3003:3042#L116)
``` go
func GenPrivKeyEd25519() PrivKeyEd25519
```
### <a name="GenPrivKeyEd25519FromSecret">func</a> [GenPrivKeyEd25519FromSecret](/src/target/priv_key.go?s=3290:3352#L125)
``` go
func GenPrivKeyEd25519FromSecret(secret []byte) PrivKeyEd25519
```
NOTE: secret should be the output of a KDF like bcrypt,
if it's derived from user input.
### <a name="PrivKeyEd25519.Bytes">func</a> (PrivKeyEd25519) [Bytes](/src/target/priv_key.go?s=1532:1576#L60)
``` go
func (privKey PrivKeyEd25519) Bytes() []byte
```
### <a name="PrivKeyEd25519.Equals">func</a> (PrivKeyEd25519) [Equals](/src/target/priv_key.go?s=1973:2029#L75)
``` go
func (privKey PrivKeyEd25519) Equals(other PrivKey) bool
```
### <a name="PrivKeyEd25519.Generate">func</a> (PrivKeyEd25519) [Generate](/src/target/priv_key.go?s=2761:2825#L106)
``` go
func (privKey PrivKeyEd25519) Generate(index int) PrivKeyEd25519
```
Deterministically generates new priv-key bytes from key.
### <a name="PrivKeyEd25519.MarshalJSON">func</a> (PrivKeyEd25519) [MarshalJSON](/src/target/priv_key.go?s=2156:2209#L83)
``` go
func (p PrivKeyEd25519) MarshalJSON() ([]byte, error)
```
### <a name="PrivKeyEd25519.PubKey">func</a> (PrivKeyEd25519) [PubKey](/src/target/priv_key.go?s=1826:1871#L70)
``` go
func (privKey PrivKeyEd25519) PubKey() PubKey
```
### <a name="PrivKeyEd25519.Sign">func</a> (PrivKeyEd25519) [Sign](/src/target/priv_key.go?s=1635:1691#L64)
``` go
func (privKey PrivKeyEd25519) Sign(msg []byte) Signature
```
### <a name="PrivKeyEd25519.String">func</a> (PrivKeyEd25519) [String](/src/target/priv_key.go?s=2613:2658#L101)
``` go
func (privKey PrivKeyEd25519) String() string
```
### <a name="PrivKeyEd25519.ToCurve25519">func</a> (PrivKeyEd25519) [ToCurve25519](/src/target/priv_key.go?s=2399:2453#L94)
``` go
func (privKey PrivKeyEd25519) ToCurve25519() *[32]byte
```
### <a name="PrivKeyEd25519.UnmarshalJSON">func</a> (\*PrivKeyEd25519) [UnmarshalJSON](/src/target/priv_key.go?s=2250:2306#L87)
``` go
func (p *PrivKeyEd25519) UnmarshalJSON(enc []byte) error
```
## <a name="PrivKeyS">type</a> [PrivKeyS](/src/target/priv_key.go?s=929:962#L30)
``` go
type PrivKeyS struct {
PrivKey
}
```
PrivKeyS add json serialization to PrivKey
### <a name="PrivKeyS.Empty">func</a> (PrivKeyS) [Empty](/src/target/priv_key.go?s=1241:1271#L46)
``` go
func (p PrivKeyS) Empty() bool
```
### <a name="PrivKeyS.MarshalJSON">func</a> (PrivKeyS) [MarshalJSON](/src/target/priv_key.go?s=964:1011#L34)
``` go
func (p PrivKeyS) MarshalJSON() ([]byte, error)
```
### <a name="PrivKeyS.UnmarshalJSON">func</a> (\*PrivKeyS) [UnmarshalJSON](/src/target/priv_key.go?s=1057:1114#L38)
``` go
func (p *PrivKeyS) UnmarshalJSON(data []byte) (err error)
```
## <a name="PrivKeySecp256k1">type</a> [PrivKeySecp256k1](/src/target/priv_key.go?s=3635:3665#L136)
``` go
type PrivKeySecp256k1 [32]byte
```
Implements PrivKey
### <a name="GenPrivKeySecp256k1">func</a> [GenPrivKeySecp256k1](/src/target/priv_key.go?s=5071:5114#L194)
``` go
func GenPrivKeySecp256k1() PrivKeySecp256k1
```
### <a name="GenPrivKeySecp256k1FromSecret">func</a> [GenPrivKeySecp256k1FromSecret](/src/target/priv_key.go?s=5436:5502#L204)
``` go
func GenPrivKeySecp256k1FromSecret(secret []byte) PrivKeySecp256k1
```
NOTE: secret should be the output of a KDF like bcrypt,
if it's derived from user input.
### <a name="PrivKeySecp256k1.Bytes">func</a> (PrivKeySecp256k1) [Bytes](/src/target/priv_key.go?s=3667:3713#L138)
``` go
func (privKey PrivKeySecp256k1) Bytes() []byte
```
### <a name="PrivKeySecp256k1.Equals">func</a> (PrivKeySecp256k1) [Equals](/src/target/priv_key.go?s=4235:4293#L158)
``` go
func (privKey PrivKeySecp256k1) Equals(other PrivKey) bool
```
### <a name="PrivKeySecp256k1.MarshalJSON">func</a> (PrivKeySecp256k1) [MarshalJSON](/src/target/priv_key.go?s=4426:4481#L166)
``` go
func (p PrivKeySecp256k1) MarshalJSON() ([]byte, error)
```
### <a name="PrivKeySecp256k1.PubKey">func</a> (PrivKeySecp256k1) [PubKey](/src/target/priv_key.go?s=4032:4079#L151)
``` go
func (privKey PrivKeySecp256k1) PubKey() PubKey
```
### <a name="PrivKeySecp256k1.Sign">func</a> (PrivKeySecp256k1) [Sign](/src/target/priv_key.go?s=3772:3830#L142)
``` go
func (privKey PrivKeySecp256k1) Sign(msg []byte) Signature
```
### <a name="PrivKeySecp256k1.String">func</a> (PrivKeySecp256k1) [String](/src/target/priv_key.go?s=4673:4720#L177)
``` go
func (privKey PrivKeySecp256k1) String() string
```
### <a name="PrivKeySecp256k1.UnmarshalJSON">func</a> (\*PrivKeySecp256k1) [UnmarshalJSON](/src/target/priv_key.go?s=4522:4580#L170)
``` go
func (p *PrivKeySecp256k1) UnmarshalJSON(enc []byte) error
```
## <a name="PubKey">type</a> [PubKey](/src/target/pub_key.go?s=361:506#L7)
``` go
type PubKey interface {
Address() []byte
Bytes() []byte
KeyString() string
VerifyBytes(msg []byte, sig Signature) bool
Equals(PubKey) bool
}
```
PubKey is part of Account and Validator.
### <a name="PubKeyFromBytes">func</a> [PubKeyFromBytes](/src/target/pub_key.go?s=1203:1270#L45)
``` go
func PubKeyFromBytes(pubKeyBytes []byte) (pubKey PubKey, err error)
```
## <a name="PubKeyEd25519">type</a> [PubKeyEd25519](/src/target/pub_key.go?s=1396:1423#L53)
``` go
type PubKeyEd25519 [32]byte
```
Implements PubKey
### <a name="PubKeyEd25519.Address">func</a> (PubKeyEd25519) [Address](/src/target/pub_key.go?s=1425:1469#L55)
``` go
func (pubKey PubKeyEd25519) Address() []byte
```
### <a name="PubKeyEd25519.Bytes">func</a> (PubKeyEd25519) [Bytes](/src/target/pub_key.go?s=1789:1831#L68)
``` go
func (pubKey PubKeyEd25519) Bytes() []byte
```
### <a name="PubKeyEd25519.Equals">func</a> (PubKeyEd25519) [Equals](/src/target/pub_key.go?s=3064:3117#L119)
``` go
func (pubKey PubKeyEd25519) Equals(other PubKey) bool
```
### <a name="PubKeyEd25519.KeyString">func</a> (PubKeyEd25519) [KeyString](/src/target/pub_key.go?s=2983:3029#L115)
``` go
func (pubKey PubKeyEd25519) KeyString() string
```
Must return the full bytes in hex.
Used for map keying, etc.
### <a name="PubKeyEd25519.MarshalJSON">func</a> (PubKeyEd25519) [MarshalJSON](/src/target/pub_key.go?s=2279:2331#L87)
``` go
func (p PubKeyEd25519) MarshalJSON() ([]byte, error)
```
### <a name="PubKeyEd25519.String">func</a> (PubKeyEd25519) [String](/src/target/pub_key.go?s=2823:2866#L109)
``` go
func (pubKey PubKeyEd25519) String() string
```
### <a name="PubKeyEd25519.ToCurve25519">func</a> (PubKeyEd25519) [ToCurve25519](/src/target/pub_key.go?s=2585:2637#L100)
``` go
func (pubKey PubKeyEd25519) ToCurve25519() *[32]byte
```
For use with golang/crypto/nacl/box
If error, returns nil.
### <a name="PubKeyEd25519.UnmarshalJSON">func</a> (\*PubKeyEd25519) [UnmarshalJSON](/src/target/pub_key.go?s=2372:2427#L91)
``` go
func (p *PubKeyEd25519) UnmarshalJSON(enc []byte) error
```
### <a name="PubKeyEd25519.VerifyBytes">func</a> (PubKeyEd25519) [VerifyBytes](/src/target/pub_key.go?s=1888:1960#L72)
``` go
func (pubKey PubKeyEd25519) VerifyBytes(msg []byte, sig_ Signature) bool
```
## <a name="PubKeyS">type</a> [PubKeyS](/src/target/pub_key.go?s=841:872#L25)
``` go
type PubKeyS struct {
PubKey
}
```
PubKeyS add json serialization to PubKey
### <a name="PubKeyS.Empty">func</a> (PubKeyS) [Empty](/src/target/pub_key.go?s=1144:1173#L41)
``` go
func (p PubKeyS) Empty() bool
```
### <a name="PubKeyS.MarshalJSON">func</a> (PubKeyS) [MarshalJSON](/src/target/pub_key.go?s=874:920#L29)
``` go
func (p PubKeyS) MarshalJSON() ([]byte, error)
```
### <a name="PubKeyS.UnmarshalJSON">func</a> (\*PubKeyS) [UnmarshalJSON](/src/target/pub_key.go?s=964:1020#L33)
``` go
func (p *PubKeyS) UnmarshalJSON(data []byte) (err error)
```
## <a name="PubKeySecp256k1">type</a> [PubKeySecp256k1](/src/target/pub_key.go?s=3401:3430#L132)
``` go
type PubKeySecp256k1 [33]byte
```
Implements PubKey.
Compressed pubkey (just the x-cord),
prefixed with 0x02 or 0x03, depending on the y-cord.
### <a name="PubKeySecp256k1.Address">func</a> (PubKeySecp256k1) [Address](/src/target/pub_key.go?s=3497:3543#L135)
``` go
func (pubKey PubKeySecp256k1) Address() []byte
```
Implements Bitcoin style addresses: RIPEMD160(SHA256(pubkey))
### <a name="PubKeySecp256k1.Bytes">func</a> (PubKeySecp256k1) [Bytes](/src/target/pub_key.go?s=3774:3818#L145)
``` go
func (pubKey PubKeySecp256k1) Bytes() []byte
```
### <a name="PubKeySecp256k1.Equals">func</a> (PubKeySecp256k1) [Equals](/src/target/pub_key.go?s=4897:4952#L192)
``` go
func (pubKey PubKeySecp256k1) Equals(other PubKey) bool
```
### <a name="PubKeySecp256k1.KeyString">func</a> (PubKeySecp256k1) [KeyString](/src/target/pub_key.go?s=4814:4862#L188)
``` go
func (pubKey PubKeySecp256k1) KeyString() string
```
Must return the full bytes in hex.
Used for map keying, etc.
### <a name="PubKeySecp256k1.MarshalJSON">func</a> (PubKeySecp256k1) [MarshalJSON](/src/target/pub_key.go?s=4405:4459#L171)
``` go
func (p PubKeySecp256k1) MarshalJSON() ([]byte, error)
```
### <a name="PubKeySecp256k1.String">func</a> (PubKeySecp256k1) [String](/src/target/pub_key.go?s=4650:4695#L182)
``` go
func (pubKey PubKeySecp256k1) String() string
```
### <a name="PubKeySecp256k1.UnmarshalJSON">func</a> (\*PubKeySecp256k1) [UnmarshalJSON](/src/target/pub_key.go?s=4500:4557#L175)
``` go
func (p *PubKeySecp256k1) UnmarshalJSON(enc []byte) error
```
### <a name="PubKeySecp256k1.VerifyBytes">func</a> (PubKeySecp256k1) [VerifyBytes](/src/target/pub_key.go?s=3875:3949#L149)
``` go
func (pubKey PubKeySecp256k1) VerifyBytes(msg []byte, sig_ Signature) bool
```
## <a name="Signature">type</a> [Signature](/src/target/signature.go?s=204:304#L3)
``` go
type Signature interface {
Bytes() []byte
IsZero() bool
String() string
Equals(Signature) bool
}
```
Signature is a part of Txs and consensus Votes.
### <a name="SignatureFromBytes">func</a> [SignatureFromBytes](/src/target/signature.go?s=1031:1098#L40)
``` go
func SignatureFromBytes(sigBytes []byte) (sig Signature, err error)
```
## <a name="SignatureEd25519">type</a> [SignatureEd25519](/src/target/signature.go?s=1221:1251#L48)
``` go
type SignatureEd25519 [64]byte
```
Implements Signature
### <a name="SignatureEd25519.Bytes">func</a> (SignatureEd25519) [Bytes](/src/target/signature.go?s=1253:1295#L50)
``` go
func (sig SignatureEd25519) Bytes() []byte
```
### <a name="SignatureEd25519.Equals">func</a> (SignatureEd25519) [Equals](/src/target/signature.go?s=1520:1576#L58)
``` go
func (sig SignatureEd25519) Equals(other Signature) bool
```
### <a name="SignatureEd25519.IsZero">func</a> (SignatureEd25519) [IsZero](/src/target/signature.go?s=1352:1393#L54)
``` go
func (sig SignatureEd25519) IsZero() bool
```
### <a name="SignatureEd25519.MarshalJSON">func</a> (SignatureEd25519) [MarshalJSON](/src/target/signature.go?s=1701:1756#L66)
``` go
func (p SignatureEd25519) MarshalJSON() ([]byte, error)
```
### <a name="SignatureEd25519.String">func</a> (SignatureEd25519) [String](/src/target/signature.go?s=1420:1463#L56)
``` go
func (sig SignatureEd25519) String() string
```
### <a name="SignatureEd25519.UnmarshalJSON">func</a> (\*SignatureEd25519) [UnmarshalJSON](/src/target/signature.go?s=1797:1855#L70)
``` go
func (p *SignatureEd25519) UnmarshalJSON(enc []byte) error
```
## <a name="SignatureS">type</a> [SignatureS](/src/target/signature.go?s=648:685#L20)
``` go
type SignatureS struct {
Signature
}
```
SignatureS add json serialization to Signature
### <a name="SignatureS.Empty">func</a> (SignatureS) [Empty](/src/target/signature.go?s=966:998#L36)
``` go
func (p SignatureS) Empty() bool
```
### <a name="SignatureS.MarshalJSON">func</a> (SignatureS) [MarshalJSON](/src/target/signature.go?s=687:736#L24)
``` go
func (p SignatureS) MarshalJSON() ([]byte, error)
```
### <a name="SignatureS.UnmarshalJSON">func</a> (\*SignatureS) [UnmarshalJSON](/src/target/signature.go?s=780:839#L28)
``` go
func (p *SignatureS) UnmarshalJSON(data []byte) (err error)
```
## <a name="SignatureSecp256k1">type</a> [SignatureSecp256k1](/src/target/signature.go?s=2013:2043#L80)
``` go
type SignatureSecp256k1 []byte
```
Implements Signature
### <a name="SignatureSecp256k1.Bytes">func</a> (SignatureSecp256k1) [Bytes](/src/target/signature.go?s=2045:2089#L82)
``` go
func (sig SignatureSecp256k1) Bytes() []byte
```
### <a name="SignatureSecp256k1.Equals">func</a> (SignatureSecp256k1) [Equals](/src/target/signature.go?s=2318:2376#L90)
``` go
func (sig SignatureSecp256k1) Equals(other Signature) bool
```
### <a name="SignatureSecp256k1.IsZero">func</a> (SignatureSecp256k1) [IsZero](/src/target/signature.go?s=2146:2189#L86)
``` go
func (sig SignatureSecp256k1) IsZero() bool
```
### <a name="SignatureSecp256k1.MarshalJSON">func</a> (SignatureSecp256k1) [MarshalJSON](/src/target/signature.go?s=2502:2559#L97)
``` go
func (p SignatureSecp256k1) MarshalJSON() ([]byte, error)
```
### <a name="SignatureSecp256k1.String">func</a> (SignatureSecp256k1) [String](/src/target/signature.go?s=2216:2261#L88)
``` go
func (sig SignatureSecp256k1) String() string
```
### <a name="SignatureSecp256k1.UnmarshalJSON">func</a> (\*SignatureSecp256k1) [UnmarshalJSON](/src/target/signature.go?s=2597:2657#L101)
``` go
func (p *SignatureSecp256k1) UnmarshalJSON(enc []byte) error
```
- - -
Generated by [godoc2md](http://godoc.org/github.com/davecheney/godoc2md)
+39
View File
@@ -0,0 +1,39 @@
package crypto
import (
"bytes"
"io/ioutil"
. "github.com/tendermint/tmlibs/common"
"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 {
PanicSanity("Error encoding ascii armor: " + err.Error())
}
_, err = w.Write(data)
if err != nil {
PanicSanity("Error encoding ascii armor: " + err.Error())
}
err = w.Close()
if err != nil {
PanicSanity("Error encoding ascii armor: " + err.Error())
}
return string(buf.Bytes())
}
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
}
+20
View File
@@ -0,0 +1,20 @@
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)
}
+35
View File
@@ -0,0 +1,35 @@
// Copyright 2011 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 bcrypt
import "encoding/base64"
const alphabet = "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
var bcEncoding = base64.NewEncoding(alphabet)
func base64Encode(src []byte) []byte {
n := bcEncoding.EncodedLen(len(src))
dst := make([]byte, n)
bcEncoding.Encode(dst, src)
for dst[n-1] == '=' {
n--
}
return dst[:n]
}
func base64Decode(src []byte) ([]byte, error) {
numOfEquals := 4 - (len(src) % 4)
for i := 0; i < numOfEquals; i++ {
src = append(src, '=')
}
dst := make([]byte, bcEncoding.DecodedLen(len(src)))
n, err := bcEncoding.Decode(dst, src)
if err != nil {
return nil, err
}
return dst[:n], nil
}
+292
View File
@@ -0,0 +1,292 @@
package bcrypt
// MODIFIED BY TENDERMINT TO EXPOSE NONCE
// Copyright 2011 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 bcrypt implements Provos and Mazières's bcrypt adaptive hashing
// algorithm. See http://www.usenix.org/event/usenix99/provos/provos.pdf
// The code is a port of Provos and Mazières's C implementation.
import (
"crypto/subtle"
"errors"
"fmt"
"strconv"
"golang.org/x/crypto/blowfish"
)
const (
MinCost int = 4 // the minimum allowable cost as passed in to GenerateFromPassword
MaxCost int = 31 // the maximum allowable cost as passed in to GenerateFromPassword
DefaultCost int = 10 // the cost that will actually be set if a cost below MinCost is passed into GenerateFromPassword
)
// The error returned from CompareHashAndPassword when a password and hash do
// not match.
var ErrMismatchedHashAndPassword = errors.New("crypto/bcrypt: hashedPassword is not the hash of the given password")
// The error returned from CompareHashAndPassword when a hash is too short to
// be a bcrypt hash.
var ErrHashTooShort = errors.New("crypto/bcrypt: hashedSecret too short to be a bcrypted password")
// The error returned from CompareHashAndPassword when a hash was created with
// a bcrypt algorithm newer than this implementation.
type HashVersionTooNewError byte
func (hv HashVersionTooNewError) Error() string {
return fmt.Sprintf("crypto/bcrypt: bcrypt algorithm version '%c' requested is newer than current version '%c'", byte(hv), majorVersion)
}
// The error returned from CompareHashAndPassword when a hash starts with something other than '$'
type InvalidHashPrefixError byte
func (ih InvalidHashPrefixError) Error() string {
return fmt.Sprintf("crypto/bcrypt: bcrypt hashes must start with '$', but hashedSecret started with '%c'", byte(ih))
}
type InvalidCostError int
func (ic InvalidCostError) Error() string {
return fmt.Sprintf("crypto/bcrypt: cost %d is outside allowed range (%d,%d)", int(ic), int(MinCost), int(MaxCost))
}
const (
majorVersion = '2'
minorVersion = 'a'
maxSaltSize = 16
maxCryptedHashSize = 23
encodedSaltSize = 22
encodedHashSize = 31
minHashSize = 59
)
// magicCipherData is an IV for the 64 Blowfish encryption calls in
// bcrypt(). It's the string "OrpheanBeholderScryDoubt" in big-endian bytes.
var magicCipherData = []byte{
0x4f, 0x72, 0x70, 0x68,
0x65, 0x61, 0x6e, 0x42,
0x65, 0x68, 0x6f, 0x6c,
0x64, 0x65, 0x72, 0x53,
0x63, 0x72, 0x79, 0x44,
0x6f, 0x75, 0x62, 0x74,
}
type hashed struct {
hash []byte
salt []byte
cost int // allowed range is MinCost to MaxCost
major byte
minor byte
}
// GenerateFromPassword returns the bcrypt hash of the password at the given
// cost. If the cost given is less than MinCost, the cost will be set to
// DefaultCost, instead. Use CompareHashAndPassword, as defined in this package,
// to compare the returned hashed password with its cleartext version.
func GenerateFromPassword(salt []byte, password []byte, cost int) ([]byte, error) {
if len(salt) != maxSaltSize {
return nil, fmt.Errorf("Salt len must be %v", maxSaltSize)
}
p, err := newFromPassword(salt, password, cost)
if err != nil {
return nil, err
}
return p.Hash(), nil
}
// CompareHashAndPassword compares a bcrypt hashed password with its possible
// plaintext equivalent. Returns nil on success, or an error on failure.
func CompareHashAndPassword(hashedPassword, password []byte) error {
p, err := newFromHash(hashedPassword)
if err != nil {
return err
}
otherHash, err := bcrypt(password, p.cost, p.salt)
if err != nil {
return err
}
otherP := &hashed{otherHash, p.salt, p.cost, p.major, p.minor}
if subtle.ConstantTimeCompare(p.Hash(), otherP.Hash()) == 1 {
return nil
}
return ErrMismatchedHashAndPassword
}
// Cost returns the hashing cost used to create the given hashed
// password. When, in the future, the hashing cost of a password system needs
// to be increased in order to adjust for greater computational power, this
// function allows one to establish which passwords need to be updated.
func Cost(hashedPassword []byte) (int, error) {
p, err := newFromHash(hashedPassword)
if err != nil {
return 0, err
}
return p.cost, nil
}
func newFromPassword(salt []byte, password []byte, cost int) (*hashed, error) {
if cost < MinCost {
cost = DefaultCost
}
p := new(hashed)
p.major = majorVersion
p.minor = minorVersion
err := checkCost(cost)
if err != nil {
return nil, err
}
p.cost = cost
p.salt = base64Encode(salt)
hash, err := bcrypt(password, p.cost, p.salt)
if err != nil {
return nil, err
}
p.hash = hash
return p, err
}
func newFromHash(hashedSecret []byte) (*hashed, error) {
if len(hashedSecret) < minHashSize {
return nil, ErrHashTooShort
}
p := new(hashed)
n, err := p.decodeVersion(hashedSecret)
if err != nil {
return nil, err
}
hashedSecret = hashedSecret[n:]
n, err = p.decodeCost(hashedSecret)
if err != nil {
return nil, err
}
hashedSecret = hashedSecret[n:]
// The "+2" is here because we'll have to append at most 2 '=' to the salt
// when base64 decoding it in expensiveBlowfishSetup().
p.salt = make([]byte, encodedSaltSize, encodedSaltSize+2)
copy(p.salt, hashedSecret[:encodedSaltSize])
hashedSecret = hashedSecret[encodedSaltSize:]
p.hash = make([]byte, len(hashedSecret))
copy(p.hash, hashedSecret)
return p, nil
}
func bcrypt(password []byte, cost int, salt []byte) ([]byte, error) {
cipherData := make([]byte, len(magicCipherData))
copy(cipherData, magicCipherData)
c, err := expensiveBlowfishSetup(password, uint32(cost), salt)
if err != nil {
return nil, err
}
for i := 0; i < 24; i += 8 {
for j := 0; j < 64; j++ {
c.Encrypt(cipherData[i:i+8], cipherData[i:i+8])
}
}
// Bug compatibility with C bcrypt implementations. We only encode 23 of
// the 24 bytes encrypted.
hsh := base64Encode(cipherData[:maxCryptedHashSize])
return hsh, nil
}
func expensiveBlowfishSetup(key []byte, cost uint32, salt []byte) (*blowfish.Cipher, error) {
csalt, err := base64Decode(salt)
if err != nil {
return nil, err
}
// Bug compatibility with C bcrypt implementations. They use the trailing
// NULL in the key string during expansion.
ckey := append(key, 0)
c, err := blowfish.NewSaltedCipher(ckey, csalt)
if err != nil {
return nil, err
}
var i, rounds uint64
rounds = 1 << cost
for i = 0; i < rounds; i++ {
blowfish.ExpandKey(ckey, c)
blowfish.ExpandKey(csalt, c)
}
return c, nil
}
func (p *hashed) Hash() []byte {
arr := make([]byte, 60)
arr[0] = '$'
arr[1] = p.major
n := 2
if p.minor != 0 {
arr[2] = p.minor
n = 3
}
arr[n] = '$'
n += 1
copy(arr[n:], []byte(fmt.Sprintf("%02d", p.cost)))
n += 2
arr[n] = '$'
n += 1
copy(arr[n:], p.salt)
n += encodedSaltSize
copy(arr[n:], p.hash)
n += encodedHashSize
return arr[:n]
}
func (p *hashed) decodeVersion(sbytes []byte) (int, error) {
if sbytes[0] != '$' {
return -1, InvalidHashPrefixError(sbytes[0])
}
if sbytes[1] > majorVersion {
return -1, HashVersionTooNewError(sbytes[1])
}
p.major = sbytes[1]
n := 3
if sbytes[2] != '$' {
p.minor = sbytes[2]
n++
}
return n, nil
}
// sbytes should begin where decodeVersion left off.
func (p *hashed) decodeCost(sbytes []byte) (int, error) {
cost, err := strconv.Atoi(string(sbytes[0:2]))
if err != nil {
return -1, err
}
err = checkCost(cost)
if err != nil {
return -1, err
}
p.cost = cost
return 3, nil
}
func (p *hashed) String() string {
return fmt.Sprintf("&{hash: %#v, salt: %#v, cost: %d, major: %c, minor: %c}", string(p.hash), p.salt, p.cost, p.major, p.minor)
}
func checkCost(cost int) error {
if cost < MinCost || cost > MaxCost {
return InvalidCostError(cost)
}
return nil
}
+9
View File
@@ -0,0 +1,9 @@
package crypto
// Types of implementations
const (
TypeEd25519 = byte(0x01)
TypeSecp256k1 = byte(0x02)
NameEd25519 = "ed25519"
NameSecp256k1 = "secp256k1"
)
+91
View File
@@ -0,0 +1,91 @@
package crypto_test
import (
"fmt"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
data "github.com/tendermint/go-wire/data"
)
type PubName struct {
PubNameInner
}
type PubNameInner interface {
AssertIsPubNameInner()
String() string
}
func (p PubName) MarshalJSON() ([]byte, error) {
return pubNameMapper.ToJSON(p.PubNameInner)
}
func (p *PubName) UnmarshalJSON(data []byte) error {
parsed, err := pubNameMapper.FromJSON(data)
if err == nil && parsed != nil {
p.PubNameInner = parsed.(PubNameInner)
}
return err
}
var pubNameMapper = data.NewMapper(PubName{}).
RegisterImplementation(PubNameFoo{}, "foo", 1).
RegisterImplementation(PubNameBar{}, "bar", 2)
func (f PubNameFoo) AssertIsPubNameInner() {}
func (f PubNameBar) AssertIsPubNameInner() {}
//----------------------------------------
type PubNameFoo struct {
Name string
}
func (f PubNameFoo) String() string { return "Foo: " + f.Name }
type PubNameBar struct {
Age int
}
func (b PubNameBar) String() string { return fmt.Sprintf("Bar #%d", b.Age) }
//----------------------------------------
// TestEncodeDemo tries the various strategies to encode the objects
func TestEncodeDemo(t *testing.T) {
assert, require := assert.New(t), require.New(t)
cases := []struct {
in, out PubNameInner
expected string
}{
{PubName{PubNameFoo{"pub-foo"}}, &PubName{}, "Foo: pub-foo"},
{PubName{PubNameBar{7}}, &PubName{}, "Bar #7"},
}
for i, tc := range cases {
// Make sure it is proper to start
require.Equal(tc.expected, tc.in.String())
// Try to encode as binary
b, err := data.ToWire(tc.in)
if assert.Nil(err, "%d: %#v", i, tc.in) {
err := data.FromWire(b, tc.out)
if assert.Nil(err) {
assert.Equal(tc.expected, tc.out.String())
}
}
// Try to encode it as json
j, err := data.ToJSON(tc.in)
if assert.Nil(err, "%d: %#v", i, tc.in) {
err := data.FromJSON(j, tc.out)
if assert.Nil(err) {
assert.Equal(tc.expected, tc.out.String())
}
}
}
}
+183
View File
@@ -0,0 +1,183 @@
package crypto
import (
"fmt"
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
data "github.com/tendermint/go-wire/data"
wire "github.com/tendermint/go-wire"
)
type byter interface {
Bytes() []byte
}
// go to wire encoding and back
func checkWire(t *testing.T, in byter, reader interface{}, typ byte, size int) {
// test to and from binary
bin, err := data.ToWire(in)
require.Nil(t, err, "%+v", err)
assert.Equal(t, typ, bin[0])
// make sure this is compatible with current (Bytes()) encoding
assert.Equal(t, in.Bytes(), bin)
// make sure we have the expected length
assert.Equal(t, size, len(bin))
err = data.FromWire(bin, reader)
require.Nil(t, err, "%+v", err)
}
// go to json encoding and back
func checkJSON(t *testing.T, in interface{}, reader interface{}, typ string) {
// test to and from binary
js, err := data.ToJSON(in)
require.Nil(t, err, "%+v", err)
styp := `"` + typ + `"`
assert.True(t, strings.Contains(string(js), styp))
err = data.FromJSON(js, reader)
require.Nil(t, err, "%+v", err)
// also check text format
text, err := data.ToText(in)
require.Nil(t, err, "%+v", err)
parts := strings.Split(text, ":")
require.Equal(t, 2, len(parts))
// make sure the first part is the typ string
assert.Equal(t, typ, parts[0])
// and the data is also present in the json
assert.True(t, strings.Contains(string(js), parts[1]))
}
// make sure go-wire json can still figure this out...
func checkWireJSON(t *testing.T, in interface{}, reader interface{}, typ byte) {
// test to and from binary
var err error
js := wire.JSONBytes(in)
btyp := fmt.Sprintf("[%d,", typ)
assert.True(t, strings.HasPrefix(string(js), btyp), string(js))
wire.ReadJSON(reader, js, &err)
require.Nil(t, err, "%+v", err)
}
func TestKeyEncodings(t *testing.T) {
cases := []struct {
privKey PrivKey
keyType byte
keyName string
// 1 (type byte) + size of byte array
privSize, pubSize int
}{
{
privKey: GenPrivKeyEd25519().Wrap(),
keyType: TypeEd25519,
keyName: NameEd25519,
privSize: 65,
pubSize: 33,
},
{
privKey: GenPrivKeySecp256k1().Wrap(),
keyType: TypeSecp256k1,
keyName: NameSecp256k1,
privSize: 33,
pubSize: 34,
},
}
for _, tc := range cases {
// check (de/en)codings of private key
var priv2, priv3, priv4 PrivKey
checkWire(t, tc.privKey, &priv2, tc.keyType, tc.privSize)
assert.EqualValues(t, tc.privKey, priv2)
checkJSON(t, tc.privKey, &priv3, tc.keyName)
assert.EqualValues(t, tc.privKey, priv3)
checkWireJSON(t, tc.privKey, &priv4, tc.keyType)
assert.EqualValues(t, tc.privKey, priv4)
// check (de/en)codings of public key
pubKey := tc.privKey.PubKey()
var pub2, pub3, pub4 PubKey
checkWire(t, pubKey, &pub2, tc.keyType, tc.pubSize)
assert.EqualValues(t, pubKey, pub2)
checkJSON(t, pubKey, &pub3, tc.keyName)
assert.EqualValues(t, pubKey, pub3)
checkWireJSON(t, pubKey, &pub4, tc.keyType)
assert.EqualValues(t, pubKey, pub4)
}
}
func toFromJSON(t *testing.T, in interface{}, recvr interface{}) {
js, err := data.ToJSON(in)
require.Nil(t, err, "%+v", err)
err = data.FromJSON(js, recvr)
require.Nil(t, err, "%+v", err)
}
func TestNilEncodings(t *testing.T) {
// make sure sigs are okay with nil
var a, b Signature
toFromJSON(t, a, &b)
assert.EqualValues(t, a, b)
// make sure sigs are okay with nil
var c, d PubKey
toFromJSON(t, c, &d)
assert.EqualValues(t, c, d)
// make sure sigs are okay with nil
var e, f PrivKey
toFromJSON(t, e, &f)
assert.EqualValues(t, e, f)
}
type SigMessage struct {
Key PubKey
Sig Signature
}
func (s SigMessage) Bytes() []byte {
return wire.BinaryBytes(s)
}
func TestEmbededWireEncodings(t *testing.T) {
assert := assert.New(t)
cases := []struct {
privKey PrivKey
keyType byte
keyName string
size int // pub + sig size
}{
{
privKey: GenPrivKeyEd25519().Wrap(),
keyType: TypeEd25519,
keyName: NameEd25519,
size: 2 + 32 + 64,
},
// {
// privKey: GenPrivKeySecp256k1().Wrap(),
// keyType: TypeSecp256k1,
// keyName: NameSecp256k1,
// size: 2 + 33 + 72, // ugh, either 72 or 73 depending....
// },
}
payload := randBytes(20)
for i, tc := range cases {
pubKey := tc.privKey.PubKey()
sig := tc.privKey.Sign(payload)
assert.True(pubKey.VerifyBytes(payload, sig), "%d", i)
msg := SigMessage{
Key: pubKey,
Sig: sig,
}
var msg2 SigMessage
checkWire(t, msg, &msg2, tc.keyType, tc.size)
}
}
+30
View File
@@ -0,0 +1,30 @@
package: github.com/tendermint/go-crypto
import:
- package: github.com/btcsuite/btcd
subpackages:
- btcec
- package: github.com/btcsuite/btcutil
subpackages:
- base58
- package: github.com/tendermint/ed25519
subpackages:
- extra25519
- package: github.com/tendermint/tmlibs
version: unstable
- package: github.com/tendermint/go-wire
version: unstable
- package: golang.org/x/crypto
subpackages:
- blowfish
- nacl/secretbox
- openpgp/armor
- ripemd160
testImport:
- package: github.com/mndrix/btcutil
- package: github.com/stretchr/testify
version: ^1.1.4
subpackages:
- assert
- require
- package: github.com/tyler-smith/go-bip32
- package: github.com/tyler-smith/go-bip39
+18
View File
@@ -0,0 +1,18 @@
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)
}
+290
View File
@@ -0,0 +1,290 @@
package hd
import (
"crypto/ecdsa"
"crypto/hmac"
"crypto/sha256"
"crypto/sha512"
"encoding/base64"
"encoding/binary"
"encoding/hex"
"errors"
"fmt"
"hash"
"log"
"math/big"
"strconv"
"strings"
"github.com/btcsuite/btcd/btcec"
"github.com/btcsuite/btcutil/base58"
"github.com/tendermint/go-crypto"
"golang.org/x/crypto/ripemd160"
)
func ComputeAddress(pubKeyHex string, chainHex string, path string, index int32) string {
pubKeyBytes := DerivePublicKeyForPath(
HexDecode(pubKeyHex),
HexDecode(chainHex),
fmt.Sprintf("%v/%v", path, index),
)
return AddrFromPubKeyBytes(pubKeyBytes)
}
func ComputePrivateKey(mprivHex string, chainHex string, path string, index int32) string {
privKeyBytes := DerivePrivateKeyForPath(
HexDecode(mprivHex),
HexDecode(chainHex),
fmt.Sprintf("%v/%v", path, index),
)
return HexEncode(privKeyBytes)
}
func ComputeAddressForPrivKey(privKey string) string {
pubKeyBytes := PubKeyBytesFromPrivKeyBytes(HexDecode(privKey), true)
return AddrFromPubKeyBytes(pubKeyBytes)
}
func SignMessage(privKey string, message string, compress bool) string {
prefixBytes := []byte("Bitcoin Signed Message:\n")
messageBytes := []byte(message)
bytes := []byte{}
bytes = append(bytes, byte(len(prefixBytes)))
bytes = append(bytes, prefixBytes...)
bytes = append(bytes, byte(len(messageBytes)))
bytes = append(bytes, messageBytes...)
privKeyBytes := HexDecode(privKey)
x, y := btcec.S256().ScalarBaseMult(privKeyBytes)
ecdsaPubKey := ecdsa.PublicKey{
Curve: btcec.S256(),
X: x,
Y: y,
}
ecdsaPrivKey := &btcec.PrivateKey{
PublicKey: ecdsaPubKey,
D: new(big.Int).SetBytes(privKeyBytes),
}
sigbytes, err := btcec.SignCompact(btcec.S256(), ecdsaPrivKey, crypto.Sha256(crypto.Sha256(bytes)), compress)
if err != nil {
panic(err)
}
return base64.StdEncoding.EncodeToString(sigbytes)
}
// returns MPK, Chain, and master secret in hex.
func ComputeMastersFromSeed(seed string) (string, string, string, string) {
secret, chain := I64([]byte("Bitcoin seed"), []byte(seed))
pubKeyBytes := PubKeyBytesFromPrivKeyBytes(secret, true)
return HexEncode(pubKeyBytes), HexEncode(secret), HexEncode(chain), HexEncode(secret)
}
func ComputeWIF(privKey string, compress bool) string {
return WIFFromPrivKeyBytes(HexDecode(privKey), compress)
}
func ComputeTxId(rawTxHex string) string {
return HexEncode(ReverseBytes(CalcHash256(HexDecode(rawTxHex))))
}
// Private methods...
func printKeyInfo(privKeyBytes []byte, pubKeyBytes []byte, chain []byte) {
if pubKeyBytes == nil {
pubKeyBytes = PubKeyBytesFromPrivKeyBytes(privKeyBytes, true)
}
addr := AddrFromPubKeyBytes(pubKeyBytes)
log.Println("\nprikey:\t%v\npubKeyBytes:\t%v\naddr:\t%v\nchain:\t%v",
HexEncode(privKeyBytes),
HexEncode(pubKeyBytes),
addr,
HexEncode(chain))
}
func DerivePrivateKeyForPath(privKeyBytes []byte, chain []byte, path string) []byte {
data := privKeyBytes
parts := strings.Split(path, "/")
for _, part := range parts {
prime := part[len(part)-1:] == "'"
// prime == private derivation. Otherwise public.
if prime {
part = part[:len(part)-1]
}
i, err := strconv.Atoi(part)
if err != nil {
panic(err)
}
if i < 0 {
panic(errors.New("index too large."))
}
data, chain = DerivePrivateKey(data, chain, uint32(i), prime)
//printKeyInfo(data, nil, chain)
}
return data
}
func DerivePublicKeyForPath(pubKeyBytes []byte, chain []byte, path string) []byte {
data := pubKeyBytes
parts := strings.Split(path, "/")
for _, part := range parts {
prime := part[len(part)-1:] == "'"
if prime {
panic(errors.New("cannot do a prime derivation from public key"))
}
i, err := strconv.Atoi(part)
if err != nil {
panic(err)
}
if i < 0 {
panic(errors.New("index too large."))
}
data, chain = DerivePublicKey(data, chain, uint32(i))
//printKeyInfo(nil, data, chain)
}
return data
}
func DerivePrivateKey(privKeyBytes []byte, chain []byte, i uint32, prime bool) ([]byte, []byte) {
data := []byte{}
if prime {
i = i | 0x80000000
data = append([]byte{byte(0)}, privKeyBytes...)
} else {
public := PubKeyBytesFromPrivKeyBytes(privKeyBytes, true)
data = public
}
data = append(data, uint32ToBytes(i)...)
data2, chain2 := I64(chain, data)
x := addScalars(privKeyBytes, data2)
return x, chain2
}
func DerivePublicKey(pubKeyBytes []byte, chain []byte, i uint32) ([]byte, []byte) {
data := []byte{}
data = append(data, pubKeyBytes...)
data = append(data, uint32ToBytes(i)...)
data2, chain2 := I64(chain, data)
data2p := PubKeyBytesFromPrivKeyBytes(data2, true)
return addPoints(pubKeyBytes, data2p), chain2
}
func addPoints(a []byte, b []byte) []byte {
ap, err := btcec.ParsePubKey(a, btcec.S256())
if err != nil {
panic(err)
}
bp, err := btcec.ParsePubKey(b, btcec.S256())
if err != nil {
panic(err)
}
sumX, sumY := btcec.S256().Add(ap.X, ap.Y, bp.X, bp.Y)
sum := (*btcec.PublicKey)(&btcec.PublicKey{
Curve: btcec.S256(),
X: sumX,
Y: sumY,
})
return sum.SerializeCompressed()
}
func addScalars(a []byte, b []byte) []byte {
aInt := new(big.Int).SetBytes(a)
bInt := new(big.Int).SetBytes(b)
sInt := new(big.Int).Add(aInt, bInt)
x := sInt.Mod(sInt, btcec.S256().N).Bytes()
x2 := [32]byte{}
copy(x2[32-len(x):], x)
return x2[:]
}
func uint32ToBytes(i uint32) []byte {
b := [4]byte{}
binary.BigEndian.PutUint32(b[:], i)
return b[:]
}
func HexEncode(b []byte) string {
return hex.EncodeToString(b)
}
func HexDecode(str string) []byte {
b, _ := hex.DecodeString(str)
return b
}
func I64(key []byte, data []byte) ([]byte, []byte) {
mac := hmac.New(sha512.New, key)
mac.Write(data)
I := mac.Sum(nil)
return I[:32], I[32:]
}
// This returns a Bitcoin-like address.
func AddrFromPubKeyBytes(pubKeyBytes []byte) string {
prefix := byte(0x00) // TODO Make const or configurable
h160 := CalcHash160(pubKeyBytes)
h160 = append([]byte{prefix}, h160...)
checksum := CalcHash256(h160)
b := append(h160, checksum[:4]...)
return base58.Encode(b)
}
func AddrBytesFromPubKeyBytes(pubKeyBytes []byte) (addrBytes []byte, checksum []byte) {
prefix := byte(0x00) // TODO Make const or configurable
h160 := CalcHash160(pubKeyBytes)
_h160 := append([]byte{prefix}, h160...)
checksum = CalcHash256(_h160)[:4]
return h160, checksum
}
func WIFFromPrivKeyBytes(privKeyBytes []byte, compress bool) string {
prefix := byte(0x80) // TODO Make const or configurable
bytes := append([]byte{prefix}, privKeyBytes...)
if compress {
bytes = append(bytes, byte(1))
}
checksum := CalcHash256(bytes)
bytes = append(bytes, checksum[:4]...)
return base58.Encode(bytes)
}
func PubKeyBytesFromPrivKeyBytes(privKeyBytes []byte, compress bool) (pubKeyBytes []byte) {
x, y := btcec.S256().ScalarBaseMult(privKeyBytes)
pub := (*btcec.PublicKey)(&btcec.PublicKey{
Curve: btcec.S256(),
X: x,
Y: y,
})
if compress {
return pub.SerializeCompressed()
}
return pub.SerializeUncompressed()
}
// Calculate the hash of hasher over buf.
func CalcHash(buf []byte, hasher hash.Hash) []byte {
hasher.Write(buf)
return hasher.Sum(nil)
}
// calculate hash160 which is ripemd160(sha256(data))
func CalcHash160(buf []byte) []byte {
return CalcHash(CalcHash(buf, sha256.New()), ripemd160.New())
}
// calculate hash256 which is sha256(sha256(data))
func CalcHash256(buf []byte) []byte {
return CalcHash(CalcHash(buf, sha256.New()), sha256.New())
}
// calculate sha512(data)
func CalcSha512(buf []byte) []byte {
return CalcHash(buf, sha512.New())
}
func ReverseBytes(buf []byte) []byte {
res := []byte{}
for i := len(buf) - 1; i >= 0; i-- {
res = append(res, buf[i])
}
return res
}
+37
View File
@@ -0,0 +1,37 @@
package hd
/*
import (
"encoding/hex"
"fmt"
"testing"
)
func TestManual(t *testing.T) {
bytes, _ := hex.DecodeString("dfac699f1618c9be4df2befe94dc5f313946ebafa386756bd4926a1ecfd7cf2438426ede521d1ee6512391bc200b7910bcbea593e68d52b874c29bdc5a308ed1")
fmt.Println(bytes)
puk, prk, ch, se := ComputeMastersFromSeed(string(bytes))
fmt.Println(puk, ch, se)
pubBytes2 := DerivePublicKeyForPath(
HexDecode(puk),
HexDecode(ch),
//"44'/118'/0'/0/0",
"0/0",
)
fmt.Printf("PUB2 %X\n", pubBytes2)
privBytes := DerivePrivateKeyForPath(
HexDecode(prk),
HexDecode(ch),
//"44'/118'/0'/0/0",
//"0/0",
"44'/118'/0'/0/0",
)
fmt.Printf("PRIV %X\n", privBytes)
pubBytes := PubKeyBytesFromPrivKeyBytes(privBytes, true)
fmt.Printf("PUB %X\n", pubBytes)
}
*/
+189
View File
@@ -0,0 +1,189 @@
package hd
import (
"bytes"
"crypto/hmac"
"crypto/sha512"
"encoding/binary"
"encoding/hex"
"encoding/json"
"fmt"
"io/ioutil"
"os"
"testing"
"github.com/stretchr/testify/assert"
"github.com/tyler-smith/go-bip39"
"github.com/btcsuite/btcd/chaincfg"
"github.com/btcsuite/btcutil/hdkeychain"
"github.com/mndrix/btcutil"
"github.com/tyler-smith/go-bip32"
"github.com/tendermint/go-crypto"
)
type addrData struct {
Mnemonic string
Master string
Seed string
Priv string
Pub string
Addr string
}
// NOTE: atom fundraiser address
var hdPath string = "m/44'/118'/0'/0/0"
var hdToAddrTable []addrData
func init() {
b, err := ioutil.ReadFile("test.json")
if err != nil {
fmt.Println(err)
os.Exit(1)
}
err = json.Unmarshal(b, &hdToAddrTable)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
}
func TestHDToAddr(t *testing.T) {
for i, d := range hdToAddrTable {
privB, _ := hex.DecodeString(d.Priv)
pubB, _ := hex.DecodeString(d.Pub)
addrB, _ := hex.DecodeString(d.Addr)
seedB, _ := hex.DecodeString(d.Seed)
masterB, _ := hex.DecodeString(d.Master)
seed := bip39.NewSeed(d.Mnemonic, "")
fmt.Println("================================")
fmt.Println("ROUND:", i, "MNEMONIC:", d.Mnemonic)
// master, priv, pub := tylerSmith(seed)
// master, priv, pub := btcsuite(seed)
master, priv, pub := gocrypto(seed)
fmt.Printf("\tNODEJS GOLANG\n")
fmt.Printf("SEED \t%X %X\n", seedB, seed)
fmt.Printf("MSTR \t%X %X\n", masterB, master)
fmt.Printf("PRIV \t%X %X\n", privB, priv)
fmt.Printf("PUB \t%X %X\n", pubB, pub)
_, _ = priv, privB
assert.Equal(t, master, masterB, fmt.Sprintf("Expected masters to match for %d", i))
assert.Equal(t, priv, privB, "Expected priv keys to match")
assert.Equal(t, pub, pubB, fmt.Sprintf("Expected pub keys to match for %d", i))
var pubT crypto.PubKeySecp256k1
copy(pubT[:], pub)
addr := pubT.Address()
fmt.Printf("ADDR \t%X %X\n", addrB, addr)
assert.Equal(t, addr, addrB, fmt.Sprintf("Expected addresses to match %d", i))
}
}
func ifExit(err error, n int) {
if err != nil {
fmt.Println(n, err)
os.Exit(1)
}
}
func gocrypto(seed []byte) ([]byte, []byte, []byte) {
_, priv, ch, _ := ComputeMastersFromSeed(string(seed))
privBytes := DerivePrivateKeyForPath(
HexDecode(priv),
HexDecode(ch),
"44'/118'/0'/0/0",
)
pubBytes := PubKeyBytesFromPrivKeyBytes(privBytes, true)
return HexDecode(priv), privBytes, pubBytes
}
func btcsuite(seed []byte) ([]byte, []byte, []byte) {
fmt.Println("HD")
masterKey, err := hdkeychain.NewMaster(seed, &chaincfg.MainNetParams)
if err != nil {
hmac := hmac.New(sha512.New, []byte("Bitcoin seed"))
hmac.Write([]byte(seed))
intermediary := hmac.Sum(nil)
curve := btcutil.Secp256k1()
curveParams := curve.Params()
// Split it into our key and chain code
keyBytes := intermediary[:32]
fmt.Printf("\t%X\n", keyBytes)
fmt.Printf("\t%X\n", curveParams.N.Bytes())
keyInt, _ := binary.ReadVarint(bytes.NewBuffer(keyBytes))
fmt.Printf("\t%d\n", keyInt)
}
fh := hdkeychain.HardenedKeyStart
k, err := masterKey.Child(uint32(fh + 44))
ifExit(err, 44)
k, err = k.Child(uint32(fh + 118))
ifExit(err, 118)
k, err = k.Child(uint32(fh + 0))
ifExit(err, 1)
k, err = k.Child(uint32(0))
ifExit(err, 2)
k, err = k.Child(uint32(0))
ifExit(err, 3)
ecpriv, err := k.ECPrivKey()
ifExit(err, 10)
ecpub, err := k.ECPubKey()
ifExit(err, 11)
priv := ecpriv.Serialize()
pub := ecpub.SerializeCompressed()
mkey, _ := masterKey.ECPrivKey()
return mkey.Serialize(), priv, pub
}
// return priv and pub
func tylerSmith(seed []byte) ([]byte, []byte, []byte) {
masterKey, err := bip32.NewMasterKey(seed)
if err != nil {
hmac := hmac.New(sha512.New, []byte("Bitcoin seed"))
hmac.Write([]byte(seed))
intermediary := hmac.Sum(nil)
curve := btcutil.Secp256k1()
curveParams := curve.Params()
// Split it into our key and chain code
keyBytes := intermediary[:32]
fmt.Printf("\t%X\n", keyBytes)
fmt.Printf("\t%X\n", curveParams.N.Bytes())
keyInt, _ := binary.ReadVarint(bytes.NewBuffer(keyBytes))
fmt.Printf("\t%d\n", keyInt)
}
ifExit(err, 0)
fh := bip32.FirstHardenedChild
k, err := masterKey.NewChildKey(fh + 44)
ifExit(err, 44)
k, err = k.NewChildKey(fh + 118)
ifExit(err, 118)
k, err = k.NewChildKey(fh + 0)
ifExit(err, 1)
k, err = k.NewChildKey(0)
ifExit(err, 2)
k, err = k.NewChildKey(0)
ifExit(err, 3)
priv := k.Key
pub := k.PublicKey().Key
return masterKey.Key, priv, pub
}
File diff suppressed because one or more lines are too long
+237
View File
@@ -0,0 +1,237 @@
package crypto
import (
"bytes"
secp256k1 "github.com/btcsuite/btcd/btcec"
"github.com/tendermint/ed25519"
"github.com/tendermint/ed25519/extra25519"
. "github.com/tendermint/tmlibs/common"
data "github.com/tendermint/go-wire/data"
"github.com/tendermint/go-wire"
)
func PrivKeyFromBytes(privKeyBytes []byte) (privKey PrivKey, err error) {
err = wire.ReadBinaryBytes(privKeyBytes, &privKey)
return
}
//----------------------------------------
type PrivKey struct {
PrivKeyInner `json:"unwrap"`
}
// DO NOT USE THIS INTERFACE.
// You probably want to use PubKey
type PrivKeyInner interface {
AssertIsPrivKeyInner()
Bytes() []byte
Sign(msg []byte) Signature
PubKey() PubKey
Equals(PrivKey) bool
Wrap() PrivKey
}
func (p PrivKey) MarshalJSON() ([]byte, error) {
return privKeyMapper.ToJSON(p.PrivKeyInner)
}
func (p *PrivKey) UnmarshalJSON(data []byte) (err error) {
parsed, err := privKeyMapper.FromJSON(data)
if err == nil && parsed != nil {
p.PrivKeyInner = parsed.(PrivKeyInner)
}
return
}
// Unwrap recovers the concrete interface safely (regardless of levels of embeds)
func (p PrivKey) Unwrap() PrivKeyInner {
pk := p.PrivKeyInner
for wrap, ok := pk.(PrivKey); ok; wrap, ok = pk.(PrivKey) {
pk = wrap.PrivKeyInner
}
return pk
}
func (p PrivKey) Empty() bool {
return p.PrivKeyInner == nil
}
var privKeyMapper = data.NewMapper(PrivKey{}).
RegisterImplementation(PrivKeyEd25519{}, NameEd25519, TypeEd25519).
RegisterImplementation(PrivKeySecp256k1{}, NameSecp256k1, TypeSecp256k1)
//-------------------------------------
var _ PrivKeyInner = PrivKeyEd25519{}
// Implements PrivKey
type PrivKeyEd25519 [64]byte
func (privKey PrivKeyEd25519) AssertIsPrivKeyInner() {}
func (privKey PrivKeyEd25519) Bytes() []byte {
return wire.BinaryBytes(PrivKey{privKey})
}
func (privKey PrivKeyEd25519) Sign(msg []byte) Signature {
privKeyBytes := [64]byte(privKey)
signatureBytes := ed25519.Sign(&privKeyBytes, msg)
return SignatureEd25519(*signatureBytes).Wrap()
}
func (privKey PrivKeyEd25519) PubKey() PubKey {
privKeyBytes := [64]byte(privKey)
pubBytes := *ed25519.MakePublicKey(&privKeyBytes)
return PubKeyEd25519(pubBytes).Wrap()
}
func (privKey PrivKeyEd25519) Equals(other PrivKey) bool {
if otherEd, ok := other.Unwrap().(PrivKeyEd25519); ok {
return bytes.Equal(privKey[:], otherEd[:])
} else {
return false
}
}
func (p PrivKeyEd25519) MarshalJSON() ([]byte, error) {
return data.Encoder.Marshal(p[:])
}
func (p *PrivKeyEd25519) UnmarshalJSON(enc []byte) error {
var ref []byte
err := data.Encoder.Unmarshal(&ref, enc)
copy(p[:], ref)
return err
}
func (privKey PrivKeyEd25519) ToCurve25519() *[32]byte {
keyCurve25519 := new([32]byte)
privKeyBytes := [64]byte(privKey)
extra25519.PrivateKeyToCurve25519(keyCurve25519, &privKeyBytes)
return keyCurve25519
}
func (privKey PrivKeyEd25519) String() string {
return Fmt("PrivKeyEd25519{*****}")
}
// Deterministically generates new priv-key bytes from key.
func (privKey PrivKeyEd25519) Generate(index int) PrivKeyEd25519 {
newBytes := wire.BinarySha256(struct {
PrivKey [64]byte
Index int
}{privKey, index})
var newKey [64]byte
copy(newKey[:], newBytes)
return PrivKeyEd25519(newKey)
}
func (privKey PrivKeyEd25519) Wrap() PrivKey {
return PrivKey{privKey}
}
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 _ PrivKeyInner = PrivKeySecp256k1{}
// Implements PrivKey
type PrivKeySecp256k1 [32]byte
func (privKey PrivKeySecp256k1) AssertIsPrivKeyInner() {}
func (privKey PrivKeySecp256k1) Bytes() []byte {
return wire.BinaryBytes(PrivKey{privKey})
}
func (privKey PrivKeySecp256k1) Sign(msg []byte) Signature {
priv__, _ := secp256k1.PrivKeyFromBytes(secp256k1.S256(), privKey[:])
sig__, err := priv__.Sign(Sha256(msg))
if err != nil {
PanicSanity(err)
}
return SignatureSecp256k1(sig__.Serialize()).Wrap()
}
func (privKey PrivKeySecp256k1) PubKey() PubKey {
_, pub__ := secp256k1.PrivKeyFromBytes(secp256k1.S256(), privKey[:])
var pub PubKeySecp256k1
copy(pub[:], pub__.SerializeCompressed())
return pub.Wrap()
}
func (privKey PrivKeySecp256k1) Equals(other PrivKey) bool {
if otherSecp, ok := other.Unwrap().(PrivKeySecp256k1); ok {
return bytes.Equal(privKey[:], otherSecp[:])
} else {
return false
}
}
func (p PrivKeySecp256k1) MarshalJSON() ([]byte, error) {
return data.Encoder.Marshal(p[:])
}
func (p *PrivKeySecp256k1) UnmarshalJSON(enc []byte) error {
var ref []byte
err := data.Encoder.Unmarshal(&ref, enc)
copy(p[:], ref)
return err
}
func (privKey PrivKeySecp256k1) String() string {
return Fmt("PrivKeySecp256k1{*****}")
}
func (privKey PrivKeySecp256k1) Wrap() PrivKey {
return PrivKey{privKey}
}
/*
// Deterministically generates new priv-key bytes from key.
func (key PrivKeySecp256k1) Generate(index int) PrivKeySecp256k1 {
newBytes := wire.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)
}
+224
View File
@@ -0,0 +1,224 @@
package crypto
import (
"bytes"
"crypto/sha256"
secp256k1 "github.com/btcsuite/btcd/btcec"
"github.com/tendermint/ed25519"
"github.com/tendermint/ed25519/extra25519"
. "github.com/tendermint/tmlibs/common"
data "github.com/tendermint/go-wire/data"
"github.com/tendermint/go-wire"
"golang.org/x/crypto/ripemd160"
)
func PubKeyFromBytes(pubKeyBytes []byte) (pubKey PubKey, err error) {
err = wire.ReadBinaryBytes(pubKeyBytes, &pubKey)
return
}
//----------------------------------------
type PubKey struct {
PubKeyInner `json:"unwrap"`
}
// DO NOT USE THIS INTERFACE.
// You probably want to use PubKey
type PubKeyInner interface {
AssertIsPubKeyInner()
Address() []byte
Bytes() []byte
KeyString() string
VerifyBytes(msg []byte, sig Signature) bool
Equals(PubKey) bool
Wrap() PubKey
}
func (pk PubKey) MarshalJSON() ([]byte, error) {
return pubKeyMapper.ToJSON(pk.PubKeyInner)
}
func (pk *PubKey) UnmarshalJSON(data []byte) (err error) {
parsed, err := pubKeyMapper.FromJSON(data)
if err == nil && parsed != nil {
pk.PubKeyInner = parsed.(PubKeyInner)
}
return
}
// Unwrap recovers the concrete interface safely (regardless of levels of embeds)
func (pk PubKey) Unwrap() PubKeyInner {
pkI := pk.PubKeyInner
for wrap, ok := pkI.(PubKey); ok; wrap, ok = pkI.(PubKey) {
pkI = wrap.PubKeyInner
}
return pkI
}
func (p PubKey) Empty() bool {
return p.PubKeyInner == nil
}
var pubKeyMapper = data.NewMapper(PubKey{}).
RegisterImplementation(PubKeyEd25519{}, NameEd25519, TypeEd25519).
RegisterImplementation(PubKeySecp256k1{}, NameSecp256k1, TypeSecp256k1)
//-------------------------------------
var _ PubKeyInner = PubKeyEd25519{}
// Implements PubKeyInner
type PubKeyEd25519 [32]byte
func (pubKey PubKeyEd25519) AssertIsPubKeyInner() {}
func (pubKey PubKeyEd25519) Address() []byte {
w, n, err := new(bytes.Buffer), new(int), new(error)
wire.WriteBinary(pubKey[:], w, n, err)
if *err != nil {
PanicCrisis(*err)
}
// append type byte
encodedPubkey := append([]byte{TypeEd25519}, w.Bytes()...)
hasher := ripemd160.New()
hasher.Write(encodedPubkey) // does not error
return hasher.Sum(nil)
}
func (pubKey PubKeyEd25519) Bytes() []byte {
return wire.BinaryBytes(PubKey{pubKey})
}
func (pubKey PubKeyEd25519) VerifyBytes(msg []byte, sig_ Signature) bool {
// make sure we use the same algorithm to sign
sig, ok := sig_.Unwrap().(SignatureEd25519)
if !ok {
return false
}
pubKeyBytes := [32]byte(pubKey)
sigBytes := [64]byte(sig)
return ed25519.Verify(&pubKeyBytes, msg, &sigBytes)
}
func (p PubKeyEd25519) MarshalJSON() ([]byte, error) {
return data.Encoder.Marshal(p[:])
}
func (p *PubKeyEd25519) UnmarshalJSON(enc []byte) error {
var ref []byte
err := data.Encoder.Unmarshal(&ref, enc)
copy(p[:], ref)
return err
}
// 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("PubKeyEd25519{%X}", pubKey[:])
}
// Must return the full bytes in hex.
// Used for map keying, etc.
func (pubKey PubKeyEd25519) KeyString() string {
return Fmt("%X", pubKey[:])
}
func (pubKey PubKeyEd25519) Equals(other PubKey) bool {
if otherEd, ok := other.Unwrap().(PubKeyEd25519); ok {
return bytes.Equal(pubKey[:], otherEd[:])
} else {
return false
}
}
func (pubKey PubKeyEd25519) Wrap() PubKey {
return PubKey{pubKey}
}
//-------------------------------------
var _ PubKeyInner = PubKeySecp256k1{}
// Implements PubKey.
// Compressed pubkey (just the x-cord),
// prefixed with 0x02 or 0x03, depending on the y-cord.
type PubKeySecp256k1 [33]byte
func (pubKey PubKeySecp256k1) AssertIsPubKeyInner() {}
// Implements Bitcoin style addresses: RIPEMD160(SHA256(pubkey))
func (pubKey PubKeySecp256k1) Address() []byte {
hasherSHA256 := sha256.New()
hasherSHA256.Write(pubKey[:]) // does not error
sha := hasherSHA256.Sum(nil)
hasherRIPEMD160 := ripemd160.New()
hasherRIPEMD160.Write(sha) // does not error
return hasherRIPEMD160.Sum(nil)
}
func (pubKey PubKeySecp256k1) Bytes() []byte {
return wire.BinaryBytes(PubKey{pubKey})
}
func (pubKey PubKeySecp256k1) VerifyBytes(msg []byte, sig_ Signature) bool {
// and assert same algorithm to sign and verify
sig, ok := sig_.Unwrap().(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 (p PubKeySecp256k1) MarshalJSON() ([]byte, error) {
return data.Encoder.Marshal(p[:])
}
func (p *PubKeySecp256k1) UnmarshalJSON(enc []byte) error {
var ref []byte
err := data.Encoder.Unmarshal(&ref, enc)
copy(p[:], ref)
return err
}
func (pubKey PubKeySecp256k1) String() string {
return Fmt("PubKeySecp256k1{%X}", pubKey[:])
}
// Must return the full bytes in hex.
// Used for map keying, etc.
func (pubKey PubKeySecp256k1) KeyString() string {
return Fmt("%X", pubKey[:])
}
func (pubKey PubKeySecp256k1) Equals(other PubKey) bool {
if otherSecp, ok := other.Unwrap().(PubKeySecp256k1); ok {
return bytes.Equal(pubKey[:], otherSecp[:])
} else {
return false
}
}
func (pubKey PubKeySecp256k1) Wrap() PubKey {
return PubKey{pubKey}
}
+41
View File
@@ -0,0 +1,41 @@
package crypto
import (
"encoding/hex"
"testing"
"github.com/btcsuite/btcutil/base58"
"github.com/stretchr/testify/assert"
)
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)
addrB, _, _ := base58.CheckDecode(d.addr)
var priv PrivKeySecp256k1
copy(priv[:], privB)
pubT := priv.PubKey().Unwrap().(PubKeySecp256k1)
pub := pubT[:]
addr := priv.PubKey().Address()
assert.Equal(t, pub, pubB, "Expected pub keys to match")
assert.Equal(t, addr, addrB, "Expected addresses to match")
}
}
+100
View File
@@ -0,0 +1,100 @@
package crypto
import (
"crypto/aes"
"crypto/cipher"
crand "crypto/rand"
"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
}
// RandHex(24) gives 96 bits of randomness, 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
hashBytes := Sha256(seedBytes)
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
}
+137
View File
@@ -0,0 +1,137 @@
package crypto
import (
"bytes"
"fmt"
. "github.com/tendermint/tmlibs/common"
data "github.com/tendermint/go-wire/data"
"github.com/tendermint/go-wire"
)
func SignatureFromBytes(sigBytes []byte) (sig Signature, err error) {
err = wire.ReadBinaryBytes(sigBytes, &sig)
return
}
//----------------------------------------
type Signature struct {
SignatureInner `json:"unwrap"`
}
// DO NOT USE THIS INTERFACE.
// You probably want to use Signature.
type SignatureInner interface {
AssertIsSignatureInner()
Bytes() []byte
IsZero() bool
String() string
Equals(Signature) bool
Wrap() Signature
}
func (sig Signature) MarshalJSON() ([]byte, error) {
return sigMapper.ToJSON(sig.SignatureInner)
}
func (sig *Signature) UnmarshalJSON(data []byte) (err error) {
parsed, err := sigMapper.FromJSON(data)
if err == nil && parsed != nil {
sig.SignatureInner = parsed.(SignatureInner)
}
return
}
// Unwrap recovers the concrete interface safely (regardless of levels of embeds)
func (sig Signature) Unwrap() SignatureInner {
pk := sig.SignatureInner
for wrap, ok := pk.(Signature); ok; wrap, ok = pk.(Signature) {
pk = wrap.SignatureInner
}
return pk
}
func (sig Signature) Empty() bool {
return sig.SignatureInner == nil
}
var sigMapper = data.NewMapper(Signature{}).
RegisterImplementation(SignatureEd25519{}, NameEd25519, TypeEd25519).
RegisterImplementation(SignatureSecp256k1{}, NameSecp256k1, TypeSecp256k1)
//-------------------------------------
var _ SignatureInner = SignatureEd25519{}
// Implements Signature
type SignatureEd25519 [64]byte
func (sig SignatureEd25519) AssertIsSignatureInner() {}
func (sig SignatureEd25519) Bytes() []byte {
return wire.BinaryBytes(Signature{sig})
}
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.Unwrap().(SignatureEd25519); ok {
return bytes.Equal(sig[:], otherEd[:])
} else {
return false
}
}
func (sig SignatureEd25519) MarshalJSON() ([]byte, error) {
return data.Encoder.Marshal(sig[:])
}
func (sig *SignatureEd25519) UnmarshalJSON(enc []byte) error {
var ref []byte
err := data.Encoder.Unmarshal(&ref, enc)
copy(sig[:], ref)
return err
}
func (sig SignatureEd25519) Wrap() Signature {
return Signature{sig}
}
//-------------------------------------
var _ SignatureInner = SignatureSecp256k1{}
// Implements Signature
type SignatureSecp256k1 []byte
func (sig SignatureSecp256k1) AssertIsSignatureInner() {}
func (sig SignatureSecp256k1) Bytes() []byte {
return wire.BinaryBytes(Signature{sig})
}
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 otherEd, ok := other.Unwrap().(SignatureSecp256k1); ok {
return bytes.Equal(sig[:], otherEd[:])
} else {
return false
}
}
func (sig SignatureSecp256k1) MarshalJSON() ([]byte, error) {
return data.Encoder.Marshal(sig)
}
func (sig *SignatureSecp256k1) UnmarshalJSON(enc []byte) error {
return data.Encoder.Unmarshal((*[]byte)(sig), enc)
}
func (sig SignatureSecp256k1) Wrap() Signature {
return Signature{sig}
}
+143
View File
@@ -0,0 +1,143 @@
package crypto
import (
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/tendermint/ed25519"
data "github.com/tendermint/go-wire/data"
)
func TestSignAndValidateEd25519(t *testing.T) {
privKey := GenPrivKeyEd25519()
pubKey := privKey.PubKey()
msg := CRandBytes(128)
sig := privKey.Sign(msg)
// Test the signature
assert.True(t, pubKey.VerifyBytes(msg, sig))
// Mutate the signature, just one bit.
sigEd := sig.Unwrap().(SignatureEd25519)
sigEd[7] ^= byte(0x01)
sig = sigEd.Wrap()
assert.False(t, pubKey.VerifyBytes(msg, sig))
}
func TestSignAndValidateSecp256k1(t *testing.T) {
privKey := GenPrivKeySecp256k1()
pubKey := privKey.PubKey()
msg := CRandBytes(128)
sig := privKey.Sign(msg)
assert.True(t, pubKey.VerifyBytes(msg, sig))
// Mutate the signature, just one bit.
sigEd := sig.Unwrap().(SignatureSecp256k1)
sigEd[3] ^= byte(0x01)
sig = sigEd.Wrap()
assert.False(t, pubKey.VerifyBytes(msg, sig))
}
func TestSignatureEncodings(t *testing.T) {
cases := []struct {
privKey PrivKey
sigSize int
sigType byte
sigName string
}{
{
privKey: GenPrivKeyEd25519().Wrap(),
sigSize: ed25519.SignatureSize,
sigType: TypeEd25519,
sigName: NameEd25519,
},
{
privKey: GenPrivKeySecp256k1().Wrap(),
sigSize: 0, // unknown
sigType: TypeSecp256k1,
sigName: NameSecp256k1,
},
}
for _, tc := range cases {
// note we embed them from the beginning....
pubKey := tc.privKey.PubKey()
msg := CRandBytes(128)
sig := tc.privKey.Sign(msg)
// store as wire
bin, err := data.ToWire(sig)
require.Nil(t, err, "%+v", err)
if tc.sigSize != 0 {
assert.Equal(t, tc.sigSize+1, len(bin))
}
assert.Equal(t, tc.sigType, bin[0])
// and back
sig2 := Signature{}
err = data.FromWire(bin, &sig2)
require.Nil(t, err, "%+v", err)
assert.EqualValues(t, sig, sig2)
assert.True(t, pubKey.VerifyBytes(msg, sig2))
// store as json
js, err := data.ToJSON(sig)
require.Nil(t, err, "%+v", err)
assert.True(t, strings.Contains(string(js), tc.sigName))
// and back
sig3 := Signature{}
err = data.FromJSON(js, &sig3)
require.Nil(t, err, "%+v", err)
assert.EqualValues(t, sig, sig3)
assert.True(t, pubKey.VerifyBytes(msg, sig3))
// and make sure we can textify it
text, err := data.ToText(sig)
require.Nil(t, err, "%+v", err)
assert.True(t, strings.HasPrefix(text, tc.sigName))
}
}
func TestWrapping(t *testing.T) {
assert := assert.New(t)
// construct some basic constructs
msg := CRandBytes(128)
priv := GenPrivKeyEd25519()
pub := priv.PubKey()
sig := priv.Sign(msg)
// do some wrapping
pubs := []PubKey{
PubKey{nil},
pub.Wrap(),
pub.Wrap().Wrap().Wrap(),
PubKey{PubKey{PubKey{pub}}}.Wrap(),
}
for _, p := range pubs {
_, ok := p.PubKeyInner.(PubKey)
assert.False(ok)
}
sigs := []Signature{
Signature{nil},
sig.Wrap(),
sig.Wrap().Wrap().Wrap(),
Signature{Signature{Signature{sig}}}.Wrap(),
}
for _, s := range sigs {
_, ok := s.SignatureInner.(Signature)
assert.False(ok)
}
}
+51
View File
@@ -0,0 +1,51 @@
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
}
+42
View File
@@ -0,0 +1,42 @@
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)
}