accounts, core, internal, node: Add support for smartcard wallets
This commit is contained in:
committed by
Guillaume Ballet
parent
3996bc1ad9
commit
f7027dd68c
21
vendor/github.com/tyler-smith/go-bip39/LICENSE
generated
vendored
Normal file
21
vendor/github.com/tyler-smith/go-bip39/LICENSE
generated
vendored
Normal 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
38
vendor/github.com/tyler-smith/go-bip39/README.md
generated
vendored
Normal 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
249
vendor/github.com/tyler-smith/go-bip39/bip39.go
generated
vendored
Normal 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
15
vendor/github.com/tyler-smith/go-bip39/coverage.txt
generated
vendored
Normal 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
2067
vendor/github.com/tyler-smith/go-bip39/wordlist.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user