Skip to content

Commit

Permalink
Merge pull request #23 from Planxnx/fix/invalid-seed-pharse
Browse files Browse the repository at this point in the history
Fix invalid seed phrases
  • Loading branch information
Planxnx authored Apr 21, 2023
2 parents ac48255 + 5773b73 commit 77f8f08
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 28 deletions.
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,6 @@ Total Wallet Resolved: 50000 w

- [conseweb/coinutil](https://github.com/conseweb/coinutil) - for BIP39 implementation in Go
- [tyler-smith/go-bip39](https://github.com/tyler-smith/go-bip39) - for BIP39 implementation in Go
- [holiman/uint256](https://github.com/holiman/uint256) - for high performance fixed size unsigned 256-bit math library

## Contributing ![eth](https://user-images.githubusercontent.com/37617738/120125730-1d1bd680-c1e4-11eb-83ad-45664245cae9.png)

Expand Down
37 changes: 15 additions & 22 deletions bip39/bip39.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,20 @@ import (
"crypto/rand"
"crypto/sha256"
"crypto/sha512"
"math/big"
"strings"

"github.com/holiman/uint256"
"github.com/pkg/errors"
"golang.org/x/crypto/pbkdf2"
)

var (
one = uint256.NewInt(1)
two = uint256.NewInt(2)
one = big.NewInt(1)
two = big.NewInt(2)

bitsChunkSize = 11
shift11BitsMask = new(uint256.Int).Lsh(one, uint(bitsChunkSize)) // 2^11 = 2048
last11BitsMask = new(uint256.Int).Sub(shift11BitsMask, one) // 2^11 - 1 = 2047
shift11BitsMask = new(big.Int).Lsh(one, uint(bitsChunkSize)) // 2^11 = 2048
last11BitsMask = new(big.Int).Sub(shift11BitsMask, one) // 2^11 - 1 = 2047
)

// NewEntropy will create random entropy bytes
Expand Down Expand Up @@ -63,31 +63,26 @@ func NewMnemonic(entropy []byte) (string, error) {
// Entropy as an int so we can bitmask without worrying about bytes slices.
entropyInt := addChecksum(entropy)

// Throw away uint256.Int for AND masking.
word := uint256.NewInt(0)
// Throw away big.Int for AND masking.
word := big.NewInt(0)

// Slice to hold words in.
words := make([]string, sentenceLength)

// 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.

var w strings.Builder
w.Grow(sentenceLength * bitsChunkSize)
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, shift11BitsMask)

// Convert bytes to an index and add that word to the list.
if i == sentenceLength-1 {
w.WriteString(Words[word.Uint64()])
} else {
w.WriteString(" ")
w.WriteString(Words[word.Uint64()])
}
words[i] = Words[word.Uint64()]
}

return w.String(), nil
return strings.Join(words, " "), nil
}

// NewSeed creates a hashed seed output given a provided string and password.
Expand All @@ -97,10 +92,10 @@ func NewSeed(mnemonic, password string) []byte {
}

// Appends to data the first (len(data) / 32)bits of the result of sha256(data)
// abd returns the result as a uint256.Int.
// abd returns the result as a big.Int.
//
// Currently only supports data up to 32 bytes.
func addChecksum(data []byte) *uint256.Int {
func addChecksum(data []byte) *big.Int {
// Get first byte of sha256
hash := computeChecksum(data)
firstChecksumByte := hash[0]
Expand All @@ -111,8 +106,7 @@ func addChecksum(data []byte) *uint256.Int {
// 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
dataInt := new(uint256.Int).SetBytes(data)

dataInt := new(big.Int).SetBytes(data)
for i := uint(0); i < checksumBitLength; i++ {
// Bitshift 1 left
dataInt.Mul(dataInt, two)
Expand All @@ -129,7 +123,6 @@ func addChecksum(data []byte) *uint256.Int {
func computeChecksum(data []byte) []byte {
hasher := sha256.New()
_, _ = hasher.Write(data) // This error is guaranteed to be nil

return hasher.Sum(nil)
}

Expand Down
56 changes: 56 additions & 0 deletions bip39/bip39_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"testing"

"github.com/stretchr/testify/assert"
"github.com/tyler-smith/go-bip39"
)

Expand Down Expand Up @@ -31,3 +32,58 @@ func BenchmarkBIP39(b *testing.B) {
}
}
}

func TestGenerateFromEntropy(t *testing.T) {
type TestSpec struct {
entropy []byte
expectedMnemonic string
}

testCases := map[string][]TestSpec{
"128bits": {
{
entropy: []byte{157, 167, 82, 14, 138, 57, 220, 233, 60, 83, 236, 19, 121, 207, 199, 151},
expectedMnemonic: "oval dentist lonely behave oven innocent vanish laugh beach solar vehicle connect",
},
{
entropy: []byte{103, 15, 41, 115, 192, 199, 222, 77, 33, 34, 50, 57, 174, 229, 13, 231},
expectedMnemonic: "grow junk friend light law charge loyal edge defy jaguar drop sort",
},
{
entropy: []byte{172, 237, 228, 119, 25, 39, 253, 133, 139, 151, 201, 62, 48, 247, 58, 15},
expectedMnemonic: "provide hundred build crane lemon security comic weird dilemma marble soldier butter",
},
{
entropy: []byte{41, 126, 238, 172, 119, 220, 20, 164, 174, 84, 12, 165, 14, 128, 206, 240},
expectedMnemonic: "city wash prison use scout false rich light pink inject crisp ticket",
},
{
entropy: []byte{21, 42, 240, 221, 4, 84, 149, 97, 139, 174, 9, 186, 150, 186, 144, 14},
expectedMnemonic: "benefit fiscal dance anger enable radio concert scorpion ritual remind piano bronze",
},
},
"256bits": {
{
entropy: []byte{6, 137, 161, 26, 237, 39, 33, 110, 228, 193, 105, 245, 181, 108, 133, 38, 168, 102, 174, 148, 240, 219, 81, 74, 194, 162, 228, 218, 16, 148, 57, 156},
expectedMnemonic: "alley escape effort surge improve resist narrow coffee volcano problem candy essence major firm fatigue bread eyebrow figure post situate patient energy toy menu",
},
{
entropy: []byte{24, 191, 8, 191, 188, 214, 228, 149, 31, 99, 124, 92, 243, 25, 195, 46, 56, 206, 78, 177, 177, 183, 231, 19, 100, 156, 57, 0, 124, 102, 156, 96},
expectedMnemonic: "board weapon copper keen hour enhance laugh hurdle friend occur ignore fragile mind chef short dad train open check improve amazing crew immense bonus",
},
},
}

for name, testSpecs := range testCases {
t.Run(name, func(t *testing.T) {
for _, testSpec := range testSpecs {
actualMnemonic, err := NewMnemonic(testSpec.entropy)
if err != nil {
t.Errorf("failed to generate mnemonic %+v", err)
}

assert.Equal(t, testSpec.expectedMnemonic, actualMnemonic)
}
})
}
}
10 changes: 8 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,19 @@ require (
github.com/btcsuite/btcd/btcutil v1.1.3
github.com/cheggaaa/pb/v3 v3.1.2
github.com/ethereum/go-ethereum v1.11.4
github.com/holiman/uint256 v1.2.2
github.com/pkg/errors v0.9.1
github.com/schollz/progressbar/v3 v3.13.0
github.com/tyler-smith/go-bip39 v1.1.0
gorm.io/driver/sqlite v1.4.4
gorm.io/gorm v1.24.6
)

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

require (
github.com/VividCortex/ewma v1.2.0 // indirect
github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect
Expand All @@ -29,7 +34,8 @@ require (
github.com/mattn/go-sqlite3 v1.14.16 // indirect
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect
github.com/rivo/uniseg v0.4.4 // indirect
golang.org/x/crypto v0.7.0 // indirect
github.com/stretchr/testify v1.8.2
golang.org/x/crypto v0.7.0
golang.org/x/sys v0.6.0 // indirect
golang.org/x/term v0.6.0 // indirect
)
11 changes: 8 additions & 3 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,6 @@ github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEW
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/holiman/uint256 v1.2.2 h1:TXKcSGc2WaxPD2+bmzAsVthL4+pEN0YwXcL5qED83vk=
github.com/holiman/uint256 v1.2.2/go.mod h1:SC8Ryt4n+UBbPbIBKaG9zbbDlp4jOru9xFZmPzLUTxw=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
Expand Down Expand Up @@ -129,9 +127,14 @@ github.com/schollz/progressbar/v3 v3.13.0 h1:9TeeWRcjW2qd05I8Kf9knPkW4vLM/hYoa6z
github.com/schollz/progressbar/v3 v3.13.0/go.mod h1:ZBYnSuLAX2LU8P8UiKN/KgF2DY58AJC8yfVYLPC8Ly4=
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY=
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc=
github.com/tklauser/go-sysconf v0.3.5 h1:uu3Xl4nkLzQfXNsWn15rPc/HQCJKObbt1dKJeWp3vU4=
Expand Down Expand Up @@ -180,6 +183,7 @@ google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miE
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
Expand All @@ -188,6 +192,7 @@ gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/driver/sqlite v1.4.4 h1:gIufGoR0dQzjkyqDyYSCvsYR6fba1Gw5YKDqKeChxFc=
gorm.io/driver/sqlite v1.4.4/go.mod h1:0Aq3iPO+v9ZKbcdiz8gLWRw5VOPcBOPUQJFLq5e2ecI=
gorm.io/gorm v1.24.0/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA=
Expand Down

0 comments on commit 77f8f08

Please sign in to comment.