cryptostore

package
v1.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 5, 2019 License: GPL-3.0, Apache-2.0 Imports: 5 Imported by: 0

Documentation

Overview

package cryptostore maintains everything needed for doing public-key signing and key management in software, based on the go-crypto library from tendermint.

It is flexible, and allows the user to provide a key generation algorithm (currently Ed25519 or Secp256k1), an encoder to passphrase-encrypt our keys when storing them (currently SecretBox from NaCl), and a method to persist the keys (currently FileStorage like ssh, or MemStorage for tests). It should be relatively simple to write your own implementation of these interfaces to match your specific security requirements.

Note that the private keys are never exposed outside the package, and the interface of Manager could be implemented by an HSM in the future for enhanced security. It would require a completely different implementation however.

This Manager aims to implement Signer and KeyManager interfaces, along with some extensions to allow importing/exporting keys and updating the passphrase.

Encoder and Generator implementations are currently in this package, keys.Storage implementations exist as subpackages of keys/storage

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Encoder

type Encoder interface {
	Encrypt(key crypto.PrivKey, pass string) ([]byte, error)
	Decrypt(data []byte, pass string) (crypto.PrivKey, error)
}

Encoder is used to encrypt any key with a passphrase for storage.

This should use a well-designed symetric encryption algorithm

var (
	// SecretBox uses the algorithm from NaCL to store secrets securely
	SecretBox Encoder = secretbox{}
	// Noop doesn't do any encryption, should only be used in test code
	Noop Encoder = noop{}
)

type GenFunc

type GenFunc func(secret []byte) (crypto.PrivKey, error)

GenFunc is a helper to transform a function into a Generator

func (GenFunc) Generate

func (f GenFunc) Generate(secret []byte) (crypto.PrivKey, error)

type Generator

type Generator interface {
	Generate(secret []byte) (crypto.PrivKey, error)
}

Generator determines the type of private key the keystore creates

var (
	// GenEd25519 produces Ed25519 private keys
	GenEd25519 Generator = GenFunc(genEd25519)
	// GenSecp256k1 produces Secp256k1 private keys
	GenSecp256k1 Generator = GenFunc(genSecp256)
	// GenLedgerEd25519 used Ed25519 keys stored on nano ledger s with cosmos app
	GenLedgerEd25519 Generator = GenFunc(genLedgerEd25519)
)

type Manager

type Manager struct {
	// contains filtered or unexported fields
}

Manager combines encyption and storage implementation to provide a full-featured key manager

func New

func New(coder Encoder, store keys.Storage, codec keys.Codec) Manager
Example
package main

import (
	"bytes"
	"fmt"

	crypto "github.com/tendermint/go-crypto"
	"github.com/tendermint/go-crypto/keys"
	"github.com/tendermint/go-crypto/keys/cryptostore"
	"github.com/tendermint/go-crypto/keys/storage/memstorage"
)

func main() {
	// Select the encryption and storage for your cryptostore
	cstore := cryptostore.New(
		cryptostore.SecretBox,
		// Note: use filestorage.New(dir) for real data
		memstorage.New(),
		keys.MustLoadCodec("english"),
	)
	ed := crypto.NameEd25519
	sec := crypto.NameSecp256k1

	// Add keys and see they return in alphabetical order
	bob, _, err := cstore.Create("Bob", "friend", ed)
	if err != nil {
		// this should never happen
		fmt.Println(err)
	} else {
		// return info here just like in List
		fmt.Println(bob.Name)
	}
	cstore.Create("Alice", "secret", sec)
	cstore.Create("Carl", "mitm", ed)
	info, _ := cstore.List()
	for _, i := range info {
		fmt.Println(i.Name)
	}

	// We need to use passphrase to generate a signature
	tx := keys.NewMockSignable([]byte("deadbeef"))
	err = cstore.Sign("Bob", "friend", tx)
	if err != nil {
		fmt.Println("don't accept real passphrase")
	}

	// and we can validate the signature with publically available info
	binfo, _ := cstore.Get("Bob")
	if !binfo.PubKey.Equals(bob.PubKey) {
		fmt.Println("Get and Create return different keys")
	}

	sigs, err := tx.Signers()
	if err != nil {
		fmt.Println("badly signed")
	} else if bytes.Equal(sigs[0].Bytes(), binfo.PubKey.Bytes()) {
		fmt.Println("signed by Bob")
	} else {
		fmt.Println("signed by someone else")
	}

}
Output:

Bob
Alice
Bob
Carl
signed by Bob

func (Manager) Create

func (s Manager) Create(name, passphrase, algo string) (keys.Info, string, error)

Create adds a new key to the storage engine, returning error if another key already stored under this name

algo must be a supported go-crypto algorithm: ed25519, secp256k1

func (Manager) Delete

func (s Manager) Delete(name, passphrase string) error

Delete removes key forever, but we must present the proper passphrase before deleting it (for security)

func (Manager) Export

func (s Manager) Export(name, oldpass, transferpass string) ([]byte, error)

Export decodes the private key with the current password, encodes it with a secure one-time password and generates a sequence that can be Imported by another Manager

This is designed to copy from one device to another, or provide backups during version updates.

func (Manager) Get

func (s Manager) Get(name string) (keys.Info, error)

Get returns the public information about one key

func (Manager) Import

func (s Manager) Import(name, newpass, transferpass string, data []byte) error

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 (Manager) List

func (s Manager) List() (keys.Infos, error)

List loads the keys from the storage and enforces alphabetical order

func (Manager) Recover

func (s Manager) Recover(name, passphrase, seedphrase string) (keys.Info, error)

Recover takes a seed phrase and tries to recover the private key.

If the seed phrase is valid, it will create the private key and store it under name, protected by passphrase.

Result similar to New(), except it doesn't return the seed again...

func (Manager) Sign

func (s Manager) Sign(name, passphrase string, tx keys.Signable) error

Sign will modify the Signable in order to attach a valid signature with this public key

If no key for this name, or the passphrase doesn't match, returns an error

func (Manager) Update

func (s Manager) Update(name, oldpass, newpass string) error

Update changes the passphrase with which a already stored key is encoded.

oldpass must be the current passphrase used for encoding, newpass will be the only valid passphrase from this time forward

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL