diff --git a/nip44/nip44.go b/nip44/nip44.go deleted file mode 100644 index 5032c8a..0000000 --- a/nip44/nip44.go +++ /dev/null @@ -1,93 +0,0 @@ -package nip44 - -import ( - "crypto/rand" - "crypto/sha256" - "encoding/base64" - "encoding/hex" - "fmt" - - "github.com/btcsuite/btcd/btcec/v2" - "golang.org/x/crypto/chacha20" -) - -// ComputeSharedSecret returns a shared secret key used to encrypt messages. -// The private and public keys should be hex encoded. -// Uses the Diffie-Hellman key exchange (ECDH) (RFC 4753). -func ComputeSharedSecret(pub string, sk string) ([]byte, error) { - privKeyBytes, err := hex.DecodeString(sk) - if err != nil { - return nil, fmt.Errorf("error decoding sender private key: %w", err) - } - privKey, _ := btcec.PrivKeyFromBytes(privKeyBytes) - - // adding 02 to signal that this is a compressed public key (33 bytes) - pubKeyBytes, err := hex.DecodeString("02" + pub) - if err != nil { - return nil, fmt.Errorf("error decoding hex string of receiver public key '%s': %w", "02"+pub, err) - } - pubKey, err := btcec.ParsePubKey(pubKeyBytes) - if err != nil { - return nil, fmt.Errorf("error parsing receiver public key '%s': %w", "02"+pub, err) - } - - sharedSecret := btcec.GenerateSharedSecret(privKey, pubKey) - hash := sha256.Sum256(sharedSecret) - return hash[:], nil -} - -// Encrypt encrypts message with key using xchacha20. -// key should be the shared secret generated by ComputeSharedSecret. -// Returns: base64(1 + nonce + encrypted_bytes). -func Encrypt(message string, key []byte) (string, error) { - nonce := make([]byte, 24) - if _, err := rand.Read(nonce); err != nil { - return "", fmt.Errorf("error creating nonce: %w", err) - } - - return encryptWithNonce(message, key, nonce) -} - -func encryptWithNonce(message string, key []byte, nonce []byte) (string, error) { - cipher, err := chacha20.NewUnauthenticatedCipher(key, nonce) - if err != nil { - return "", fmt.Errorf("error creating cipher: %w", err) - } - - msg := []byte(message) - cipher.XORKeyStream(msg, msg) - - payload := make([]byte, 1+24+len(msg)) - payload[0] = 1 - copy(payload[1:25], nonce) - copy(payload[25:], msg) - - return base64.StdEncoding.EncodeToString(payload), nil -} - -// Decrypt decrypts a content string using the shared secret key. -// The inverse operation to message -> Encrypt(message, key). -func Decrypt(payload string, key []byte) (string, error) { - data, err := base64.StdEncoding.DecodeString(payload) - if err != nil { - return "", fmt.Errorf("invalid base64: %w", err) - } - - if data[0] != 1 { - return "", fmt.Errorf("unknown version: %d", data[0]) - } - if len(data) <= 25 { - return "", fmt.Errorf("invalid payload, too small: %d", len(data)) - } - - nonce := data[1:25] - msg := data[25:] - cipher, err := chacha20.NewUnauthenticatedCipher(key, nonce) - if err != nil { - return "", fmt.Errorf("error creating cipher: %w", err) - } - - cipher.XORKeyStream(msg, msg) - - return string(msg), nil -}