From 46a0c95b968cbf5fd1ccc4e3ae58faae74114348 Mon Sep 17 00:00:00 2001 From: fiatjaf Date: Sat, 14 Sep 2024 22:47:26 -0300 Subject: [PATCH] some tweaks to 17, 44 and 59. --- nip17/nip17.go | 2 +- nip44/nip44.go | 61 ++++++++++++++++++++++---------------------------- nip59/nip59.go | 6 ++--- 3 files changed, 31 insertions(+), 38 deletions(-) diff --git a/nip17/nip17.go b/nip17/nip17.go index b5d5242..eae0728 100644 --- a/nip17/nip17.go +++ b/nip17/nip17.go @@ -81,7 +81,7 @@ func ListenForMessages( func(otherpubkey, ciphertext string) (string, error) { return kr.Decrypt(ctx, ciphertext, otherpubkey) }, ) if err != nil { - nostr.InfoLogger.Printf("[nip17] failed to unwrap received message: %s\n", err) + nostr.InfoLogger.Printf("[nip17] failed to unwrap received message '%s' from %s: %s\n", ie.Event, ie.Relay.URL, err) continue } diff --git a/nip44/nip44.go b/nip44/nip44.go index 841d4ee..23aee29 100644 --- a/nip44/nip44.go +++ b/nip44/nip44.go @@ -8,7 +8,6 @@ import ( "encoding/base64" "encoding/binary" "encoding/hex" - "errors" "fmt" "io" "math" @@ -26,20 +25,19 @@ const ( MaxPlaintextSize = 0xffff // 65535 (64kb-1) => padded to 64kb ) +var zeroes = [32]byte{} + type encryptOptions struct { err error - nonce []byte + nonce [32]byte } -// Deprecated: use WithCustomNonce instead of WithCustomSalt, so the naming is less confusing -var WithCustomSalt = WithCustomNonce - -func WithCustomNonce(salt []byte) func(opts *encryptOptions) { +func WithCustomNonce(nonce []byte) func(opts *encryptOptions) { return func(opts *encryptOptions) { - if len(salt) != 32 { - opts.err = errors.New("salt must be 32 bytes") + if len(nonce) != 32 { + opts.err = fmt.Errorf("invalid custom nonce, must be 32 bytes, got %d", len(nonce)) } - opts.nonce = salt + copy(opts.nonce[:], nonce) } } @@ -54,9 +52,8 @@ func Encrypt(plaintext string, conversationKey [32]byte, applyOptions ...func(op } nonce := opts.nonce - if nonce == nil { - nonce := make([]byte, 32) - if _, err := rand.Read(nonce); err != nil { + if nonce == zeroes { + if _, err := rand.Read(nonce[:]); err != nil { return "", err } } @@ -69,7 +66,7 @@ func Encrypt(plaintext string, conversationKey [32]byte, applyOptions ...func(op plain := []byte(plaintext) size := len(plain) if size < MinPlaintextSize || size > MaxPlaintextSize { - return "", errors.New("plaintext should be between 1b and 64kB") + return "", fmt.Errorf("plaintext should be between 1b and 64kB") } padding := calcPadding(size) @@ -89,7 +86,7 @@ func Encrypt(plaintext string, conversationKey [32]byte, applyOptions ...func(op concat := make([]byte, 1+32+len(ciphertext)+32) concat[0] = version - copy(concat[1:], nonce) + copy(concat[1:], nonce[:]) copy(concat[1+32:], ciphertext) copy(concat[1+32+len(ciphertext):], mac) @@ -99,27 +96,30 @@ func Encrypt(plaintext string, conversationKey [32]byte, applyOptions ...func(op func Decrypt(b64ciphertextWrapped string, conversationKey [32]byte) (string, error) { cLen := len(b64ciphertextWrapped) if cLen < 132 || cLen > 87472 { - return "", errors.New(fmt.Sprintf("invalid payload length: %d", cLen)) + return "", fmt.Errorf(fmt.Sprintf("invalid payload length: %d", cLen)) } if b64ciphertextWrapped[0:1] == "#" { - return "", errors.New("unknown version") + return "", fmt.Errorf("unknown version") } decoded, err := base64.StdEncoding.DecodeString(b64ciphertextWrapped) if err != nil { - return "", errors.New("invalid base64") + return "", fmt.Errorf("invalid base64") } if decoded[0] != version { - return "", errors.New(fmt.Sprintf("unknown version %d", decoded[0])) + return "", fmt.Errorf(fmt.Sprintf("unknown version %d", decoded[0])) } dLen := len(decoded) if dLen < 99 || dLen > 65603 { - return "", errors.New(fmt.Sprintf("invalid data length: %d", dLen)) + return "", fmt.Errorf(fmt.Sprintf("invalid data length: %d", dLen)) } - nonce, ciphertext, givenMac := decoded[1:33], decoded[33:dLen-32], decoded[dLen-32:] + var nonce [32]byte + copy(nonce[:], decoded[1:33]) + ciphertext := decoded[33 : dLen-32] + givenMac := decoded[dLen-32:] enc, cc20nonce, auth, err := messageKeys(conversationKey, nonce) if err != nil { return "", err @@ -131,7 +131,7 @@ func Decrypt(b64ciphertextWrapped string, conversationKey [32]byte) (string, err } if !bytes.Equal(givenMac, expectedMac) { - return "", errors.New("invalid hmac") + return "", fmt.Errorf("invalid hmac") } padded, err := chacha(enc, cc20nonce, ciphertext) @@ -142,12 +142,12 @@ func Decrypt(b64ciphertextWrapped string, conversationKey [32]byte) (string, err unpaddedLen := binary.BigEndian.Uint16(padded[0:2]) if unpaddedLen < uint16(MinPlaintextSize) || unpaddedLen > uint16(MaxPlaintextSize) || len(padded) != 2+calcPadding(int(unpaddedLen)) { - return "", errors.New("invalid padding") + return "", fmt.Errorf("invalid padding") } unpadded := padded[2:][:unpaddedLen] if len(unpadded) == 0 || len(unpadded) != int(unpaddedLen) { - return "", errors.New("invalid padding") + return "", fmt.Errorf("invalid padding") } return string(unpadded), nil @@ -182,22 +182,15 @@ func chacha(key []byte, nonce []byte, message []byte) ([]byte, error) { return dst, nil } -func sha256Hmac(key []byte, ciphertext []byte, nonce []byte) ([]byte, error) { - if len(nonce) != 32 { - return nil, errors.New("nonce aad must be 32 bytes") - } +func sha256Hmac(key []byte, ciphertext []byte, nonce [32]byte) ([]byte, error) { h := hmac.New(sha256.New, key) - h.Write(nonce) + h.Write(nonce[:]) h.Write(ciphertext) return h.Sum(nil), nil } -func messageKeys(conversationKey [32]byte, nonce []byte) ([]byte, []byte, []byte, error) { - if len(nonce) != 32 { - return nil, nil, nil, errors.New("nonce must be 32 bytes") - } - - r := hkdf.Expand(sha256.New, conversationKey[:], nonce) +func messageKeys(conversationKey [32]byte, nonce [32]byte) ([]byte, []byte, []byte, error) { + r := hkdf.Expand(sha256.New, conversationKey[:], nonce[:]) enc := make([]byte, 32) if _, err := io.ReadFull(r, enc); err != nil { return nil, nil, nil, err diff --git a/nip59/nip59.go b/nip59/nip59.go index 1640d1f..2fea757 100644 --- a/nip59/nip59.go +++ b/nip59/nip59.go @@ -39,7 +39,7 @@ func GiftWrap( if err != nil { return nostr.Event{}, err } - sealCiphertext, err := nip44.Encrypt(seal.String(), temporaryConversationKey, nil) + sealCiphertext, err := nip44.Encrypt(seal.String(), temporaryConversationKey) if err != nil { return nostr.Event{}, err } @@ -57,8 +57,8 @@ func GiftWrap( modify(&gw) } - if err := seal.Sign(nonceKey); err != nil { - return seal, err + if err := gw.Sign(nonceKey); err != nil { + return gw, err } return gw, nil