nip44: remove size limits.
implements https://github.com/nostr-protocol/nips/pull/1907
This commit is contained in:
@@ -21,10 +21,6 @@ import (
|
|||||||
|
|
||||||
const version byte = 2
|
const version byte = 2
|
||||||
|
|
||||||
const (
|
|
||||||
MaxPlaintextSize = 0xffff // 65535 (64kb-1) => padded to 64kb
|
|
||||||
)
|
|
||||||
|
|
||||||
var zeroes = [32]byte{}
|
var zeroes = [32]byte{}
|
||||||
|
|
||||||
type encryptOptions struct {
|
type encryptOptions struct {
|
||||||
@@ -65,14 +61,22 @@ func Encrypt(plaintext string, conversationKey [32]byte, applyOptions ...func(op
|
|||||||
|
|
||||||
plain := []byte(plaintext)
|
plain := []byte(plaintext)
|
||||||
size := len(plain)
|
size := len(plain)
|
||||||
if size == 0 || size > MaxPlaintextSize {
|
if size == 0 {
|
||||||
return "", fmt.Errorf("plaintext should be between 1b and 64kB")
|
return "", fmt.Errorf("plaintext can't be empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
padding := calcPadding(size)
|
padding := calcPadding(size)
|
||||||
padded := make([]byte, 2+padding)
|
var padded []byte
|
||||||
binary.BigEndian.PutUint16(padded, uint16(size))
|
|
||||||
copy(padded[2:], plain)
|
if size < (1 << 16) {
|
||||||
|
padded = make([]byte, 2+padding)
|
||||||
|
binary.BigEndian.PutUint16(padded[0:2], uint16(size))
|
||||||
|
copy(padded[2:], plain)
|
||||||
|
} else {
|
||||||
|
padded = make([]byte, 6+padding)
|
||||||
|
binary.BigEndian.PutUint32(padded[2:6], uint32(size))
|
||||||
|
copy(padded[6:], plain)
|
||||||
|
}
|
||||||
|
|
||||||
ciphertext, err := chacha(cc20key, cc20nonce, []byte(padded))
|
ciphertext, err := chacha(cc20key, cc20nonce, []byte(padded))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -95,7 +99,7 @@ func Encrypt(plaintext string, conversationKey [32]byte, applyOptions ...func(op
|
|||||||
|
|
||||||
func Decrypt(b64ciphertextWrapped string, conversationKey [32]byte) (string, error) {
|
func Decrypt(b64ciphertextWrapped string, conversationKey [32]byte) (string, error) {
|
||||||
cLen := len(b64ciphertextWrapped)
|
cLen := len(b64ciphertextWrapped)
|
||||||
if cLen < 132 || cLen > 87472 {
|
if cLen < 132 {
|
||||||
return "", fmt.Errorf("invalid payload length: %d", cLen)
|
return "", fmt.Errorf("invalid payload length: %d", cLen)
|
||||||
}
|
}
|
||||||
if b64ciphertextWrapped[0:1] == "#" {
|
if b64ciphertextWrapped[0:1] == "#" {
|
||||||
@@ -112,7 +116,7 @@ func Decrypt(b64ciphertextWrapped string, conversationKey [32]byte) (string, err
|
|||||||
}
|
}
|
||||||
|
|
||||||
dLen := len(decoded)
|
dLen := len(decoded)
|
||||||
if dLen < 99 || dLen > 65603 {
|
if dLen < 99 {
|
||||||
return "", fmt.Errorf("invalid data length: %d", dLen)
|
return "", fmt.Errorf("invalid data length: %d", dLen)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,13 +143,19 @@ func Decrypt(b64ciphertextWrapped string, conversationKey [32]byte) (string, err
|
|||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
unpaddedLen := binary.BigEndian.Uint16(padded[0:2])
|
unpaddedLen := int(binary.BigEndian.Uint16(padded[0:2]))
|
||||||
if unpaddedLen == 0 || unpaddedLen > MaxPlaintextSize || len(padded) != 2+calcPadding(int(unpaddedLen)) {
|
offset := 2
|
||||||
|
if unpaddedLen == 0 {
|
||||||
|
unpaddedLen = int(binary.BigEndian.Uint32(padded[2:6]))
|
||||||
|
offset = 6
|
||||||
|
}
|
||||||
|
|
||||||
|
if unpaddedLen < 1 || len(padded) != offset+calcPadding(unpaddedLen) {
|
||||||
return "", fmt.Errorf("invalid padding")
|
return "", fmt.Errorf("invalid padding")
|
||||||
}
|
}
|
||||||
|
|
||||||
unpadded := padded[2:][:unpaddedLen]
|
unpadded := padded[offset : offset+unpaddedLen]
|
||||||
if len(unpadded) == 0 || len(unpadded) != int(unpaddedLen) {
|
if len(unpadded) == 0 || len(unpadded) != unpaddedLen {
|
||||||
return "", fmt.Errorf("invalid padding")
|
return "", fmt.Errorf("invalid padding")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package nip44
|
|||||||
import (
|
import (
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"fiatjaf.com/nostr"
|
"fiatjaf.com/nostr"
|
||||||
@@ -1053,3 +1054,25 @@ func hexDecode32Array(hexString string) (res [32]byte, err error) {
|
|||||||
_, err = hex.Decode(res[:], []byte(hexString))
|
_, err = hex.Decode(res[:], []byte(hexString))
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestEncryptDecryptLargePayload(t *testing.T) {
|
||||||
|
sk1, err := nostr.SecretKeyFromHex("0000000000000000000000000000000000000000000000000000000000000001")
|
||||||
|
require.NoError(t, err)
|
||||||
|
pub1 := nostr.GetPublicKey(sk1)
|
||||||
|
|
||||||
|
sk2, err := nostr.SecretKeyFromHex("0000000000000000000000000000000000000000000000000000000000000002")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
convKey, err := GenerateConversationKey(pub1, sk2)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
plaintext := strings.Repeat("a", 10_000_000)
|
||||||
|
|
||||||
|
ciphertext, err := Encrypt(plaintext, convKey)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
decrypted, err := Decrypt(ciphertext, convKey)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
require.Equal(t, plaintext, decrypted)
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user