From 2cba101c22e4a0a490674f559fb2d1d37c0acbab Mon Sep 17 00:00:00 2001 From: fiatjaf Date: Thu, 15 Feb 2024 22:21:11 -0300 Subject: [PATCH] nip49: normalize passwords. because nostr is a giant shit show: https://github.com/nostr-protocol/nips/pull/1053 --- go.mod | 1 + go.sum | 2 ++ nip49/nip49.go | 24 ++++++++++++++++++++---- 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index 00fa569..0748615 100644 --- a/go.mod +++ b/go.mod @@ -16,6 +16,7 @@ require ( golang.org/x/crypto v0.7.0 golang.org/x/exp v0.0.0-20230425010034-47ecfdc1ba53 golang.org/x/net v0.8.0 + golang.org/x/text v0.8.0 ) require ( diff --git a/go.sum b/go.sum index f79ece2..4fdf64b 100644 --- a/go.sum +++ b/go.sum @@ -134,6 +134,8 @@ golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/nip49/nip49.go b/nip49/nip49.go index efd343b..db96685 100644 --- a/nip49/nip49.go +++ b/nip49/nip49.go @@ -9,6 +9,8 @@ import ( "github.com/btcsuite/btcd/btcutil/bech32" "golang.org/x/crypto/chacha20poly1305" "golang.org/x/crypto/scrypt" + "golang.org/x/text/transform" + "golang.org/x/text/unicode/norm" ) type KeySecurityByte byte @@ -33,9 +35,10 @@ func EncryptBytes(secretKey []byte, password string, logn uint8, ksb KeySecurity return "", fmt.Errorf("failed to read salt: %w", err) } n := int(math.Pow(2, float64(int(logn)))) - key, err := scrypt.Key([]byte(password), salt, n, 8, 1, 32) + + key, err := getKey(password, salt, n) if err != nil { - return "", fmt.Errorf("failed to compute key with scrypt: %w", err) + return "", err } concat := make([]byte, 91) @@ -95,9 +98,9 @@ func DecryptToBytes(bech32string string, password string) (secretKey []byte, err // keySecurityByte := ad[0] encryptedKey := data[2+16+24+1:] - key, err := scrypt.Key([]byte(password), salt, n, 8, 1, 32) + key, err := getKey(password, salt, n) if err != nil { - return nil, fmt.Errorf("failed to compute key with scrypt: %w", err) + return nil, err } c2p1, err := chacha20poly1305.NewX(key) @@ -107,3 +110,16 @@ func DecryptToBytes(bech32string string, password string) (secretKey []byte, err return c2p1.Open(nil, nonce, encryptedKey, ad) } + +func getKey(password string, salt []byte, n int) ([]byte, error) { + normalizedPassword, _, err := transform.Bytes(norm.NFKC, []byte(password)) + if err != nil { + return nil, fmt.Errorf("failed to normalize password: %w", err) + } + + key, err := scrypt.Key(normalizedPassword, salt, n, 8, 1, 32) + if err != nil { + return nil, fmt.Errorf("failed to compute key with scrypt: %w", err) + } + return key, nil +}