diff --git a/nip49/nip49.go b/nip49/nip49.go index 25882e1..efd343b 100644 --- a/nip49/nip49.go +++ b/nip49/nip49.go @@ -19,6 +19,50 @@ const ( ClientDoesNotTrackThisData KeySecurityByte = 0x02 ) +func Encrypt(secretKey string, password string, logn uint8, ksb KeySecurityByte) (b32code string, err error) { + skb, err := hex.DecodeString(secretKey) + if err != nil || len(skb) != 32 { + return "", fmt.Errorf("invalid secret key") + } + return EncryptBytes(skb, password, logn, ksb) +} + +func EncryptBytes(secretKey []byte, password string, logn uint8, ksb KeySecurityByte) (b32code string, err error) { + salt := make([]byte, 16) + if _, err := rand.Read(salt); err != nil { + 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) + if err != nil { + return "", fmt.Errorf("failed to compute key with scrypt: %w", err) + } + + concat := make([]byte, 91) + concat[0] = 0x02 + concat[1] = byte(logn) + copy(concat[2:2+16], salt) + rand.Read(concat[2+16 : 2+16+24]) // nonce + ad := []byte{byte(ksb)} + copy(concat[2+16+24:2+16+24+1], ad) + + c2p1, err := chacha20poly1305.NewX(key) + if err != nil { + return "", fmt.Errorf("failed to start xchacha20poly1305: %w", err) + } + ciphertext := c2p1.Seal(nil, concat[2+16:2+16+24], secretKey, ad) + if err != nil { + return "", fmt.Errorf("failed to encrypt: %w", err) + } + copy(concat[2+16+24+1:], ciphertext) + + bits5, err := bech32.ConvertBits(concat, 8, 5, true) + if err != nil { + return "", err + } + return bech32.Encode("ncryptsec", bits5) +} + func Decrypt(bech32string string, password string) (secretKey string, err error) { secb, err := DecryptToBytes(bech32string, password) return hex.EncodeToString(secb), err @@ -63,47 +107,3 @@ func DecryptToBytes(bech32string string, password string) (secretKey []byte, err return c2p1.Open(nil, nonce, encryptedKey, ad) } - -func Encrypt(secretKey string, password string, logn uint8, ksb KeySecurityByte) (b32code string, err error) { - skb, err := hex.DecodeString(secretKey) - if err != nil || len(skb) != 32 { - return "", fmt.Errorf("invalid secret key") - } - return EncryptBytes(skb, password, logn, ksb) -} - -func EncryptBytes(secretKey []byte, password string, logn uint8, ksb KeySecurityByte) (b32code string, err error) { - salt := make([]byte, 16) - if _, err := rand.Read(salt); err != nil { - 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) - if err != nil { - return "", fmt.Errorf("failed to compute key with scrypt: %w", err) - } - - concat := make([]byte, 91) - concat[0] = 0x02 - concat[1] = byte(logn) - copy(concat[2:2+16], salt) - rand.Read(concat[2+16 : 2+16+24]) // nonce - ad := []byte{byte(ksb)} - copy(concat[2+16+24:2+16+24+1], ad) - - c2p1, err := chacha20poly1305.NewX(key) - if err != nil { - return "", fmt.Errorf("failed to start xchacha20poly1305: %w", err) - } - ciphertext := c2p1.Seal(nil, concat[2+16:2+16+24], secretKey, ad) - if err != nil { - return "", fmt.Errorf("failed to encrypt: %w", err) - } - copy(concat[2+16+24+1:], ciphertext) - - bits5, err := bech32.ConvertBits(concat, 8, 5, true) - if err != nil { - return "", err - } - return bech32.Encode("ncryptsec", bits5) -}