Browse Source

go build compiles

pull/1782/head
Ethan Frey 7 years ago
parent
commit
4173d1031e
3 changed files with 156 additions and 45 deletions
  1. +72
    -45
      keys/keybase.go
  2. +73
    -0
      keys/mintkey.go
  3. +11
    -0
      keys/types.go

+ 72
- 45
keys/keybase.go View File

@ -1,7 +1,7 @@
package keys package keys
import ( import (
"sort"
"fmt"
"strings" "strings"
"github.com/pkg/errors" "github.com/pkg/errors"
@ -43,10 +43,7 @@ func (kb dbKeybase) Create(name, passphrase, algo string) (Info, string, error)
return Info{}, "", err 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 // we append the type byte to the serialized secret to help with recovery
// ie [secret] = [secret] + [type] // 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) seed, err := kb.codec.BytesToWords(secret)
phrase := strings.Join(seed, " ") 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. // 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.... // 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 // List loads the keys from the storage and enforces alphabetical order
func (kb dbKeybase) List() ([]Info, error) { 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 // Get returns the public information about one key
func (kb dbKeybase) Get(name string) (Info, error) { 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 // 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 // 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) { func (kb dbKeybase) Sign(name, passphrase string, msg []byte) (sig crypto.Signature, pk crypto.PubKey, err error) {
var key crypto.PrivKey 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 { if err != nil {
return return
} }
sig = key.Sign(msg) sig = key.Sign(msg)
pk = key.PubKey() pk = key.PubKey()
return 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 // This is designed to copy from one device to another, or provide backups
// during version updates. // during version updates.
func (kb dbKeybase) Export(name, oldpass, transferpass string) ([]byte, error) { 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 { if err != nil {
return nil, err 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 // 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 // If they are valid, it stores the password under the given name with the
// new passphrase. // 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 { if err != nil {
return err 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 // Delete removes key forever, but we must present the
// proper passphrase before deleting it (for security) // proper passphrase before deleting it (for security)
func (kb dbKeybase) Delete(name, passphrase string) error { func (kb dbKeybase) Delete(name, passphrase string) error {
// verify we have the proper password before deleting // 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 { if err != nil {
return err 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. // 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 // oldpass must be the current passphrase used for encoding, newpass will be
// the only valid passphrase from this time forward // the only valid passphrase from this time forward
func (kb dbKeybase) Update(name, oldpass, newpass string) error { 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 { if err != nil {
return err return err
} }
// we must delete first, as Putting over an existing name returns an error // 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) { 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 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 pubName(name string) []byte {
return []byte(fmt.Sprintf("%s.pub", name))
}
func privName(name string) []byte {
return []byte(fmt.Sprintf("%s.priv", name))
}
func isPub(name []byte) bool {
return strings.HasSuffix(string(name), ".pub")
} }

+ 73
- 0
keys/mintkey.go View 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
}

+ 11
- 0
keys/types.go View File

@ -1,6 +1,8 @@
package keys package keys
import ( import (
wire "github.com/tendermint/go-wire"
crypto "github.com/tendermint/go-crypto" crypto "github.com/tendermint/go-crypto"
) )
@ -10,6 +12,15 @@ type Info struct {
PubKey crypto.PubKey `json:"pubkey"` 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 { func info(name string, privKey crypto.PrivKey) Info {
return Info{ return Info{
Name: name, Name: name,


Loading…
Cancel
Save