mirror of
https://github.com/tendermint/tendermint.git
synced 2026-01-09 06:33:16 +00:00
go build compiles
This commit is contained in:
113
keys/keybase.go
113
keys/keybase.go
@@ -1,7 +1,7 @@
|
||||
package keys
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
@@ -43,10 +43,7 @@ func (kb dbKeybase) Create(name, passphrase, algo string) (Info, string, error)
|
||||
return Info{}, "", err
|
||||
}
|
||||
|
||||
err = kb.es.Put(name, passphrase, key)
|
||||
if err != nil {
|
||||
return Info{}, "", err
|
||||
}
|
||||
public := kb.writeKey(key, name, passphrase)
|
||||
|
||||
// we append the type byte to the serialized secret to help with recovery
|
||||
// ie [secret] = [secret] + [type]
|
||||
@@ -55,7 +52,7 @@ func (kb dbKeybase) Create(name, passphrase, algo string) (Info, string, error)
|
||||
|
||||
seed, err := kb.codec.BytesToWords(secret)
|
||||
phrase := strings.Join(seed, " ")
|
||||
return info(name, key), phrase, err
|
||||
return public, phrase, err
|
||||
}
|
||||
|
||||
// Recover takes a seed phrase and tries to recover the private key.
|
||||
@@ -82,21 +79,31 @@ func (kb dbKeybase) Recover(name, passphrase, seedphrase string) (Info, error) {
|
||||
}
|
||||
|
||||
// d00d, it worked! create the bugger....
|
||||
err = kb.es.Put(name, passphrase, key)
|
||||
return info(name, key), err
|
||||
public := kb.writeKey(key, name, passphrase)
|
||||
return public, err
|
||||
}
|
||||
|
||||
// List loads the keys from the storage and enforces alphabetical order
|
||||
func (kb dbKeybase) List() ([]Info, error) {
|
||||
res, err := kb.es.List()
|
||||
sort.Slice(res, func(a, b int) bool { return res[a].Name < res[b].Name })
|
||||
return res, err
|
||||
var res []Info
|
||||
var more = true
|
||||
for iter := kb.db.Iterator(); more; more = iter.Next() {
|
||||
key := iter.Key()
|
||||
if isPub(key) {
|
||||
info, err := readInfo(iter.Value())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
res = append(res, info)
|
||||
}
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// Get returns the public information about one key
|
||||
func (kb dbKeybase) Get(name string) (Info, error) {
|
||||
_, info, err := kb.es.store.Get(name)
|
||||
return info, err
|
||||
bs := kb.db.Get(pubName(name))
|
||||
return readInfo(bs)
|
||||
}
|
||||
|
||||
// Sign will modify the Signable in order to attach a valid signature with
|
||||
@@ -105,10 +112,12 @@ func (kb dbKeybase) Get(name string) (Info, error) {
|
||||
// If no key for this name, or the passphrase doesn't match, returns an error
|
||||
func (kb dbKeybase) Sign(name, passphrase string, msg []byte) (sig crypto.Signature, pk crypto.PubKey, err error) {
|
||||
var key crypto.PrivKey
|
||||
key, _, err = kb.es.Get(name, passphrase)
|
||||
bs := kb.db.Get(privName(name))
|
||||
key, err = unarmorDecryptPrivKey(string(bs), passphrase)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
sig = key.Sign(msg)
|
||||
pk = key.PubKey()
|
||||
return
|
||||
@@ -121,36 +130,49 @@ func (kb dbKeybase) Sign(name, passphrase string, msg []byte) (sig crypto.Signat
|
||||
// This is designed to copy from one device to another, or provide backups
|
||||
// during version updates.
|
||||
func (kb dbKeybase) Export(name, oldpass, transferpass string) ([]byte, error) {
|
||||
key, _, err := kb.es.Get(name, oldpass)
|
||||
bs := kb.db.Get(privName(name))
|
||||
key, err := unarmorDecryptPrivKey(string(bs), oldpass)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res, err := kb.es.coder.Encrypt(key, transferpass)
|
||||
return res, err
|
||||
if transferpass == "" {
|
||||
return key.Bytes(), nil
|
||||
}
|
||||
res := encryptArmorPrivKey(key, transferpass)
|
||||
return []byte(res), nil
|
||||
}
|
||||
|
||||
// Import accepts bytes generated by Export along with the same transferpass
|
||||
// If they are valid, it stores the password under the given name with the
|
||||
// new passphrase.
|
||||
func (kb dbKeybase) Import(name, newpass, transferpass string, data []byte) error {
|
||||
key, err := kb.es.coder.Decrypt(data, transferpass)
|
||||
func (kb dbKeybase) Import(name, newpass, transferpass string, data []byte) (err error) {
|
||||
var key crypto.PrivKey
|
||||
if transferpass == "" {
|
||||
key, err = crypto.PrivKeyFromBytes(data)
|
||||
} else {
|
||||
key, err = unarmorDecryptPrivKey(string(data), transferpass)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return kb.es.Put(name, newpass, key)
|
||||
kb.writeKey(key, name, newpass)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Delete removes key forever, but we must present the
|
||||
// proper passphrase before deleting it (for security)
|
||||
func (kb dbKeybase) Delete(name, passphrase string) error {
|
||||
// verify we have the proper password before deleting
|
||||
_, _, err := kb.es.Get(name, passphrase)
|
||||
bs := kb.db.Get(privName(name))
|
||||
_, err := unarmorDecryptPrivKey(string(bs), passphrase)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return kb.es.Delete(name)
|
||||
kb.db.DeleteSync(pubName(name))
|
||||
kb.db.DeleteSync(privName(name))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Update changes the passphrase with which a already stored key is encoded.
|
||||
@@ -158,15 +180,30 @@ func (kb dbKeybase) Delete(name, passphrase string) error {
|
||||
// oldpass must be the current passphrase used for encoding, newpass will be
|
||||
// the only valid passphrase from this time forward
|
||||
func (kb dbKeybase) Update(name, oldpass, newpass string) error {
|
||||
key, _, err := kb.es.Get(name, oldpass)
|
||||
bs := kb.db.Get(privName(name))
|
||||
key, err := unarmorDecryptPrivKey(string(bs), oldpass)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// we must delete first, as Putting over an existing name returns an error
|
||||
kb.Delete(name, oldpass)
|
||||
kb.db.DeleteSync(pubName(name))
|
||||
kb.db.DeleteSync(privName(name))
|
||||
kb.writeKey(key, name, newpass)
|
||||
return nil
|
||||
}
|
||||
|
||||
return kb.es.Put(name, newpass, key)
|
||||
func (kb dbKeybase) writeKey(priv crypto.PrivKey, name, passphrase string) Info {
|
||||
// generate the public bytes
|
||||
public := info(name, priv)
|
||||
// generate the encrypted privkey
|
||||
private := encryptArmorPrivKey(priv, passphrase)
|
||||
|
||||
// write them both
|
||||
kb.db.SetSync(pubName(name), public.bytes())
|
||||
kb.db.SetSync(privName(name), []byte(private))
|
||||
|
||||
return public
|
||||
}
|
||||
|
||||
func generate(algo string, secret []byte) (crypto.PrivKey, error) {
|
||||
@@ -197,24 +234,14 @@ func generateByType(typ byte, secret []byte) (crypto.PrivKey, error) {
|
||||
}
|
||||
}
|
||||
|
||||
func encrypt(key crypto.PrivKey, pass string) ([]byte, error) {
|
||||
if pass == "" {
|
||||
return key.Bytes(), nil
|
||||
}
|
||||
s := secret(pass)
|
||||
cipher := crypto.EncryptSymmetric(key.Bytes(), s)
|
||||
return cipher, nil
|
||||
func pubName(name string) []byte {
|
||||
return []byte(fmt.Sprintf("%s.pub", name))
|
||||
}
|
||||
|
||||
func decrypt(data []byte, pass string) (key crypto.PrivKey, err error) {
|
||||
private := data
|
||||
if pass != "" {
|
||||
s := secret(pass)
|
||||
private, err = crypto.DecryptSymmetric(data, s)
|
||||
if err != nil {
|
||||
return crypto.PrivKey{}, errors.Wrap(err, "Invalid Passphrase")
|
||||
}
|
||||
}
|
||||
key, err = crypto.PrivKeyFromBytes(private)
|
||||
return key, errors.Wrap(err, "Invalid Passphrase")
|
||||
func privName(name string) []byte {
|
||||
return []byte(fmt.Sprintf("%s.priv", name))
|
||||
}
|
||||
|
||||
func isPub(name []byte) bool {
|
||||
return strings.HasSuffix(string(name), ".pub")
|
||||
}
|
||||
|
||||
73
keys/mintkey.go
Normal file
73
keys/mintkey.go
Normal file
@@ -0,0 +1,73 @@
|
||||
package keys
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
|
||||
cmn "github.com/tendermint/tmlibs/common"
|
||||
|
||||
"github.com/tendermint/go-crypto"
|
||||
"github.com/tendermint/go-crypto/bcrypt"
|
||||
)
|
||||
|
||||
const (
|
||||
blockTypePrivKey = "TENDERMINT PRIVATE KEY"
|
||||
)
|
||||
|
||||
func encryptArmorPrivKey(privKey crypto.PrivKey, passphrase string) string {
|
||||
saltBytes, encBytes := encryptPrivKey(privKey, passphrase)
|
||||
header := map[string]string{
|
||||
"kdf": "bcrypt",
|
||||
"salt": fmt.Sprintf("%X", saltBytes),
|
||||
}
|
||||
armorStr := crypto.EncodeArmor(blockTypePrivKey, header, encBytes)
|
||||
return armorStr
|
||||
}
|
||||
|
||||
func unarmorDecryptPrivKey(armorStr string, passphrase string) (crypto.PrivKey, error) {
|
||||
var privKey crypto.PrivKey
|
||||
blockType, header, encBytes, err := crypto.DecodeArmor(armorStr)
|
||||
if err != nil {
|
||||
return privKey, err
|
||||
}
|
||||
if blockType != blockTypePrivKey {
|
||||
return privKey, fmt.Errorf("Unrecognized armor type: %v", blockType)
|
||||
}
|
||||
if header["kdf"] != "bcrypt" {
|
||||
return privKey, fmt.Errorf("Unrecognized KDF type: %v", header["KDF"])
|
||||
}
|
||||
if header["salt"] == "" {
|
||||
return privKey, fmt.Errorf("Missing salt bytes")
|
||||
}
|
||||
saltBytes, err := hex.DecodeString(header["salt"])
|
||||
if err != nil {
|
||||
return privKey, fmt.Errorf("Error decoding salt: %v", err.Error())
|
||||
}
|
||||
privKey, err = decryptPrivKey(saltBytes, encBytes, passphrase)
|
||||
return privKey, err
|
||||
}
|
||||
|
||||
func encryptPrivKey(privKey crypto.PrivKey, passphrase string) (saltBytes []byte, encBytes []byte) {
|
||||
saltBytes = crypto.CRandBytes(16)
|
||||
key, err := bcrypt.GenerateFromPassword(saltBytes, []byte(passphrase), 12) // TODO parameterize. 12 is good today (2016)
|
||||
if err != nil {
|
||||
cmn.Exit("Error generating bcrypt key from passphrase: " + err.Error())
|
||||
}
|
||||
key = crypto.Sha256(key) // Get 32 bytes
|
||||
privKeyBytes := privKey.Bytes()
|
||||
return saltBytes, crypto.EncryptSymmetric(privKeyBytes, key)
|
||||
}
|
||||
|
||||
func decryptPrivKey(saltBytes []byte, encBytes []byte, passphrase string) (privKey crypto.PrivKey, err error) {
|
||||
key, err := bcrypt.GenerateFromPassword(saltBytes, []byte(passphrase), 12) // TODO parameterize. 12 is good today (2016)
|
||||
if err != nil {
|
||||
cmn.Exit("Error generating bcrypt key from passphrase: " + err.Error())
|
||||
}
|
||||
key = crypto.Sha256(key) // Get 32 bytes
|
||||
privKeyBytes, err := crypto.DecryptSymmetric(encBytes, key)
|
||||
if err != nil {
|
||||
return privKey, err
|
||||
}
|
||||
privKey, err = crypto.PrivKeyFromBytes(privKeyBytes)
|
||||
return privKey, err
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
package keys
|
||||
|
||||
import (
|
||||
wire "github.com/tendermint/go-wire"
|
||||
|
||||
crypto "github.com/tendermint/go-crypto"
|
||||
)
|
||||
|
||||
@@ -10,6 +12,15 @@ type Info struct {
|
||||
PubKey crypto.PubKey `json:"pubkey"`
|
||||
}
|
||||
|
||||
func (i Info) bytes() []byte {
|
||||
return wire.BinaryBytes(i)
|
||||
}
|
||||
|
||||
func readInfo(bs []byte) (info Info, err error) {
|
||||
err = wire.ReadBinaryBytes(bs, &info)
|
||||
return
|
||||
}
|
||||
|
||||
func info(name string, privKey crypto.PrivKey) Info {
|
||||
return Info{
|
||||
Name: name,
|
||||
|
||||
Reference in New Issue
Block a user