Skip to content

Commit

Permalink
Add keystore v4 (umbracle#153)
Browse files Browse the repository at this point in the history
* Add keystore v4

* Remove keystore fixtures
  • Loading branch information
ferranbt authored Feb 19, 2022
1 parent fa97940 commit 19d7ba3
Show file tree
Hide file tree
Showing 7 changed files with 333 additions and 102 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ require (
github.com/valyala/fastjson v1.4.1
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7 // indirect
golang.org/x/text v0.3.2
google.golang.org/appengine v1.6.5 // indirect
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
gotest.tools v2.2.0+incompatible // indirect
Expand Down
11 changes: 1 addition & 10 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -110,16 +110,6 @@ github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJy
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8=
github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U=
github.com/umbracle/fastrlp v0.0.0-20210128110402-41364ca56ca8 h1:lWWKP+Oi7FSORlB3Y8rLz1Q7OOxtD8vecmtYOSNkIpo=
github.com/umbracle/fastrlp v0.0.0-20210128110402-41364ca56ca8/go.mod h1:z0AyVhz/7VbuYSaCB+tFgypZKD1DJL76ATih6XqFlig=
github.com/umbracle/fastrlp v0.0.0-20211210202053-92c528b55dea h1:KkTT5DT0SPmtNlQLSAI9jj0l2kkhn55Tl+txokkiWxQ=
github.com/umbracle/fastrlp v0.0.0-20211210202053-92c528b55dea/go.mod h1:c8J0h9aULj2i3umrfyestM6jCq0LK0U6ly6bWy96nd4=
github.com/umbracle/fastrlp v0.0.0-20211228214822-d284b9a1ca89 h1:1HVAbF+D8wO8q7u+VMVZPysfZDdAdPdTDn5YECH2xrM=
github.com/umbracle/fastrlp v0.0.0-20211228214822-d284b9a1ca89/go.mod h1:c8J0h9aULj2i3umrfyestM6jCq0LK0U6ly6bWy96nd4=
github.com/umbracle/fastrlp v0.0.0-20211228220138-9c20635803fb h1:jFYwAm/Nn6aWh2QCtejD0Ys/QVNKgf1AStCMONzcEDs=
github.com/umbracle/fastrlp v0.0.0-20211228220138-9c20635803fb/go.mod h1:c8J0h9aULj2i3umrfyestM6jCq0LK0U6ly6bWy96nd4=
github.com/umbracle/fastrlp v0.0.0-20211228223544-26f56490122f h1:swxOU4cwCfjk8Uv/80lOantbwVAoUIzDgm+sZpqX/oY=
github.com/umbracle/fastrlp v0.0.0-20211228223544-26f56490122f/go.mod h1:c8J0h9aULj2i3umrfyestM6jCq0LK0U6ly6bWy96nd4=
github.com/umbracle/fastrlp v0.0.0-20211229195328-c1416904ae17 h1:ZZy8Rj2SqGcZn1hTcoLdwFBROzrf5KiuRwhp8G4nnfA=
github.com/umbracle/fastrlp v0.0.0-20211229195328-c1416904ae17/go.mod h1:c8J0h9aULj2i3umrfyestM6jCq0LK0U6ly6bWy96nd4=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
Expand Down Expand Up @@ -155,6 +145,7 @@ golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
google.golang.org/appengine v1.6.5 h1:tycE03LOZYQNhDpS27tcQdAzLCVMaj7QT2SXxebnpCM=
Expand Down
104 changes: 104 additions & 0 deletions keystore/utils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package keystore

import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"crypto/sha256"
"encoding/hex"
"encoding/json"
"fmt"
"strings"

"golang.org/x/crypto/pbkdf2"
"golang.org/x/crypto/scrypt"
)

func getRand(size int) []byte {
buf := make([]byte, size)
rand.Read(buf)
return buf
}

type hexString []byte

func (h hexString) MarshalJSON() ([]byte, error) {
str := "\"" + hex.EncodeToString(h) + "\""
return []byte(str), nil
}

func (h *hexString) UnmarshalJSON(data []byte) error {
raw := string(data)
raw = strings.Trim(raw, "\"")

data, err := hex.DecodeString(raw)
if err != nil {
return err
}
*h = data
return nil
}

func aesCTR(key, cipherText, iv []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
stream := cipher.NewCTR(block, iv)

dst := make([]byte, len(cipherText))
stream.XORKeyStream(dst, cipherText)

return dst, nil
}

type pbkdf2Params struct {
Dklen int
Salt hexString
C int
Prf string
}

func (p *pbkdf2Params) Key(password []byte) []byte {
return pbkdf2.Key(password, p.Salt, p.C, p.Dklen, sha256.New)
}

type scryptParams struct {
Dklen int
Salt hexString
N int
P int
R int
}

func (s *scryptParams) Key(password []byte) ([]byte, error) {
return scrypt.Key(password, s.Salt, s.N, s.R, s.P, s.Dklen)
}

func applyKdf(fn string, password, paramsRaw []byte) ([]byte, error) {
var key []byte

if fn == "pbkdf2" {
var params pbkdf2Params
if err := json.Unmarshal(paramsRaw, &params); err != nil {
return nil, err
}
if params.Prf != "hmac-sha256" {
return nil, fmt.Errorf("not found")
}
key = params.Key(password)
} else if fn == "scrypt" {
var params scryptParams
err := json.Unmarshal(paramsRaw, &params)
if err != nil {
return nil, err
}
key, err = params.Key(password)
if err != nil {
return nil, err
}
} else {
return nil, fmt.Errorf("kdf '%s' not supported", fn)
}
return key, nil
}
92 changes: 1 addition & 91 deletions keystore/keystore.go → keystore/v3.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,12 @@ package keystore
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"crypto/sha256"
"encoding/hex"
"encoding/json"
"fmt"
"strings"

"github.com/umbracle/go-web3"
"golang.org/x/crypto/pbkdf2"
"golang.org/x/crypto/scrypt"
)

