accounts, core, internal, node: Add support for smartcard wallets

This commit is contained in:
Nick Johnson
2018-01-07 18:38:11 +00:00
committed by Guillaume Ballet
parent 3996bc1ad9
commit f7027dd68c
21 changed files with 5364 additions and 0 deletions

21
vendor/github.com/tyler-smith/go-bip39/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2014 Tyler Smith
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

38
vendor/github.com/tyler-smith/go-bip39/README.md generated vendored Normal file
View File

@@ -0,0 +1,38 @@
# go-bip39
A golang implementation of the BIP0039 spec for mnemonic seeds
## Credits
English wordlist and test vectors are from the standard Python BIP0039 implementation
from the Trezor guys: [https://github.com/trezor/python-mnemonic](https://github.com/trezor/python-mnemonic)
## Example
```go
package main
import (
"github.com/tyler-smith/go-bip39"
"github.com/tyler-smith/go-bip32"
"fmt"
)
func main(){
// Generate a mnemonic for memorization or user-friendly seeds
entropy, _ := bip39.NewEntropy(256)
mnemonic, _ := bip39.NewMnemonic(entropy)
// Generate a Bip32 HD wallet for the mnemonic and a user supplied password
seed := bip39.NewSeed(mnemonic, "Secret Passphrase")
masterKey, _ := bip32.NewMasterKey(seed)
publicKey := masterKey.PublicKey()
// Display mnemonic and keys
fmt.Println("Mnemonic: ", mnemonic)
fmt.Println("Master private key: ", masterKey)
fmt.Println("Master public key: ", publicKey)
}
```

249
vendor/github.com/tyler-smith/go-bip39/bip39.go generated vendored Normal file
View File

@@ -0,0 +1,249 @@
package bip39
import (
"crypto/rand"
"crypto/sha256"
"crypto/sha512"
"encoding/binary"
"errors"
"fmt"
"math/big"
"strings"
"golang.org/x/crypto/pbkdf2"
)
// Some bitwise operands for working with big.Ints
var (
Last11BitsMask = big.NewInt(2047)
RightShift11BitsDivider = big.NewInt(2048)
BigOne = big.NewInt(1)
BigTwo = big.NewInt(2)
)
// NewEntropy will create random entropy bytes
// so long as the requested size bitSize is an appropriate size.
func NewEntropy(bitSize int) ([]byte, error) {
err := validateEntropyBitSize(bitSize)
if err != nil {
return nil, err
}
entropy := make([]byte, bitSize/8)
_, err = rand.Read(entropy)
return entropy, err
}
// NewMnemonic will return a string consisting of the mnemonic words for
// the given entropy.
// If the provide entropy is invalid, an error will be returned.
func NewMnemonic(entropy []byte) (string, error) {
// Compute some lengths for convenience
entropyBitLength := len(entropy) * 8
checksumBitLength := entropyBitLength / 32
sentenceLength := (entropyBitLength + checksumBitLength) / 11
err := validateEntropyBitSize(entropyBitLength)
if err != nil {
return "", err
}
// Add checksum to entropy
entropy = addChecksum(entropy)
// Break entropy up into sentenceLength chunks of 11 bits
// For each word AND mask the rightmost 11 bits and find the word at that index
// Then bitshift entropy 11 bits right and repeat
// Add to the last empty slot so we can work with LSBs instead of MSB
// Entropy as an int so we can bitmask without worrying about bytes slices
entropyInt := new(big.Int).SetBytes(entropy)
// Slice to hold words in
words := make([]string, sentenceLength)
// Throw away big int for AND masking
word := big.NewInt(0)
for i := sentenceLength - 1; i >= 0; i-- {
// Get 11 right most bits and bitshift 11 to the right for next time
word.And(entropyInt, Last11BitsMask)
entropyInt.Div(entropyInt, RightShift11BitsDivider)
// Get the bytes representing the 11 bits as a 2 byte slice
wordBytes := padByteSlice(word.Bytes(), 2)
// Convert bytes to an index and add that word to the list
words[i] = WordList[binary.BigEndian.Uint16(wordBytes)]
}
return strings.Join(words, " "), nil
}
// MnemonicToByteArray takes a mnemonic string and turns it into a byte array
// suitable for creating another mnemonic.
// An error is returned if the mnemonic is invalid.
// FIXME
// This does not work for all values in
// the test vectors. Namely
// Vectors 0, 4, and 8.
// This is not really important because BIP39 doesnt really define a conversion
// from string to bytes.
func MnemonicToByteArray(mnemonic string) ([]byte, error) {
if IsMnemonicValid(mnemonic) == false {
return nil, fmt.Errorf("Invalid mnemonic")
}
mnemonicSlice := strings.Split(mnemonic, " ")
bitSize := len(mnemonicSlice) * 11
err := validateEntropyWithChecksumBitSize(bitSize)
if err != nil {
return nil, err
}
checksumSize := bitSize % 32
b := big.NewInt(0)
modulo := big.NewInt(2048)
for _, v := range mnemonicSlice {
index, found := ReverseWordMap[v]
if found == false {
return nil, fmt.Errorf("Word `%v` not found in reverse map", v)
}
add := big.NewInt(int64(index))
b = b.Mul(b, modulo)
b = b.Add(b, add)
}
hex := b.Bytes()
checksumModulo := big.NewInt(0).Exp(big.NewInt(2), big.NewInt(int64(checksumSize)), nil)
entropy, _ := big.NewInt(0).DivMod(b, checksumModulo, big.NewInt(0))
entropyHex := entropy.Bytes()
byteSize := bitSize/8 + 1
if len(hex) != byteSize {
tmp := make([]byte, byteSize)
diff := byteSize - len(hex)
for i := 0; i < len(hex); i++ {
tmp[i+diff] = hex[i]
}
hex = tmp
}
validationHex := addChecksum(entropyHex)
if len(validationHex) != byteSize {
tmp2 := make([]byte, byteSize)
diff2 := byteSize - len(validationHex)
for i := 0; i < len(validationHex); i++ {
tmp2[i+diff2] = validationHex[i]
}
validationHex = tmp2
}
if len(hex) != len(validationHex) {
panic("[]byte len mismatch - it shouldn't happen")
}
for i := range validationHex {
if hex[i] != validationHex[i] {
return nil, fmt.Errorf("Invalid byte at position %v", i)
}
}
return hex, nil
}
// NewSeedWithErrorChecking creates a hashed seed output given the mnemonic string and a password.
// An error is returned if the mnemonic is not convertible to a byte array.
func NewSeedWithErrorChecking(mnemonic string, password string) ([]byte, error) {
_, err := MnemonicToByteArray(mnemonic)
if err != nil {
return nil, err
}
return NewSeed(mnemonic, password), nil
}
// NewSeed creates a hashed seed output given a provided string and password.
// No checking is performed to validate that the string provided is a valid mnemonic.
func NewSeed(mnemonic string, password string) []byte {
return pbkdf2.Key([]byte(mnemonic), []byte("mnemonic"+password), 2048, 64, sha512.New)
}
// Appends to data the first (len(data) / 32)bits of the result of sha256(data)
// Currently only supports data up to 32 bytes
func addChecksum(data []byte) []byte {
// Get first byte of sha256
hasher := sha256.New()
hasher.Write(data)
hash := hasher.Sum(nil)
firstChecksumByte := hash[0]
// len() is in bytes so we divide by 4
checksumBitLength := uint(len(data) / 4)
// For each bit of check sum we want we shift the data one the left
// and then set the (new) right most bit equal to checksum bit at that index
// staring from the left
dataBigInt := new(big.Int).SetBytes(data)
for i := uint(0); i < checksumBitLength; i++ {
// Bitshift 1 left
dataBigInt.Mul(dataBigInt, BigTwo)
// Set rightmost bit if leftmost checksum bit is set
if uint8(firstChecksumByte&(1<<(7-i))) > 0 {
dataBigInt.Or(dataBigInt, BigOne)
}
}
return dataBigInt.Bytes()
}
func padByteSlice(slice []byte, length int) []byte {
newSlice := make([]byte, length-len(slice))
return append(newSlice, slice...)
}
func validateEntropyBitSize(bitSize int) error {
if (bitSize%32) != 0 || bitSize < 128 || bitSize > 256 {
return errors.New("Entropy length must be [128, 256] and a multiple of 32")
}
return nil
}
func validateEntropyWithChecksumBitSize(bitSize int) error {
if (bitSize != 128+4) && (bitSize != 160+5) && (bitSize != 192+6) && (bitSize != 224+7) && (bitSize != 256+8) {
return fmt.Errorf("Wrong entropy + checksum size - expected %v, got %v", int((bitSize-bitSize%32)+(bitSize-bitSize%32)/32), bitSize)
}
return nil
}
// IsMnemonicValid attempts to verify that the provided mnemonic is valid.
// Validity is determined by both the number of words being appropriate,
// and that all the words in the mnemonic are present in the word list.
func IsMnemonicValid(mnemonic string) bool {
// Create a list of all the words in the mnemonic sentence
words := strings.Fields(mnemonic)
//Get num of words
numOfWords := len(words)
// The number of words should be 12, 15, 18, 21 or 24
if numOfWords%3 != 0 || numOfWords < 12 || numOfWords > 24 {
return false
}
// Check if all words belong in the wordlist
for i := 0; i < numOfWords; i++ {
if !contains(WordList, words[i]) {
return false
}
}
return true
}
func contains(s []string, e string) bool {
for _, a := range s {
if a == e {
return true
}
}
return false
}

15
vendor/github.com/tyler-smith/go-bip39/coverage.txt generated vendored Normal file
View File

@@ -0,0 +1,15 @@
github.com/CrowBits/go-bip39/bip39.go addChecksum 100.00% (11/11)
github.com/CrowBits/go-bip39/bip39.go IsMnemonicValid 100.00% (8/8)
github.com/CrowBits/go-bip39/bip39.go NewEntropy 100.00% (6/6)
github.com/CrowBits/go-bip39/bip39.go contains 100.00% (4/4)
github.com/CrowBits/go-bip39/bip39.go NewSeedWithErrorChecking 100.00% (4/4)
github.com/CrowBits/go-bip39/bip39.go validateEntropyBitSize 100.00% (3/3)
github.com/CrowBits/go-bip39/bip39.go validateEntropyWithChecksumBitSize 100.00% (3/3)
github.com/CrowBits/go-bip39/bip39.go padByteSlice 100.00% (2/2)
github.com/CrowBits/go-bip39/wordlist.go init 100.00% (2/2)
github.com/CrowBits/go-bip39/bip39.go NewSeed 100.00% (1/1)
github.com/CrowBits/go-bip39/bip39.go NewMnemonic 93.75% (15/16)
github.com/CrowBits/go-bip39/bip39.go MnemonicToByteArray 90.24% (37/41)
github.com/CrowBits/go-bip39 ---------------------------------- 95.05% (96/101)

2067
vendor/github.com/tyler-smith/go-bip39/wordlist.go generated vendored Normal file

File diff suppressed because it is too large Load Diff