func getRand(size int) []byte {
buf := make([]byte, size)
rand.Read(buf)
return buf
}

// EncryptV3 encrypts data in v3 format
func EncryptV3(content []byte, password string, customScrypt ...int) ([]byte, error) {

Expand Down Expand Up @@ -92,7 +79,7 @@ func DecryptV3(content []byte, password string) ([]byte, error) {
}

// decode the kdf
kdf, err := encoding.Crypto.getKDF([]byte(password))
kdf, err := applyKdf(encoding.Crypto.KDF, []byte(password), encoding.Crypto.KDFParamsRaw)
if err != nil {
return nil, err
}
Expand All @@ -110,19 +97,6 @@ func DecryptV3(content []byte, password string) ([]byte, error) {
return dst, nil
}

func aesCTR(key, cipherText, iv []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
stream := cipher.NewCTR(block, iv)

dst := make([]byte, len(cipherText))
stream.XORKeyStream(dst, cipherText)

return dst, nil
}

type v3Encoding struct {
ID string `json:"id"`
Version int64 `json:"version"`
Expand Down Expand Up @@ -153,67 +127,3 @@ type cryptoEncoding struct {
KDFParamsRaw json.RawMessage `json:"kdfparams"`
Mac hexString `json:"mac"`
}

type hexString []byte

func (h hexString) MarshalJSON() ([]byte, error) {
str := "\"" + hex.EncodeToString(h) + "\""
return []byte(str), nil
}

func (h *hexString) UnmarshalJSON(data []byte) error {
raw := string(data)
raw = strings.Trim(raw, "\"")

data, err := hex.DecodeString(raw)
if err != nil {
return err
}
*h = data
return nil
}

type scryptParams struct {
Dklen int
Salt hexString
N int
P int
R int
}

func (s *scryptParams) Key(password []byte) ([]byte, error) {
return scrypt.Key(password, s.Salt, s.N, s.R, s.P, s.Dklen)
}

func (c *cryptoEncoding) getKDF(password []byte) ([]byte, error) {
var key []byte

if c.KDF == "pbkdf2" {
var params struct {
Dklen int
Salt hexString
C int
Prf string
}
if err := json.Unmarshal(c.KDFParamsRaw, &params); err != nil {
return nil, err
}
if params.Prf != "hmac-sha256" {
return nil, fmt.Errorf("not found")
}
key = pbkdf2.Key(password, params.Salt, params.C, params.Dklen, sha256.New)
} else if c.KDF == "scrypt" {
var params scryptParams
err := json.Unmarshal(c.KDFParamsRaw, &params)
if err != nil {
return nil, err
}
key, err = params.Key(password)
if err != nil {
return nil, err
}
} else {
return nil, fmt.Errorf("kdf '%s' not supported", c.KDF)
}
return key, nil
}
2 changes: 1 addition & 1 deletion keystore/keystore_test.go → keystore/v3_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"github.com/stretchr/testify/assert"
)

func TestKeystore(t *testing.T) {
func TestV3_EncodeDecode(t *testing.T) {
data := []byte{0x1, 0x2}
password := "abcd"

Expand Down
Loading

0 comments on commit 19d7ba3

Please sign in to comment.