Skip to content

Commit 581070c

Browse files
committed
test: optimize NIP-44 unit tests
Signed-off-by: ABHAY PANDEY <pandeyabhay967@gmail.com>
1 parent 36e5af8 commit 581070c

1 file changed

Lines changed: 30 additions & 77 deletions

File tree

test/unit/utils/nip44.spec.ts

Lines changed: 30 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -18,155 +18,112 @@ function pubkeyFromPrivkey(secHex: string): string {
1818

1919
const SEC1 = '0000000000000000000000000000000000000000000000000000000000000001'
2020
const SEC2 = '0000000000000000000000000000000000000000000000000000000000000002'
21+
const SEC3 = '0000000000000000000000000000000000000000000000000000000000000003'
2122
const KNOWN_CONVERSATION_KEY = 'c41c775356fd92eadc63ff5a0dc1da211b268cbea22316767095b2871ea1412d'
2223
const KNOWN_NONCE = '0000000000000000000000000000000000000000000000000000000000000001'
2324
const KNOWN_PLAINTEXT = 'a'
2425
const KNOWN_PAYLOAD =
2526
'AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABee0G5VSK0/9YypIObAtDKfYEAjD35uVkHyB0F4DwrcNaCXlCWZKaArsGrY6M9wnuTMxWfp1RTN9Xga8no+kF5Vsb'
2627

28+
const PUB1 = pubkeyFromPrivkey(SEC1)
29+
const PUB2 = pubkeyFromPrivkey(SEC2)
30+
const PUB3 = pubkeyFromPrivkey(SEC3)
31+
const CONVERSATION_KEY = getConversationKey(SEC1, PUB2)
32+
const RECIPIENT_CONVERSATION_KEY = getConversationKey(SEC2, PUB1)
33+
const DIFFERENT_CONVERSATION_KEY = getConversationKey(SEC1, PUB3)
34+
2735
// ---------------------------------------------------------------------------
2836

2937
describe('NIP-44', () => {
3038
describe('getConversationKey', () => {
3139
it('derives the correct conversation key from sec1 and pub2', () => {
32-
const pub2 = pubkeyFromPrivkey(SEC2)
33-
const key = getConversationKey(SEC1, pub2)
34-
expect(key.toString('hex')).to.equal(KNOWN_CONVERSATION_KEY)
40+
expect(CONVERSATION_KEY.toString('hex')).to.equal(KNOWN_CONVERSATION_KEY)
3541
})
3642

3743
it('is symmetric: conv(a, B) == conv(b, A)', () => {
38-
const pub1 = pubkeyFromPrivkey(SEC1)
39-
const pub2 = pubkeyFromPrivkey(SEC2)
40-
const keyAB = getConversationKey(SEC1, pub2)
41-
const keyBA = getConversationKey(SEC2, pub1)
42-
expect(keyAB.toString('hex')).to.equal(keyBA.toString('hex'))
44+
expect(CONVERSATION_KEY.toString('hex')).to.equal(RECIPIENT_CONVERSATION_KEY.toString('hex'))
4345
})
4446

4547
it('produces different keys for different key pairs', () => {
46-
const sec3 = '0000000000000000000000000000000000000000000000000000000000000003'
47-
const pub2 = pubkeyFromPrivkey(SEC2)
48-
const pub3 = pubkeyFromPrivkey(sec3)
49-
const key12 = getConversationKey(SEC1, pub2)
50-
const key13 = getConversationKey(SEC1, pub3)
51-
expect(key12.toString('hex')).to.not.equal(key13.toString('hex'))
48+
expect(CONVERSATION_KEY.toString('hex')).to.not.equal(DIFFERENT_CONVERSATION_KEY.toString('hex'))
5249
})
5350
})
5451

5552
describe('nip44Encrypt', () => {
5653
it('produces the canonical payload from the NIP-44 spec test vector', () => {
57-
const pub2 = pubkeyFromPrivkey(SEC2)
58-
const conversationKey = getConversationKey(SEC1, pub2)
5954
const nonce = Buffer.from(KNOWN_NONCE, 'hex')
6055

61-
const payload = nip44Encrypt(KNOWN_PLAINTEXT, conversationKey, nonce)
56+
const payload = nip44Encrypt(KNOWN_PLAINTEXT, CONVERSATION_KEY, nonce)
6257
expect(payload).to.equal(KNOWN_PAYLOAD)
6358
})
6459

6560
it('produces a valid base64 string starting with version byte 0x02', () => {
66-
const pub2 = pubkeyFromPrivkey(SEC2)
67-
const conversationKey = getConversationKey(SEC1, pub2)
68-
69-
const payload = nip44Encrypt('hello', conversationKey)
61+
const payload = nip44Encrypt('hello', CONVERSATION_KEY)
7062
const decoded = Buffer.from(payload, 'base64')
7163

7264
expect(decoded[0]).to.equal(2) // version byte
7365
expect(payload.length).to.be.within(132, 87472)
7466
})
7567

7668
it('produces different ciphertexts for the same plaintext (random nonce)', () => {
77-
const pub2 = pubkeyFromPrivkey(SEC2)
78-
const conversationKey = getConversationKey(SEC1, pub2)
79-
80-
const payload1 = nip44Encrypt('same message', conversationKey)
81-
const payload2 = nip44Encrypt('same message', conversationKey)
69+
const payload1 = nip44Encrypt('same message', CONVERSATION_KEY)
70+
const payload2 = nip44Encrypt('same message', CONVERSATION_KEY)
8271

8372
expect(payload1).to.not.equal(payload2)
8473
})
8574

8675
it('throws for empty plaintext', () => {
87-
const pub2 = pubkeyFromPrivkey(SEC2)
88-
const conversationKey = getConversationKey(SEC1, pub2)
89-
90-
expect(() => nip44Encrypt('', conversationKey)).to.throw('invalid plaintext length')
76+
expect(() => nip44Encrypt('', CONVERSATION_KEY)).to.throw('invalid plaintext length')
9177
})
9278

9379
it('throws for plaintext exceeding 65535 bytes', () => {
94-
const pub2 = pubkeyFromPrivkey(SEC2)
95-
const conversationKey = getConversationKey(SEC1, pub2)
96-
97-
expect(() => nip44Encrypt('x'.repeat(65536), conversationKey)).to.throw('invalid plaintext length')
80+
expect(() => nip44Encrypt('x'.repeat(65536), CONVERSATION_KEY)).to.throw('invalid plaintext length')
9881
})
9982
})
10083

10184
describe('nip44Decrypt', () => {
10285
it('decrypts the canonical NIP-44 spec test vector', () => {
103-
const pub2 = pubkeyFromPrivkey(SEC2)
104-
const conversationKey = getConversationKey(SEC1, pub2)
105-
106-
const plaintext = nip44Decrypt(KNOWN_PAYLOAD, conversationKey)
86+
const plaintext = nip44Decrypt(KNOWN_PAYLOAD, CONVERSATION_KEY)
10787
expect(plaintext).to.equal(KNOWN_PLAINTEXT)
10888
})
10989

11090
it('round-trips any plaintext through encrypt then decrypt', () => {
111-
const pub2 = pubkeyFromPrivkey(SEC2)
112-
const conversationKey = getConversationKey(SEC1, pub2)
11391
const original = 'Hola, que tal? 🌍'
11492

115-
const payload = nip44Encrypt(original, conversationKey)
116-
const recovered = nip44Decrypt(payload, conversationKey)
93+
const payload = nip44Encrypt(original, CONVERSATION_KEY)
94+
const recovered = nip44Decrypt(payload, CONVERSATION_KEY)
11795

11896
expect(recovered).to.equal(original)
11997
})
12098

12199
it('works with the symmetric key (recipient decrypts sender message)', () => {
122-
const pub1 = pubkeyFromPrivkey(SEC1)
123-
const pub2 = pubkeyFromPrivkey(SEC2)
124-
125-
const senderKey = getConversationKey(SEC1, pub2)
126-
const recipientKey = getConversationKey(SEC2, pub1)
127-
128-
const payload = nip44Encrypt('secret message', senderKey)
129-
const plaintext = nip44Decrypt(payload, recipientKey)
100+
const payload = nip44Encrypt('secret message', CONVERSATION_KEY)
101+
const plaintext = nip44Decrypt(payload, RECIPIENT_CONVERSATION_KEY)
130102

131103
expect(plaintext).to.equal('secret message')
132104
})
133105

134106
it('throws when MAC is tampered', () => {
135-
const pub2 = pubkeyFromPrivkey(SEC2)
136-
const conversationKey = getConversationKey(SEC1, pub2)
137-
const payload = nip44Encrypt('tamper me', conversationKey)
107+
const payload = nip44Encrypt('tamper me', CONVERSATION_KEY)
138108

139109
// Flip the last character of the base64 payload to corrupt the MAC
140110
const tampered = payload.slice(0, -4) + 'AAAA'
141111

142-
expect(() => nip44Decrypt(tampered, conversationKey)).to.throw()
112+
expect(() => nip44Decrypt(tampered, CONVERSATION_KEY)).to.throw()
143113
})
144114

145115
it('throws for payload starting with # (unsupported future version)', () => {
146-
const pub2 = pubkeyFromPrivkey(SEC2)
147-
const conversationKey = getConversationKey(SEC1, pub2)
148-
149-
expect(() => nip44Decrypt('#not-base64', conversationKey)).to.throw('unknown version')
116+
expect(() => nip44Decrypt('#not-base64', CONVERSATION_KEY)).to.throw('unknown version')
150117
})
151118

152119
it('throws for payload that is too short', () => {
153-
const pub2 = pubkeyFromPrivkey(SEC2)
154-
const conversationKey = getConversationKey(SEC1, pub2)
155-
156-
expect(() => nip44Decrypt('dG9vc2hvcnQ=', conversationKey)).to.throw('invalid payload size')
120+
expect(() => nip44Decrypt('dG9vc2hvcnQ=', CONVERSATION_KEY)).to.throw('invalid payload size')
157121
})
158122

159123
it('throws for wrong conversation key', () => {
160-
const sec3 = '0000000000000000000000000000000000000000000000000000000000000003'
161-
const pub2 = pubkeyFromPrivkey(SEC2)
162-
const pub3 = pubkeyFromPrivkey(sec3)
163-
164-
const senderKey = getConversationKey(SEC1, pub2)
165-
const wrongKey = getConversationKey(SEC1, pub3)
166-
167-
const payload = nip44Encrypt('private', senderKey)
124+
const payload = nip44Encrypt('private', CONVERSATION_KEY)
168125

169-
expect(() => nip44Decrypt(payload, wrongKey)).to.throw()
126+
expect(() => nip44Decrypt(payload, DIFFERENT_CONVERSATION_KEY)).to.throw()
170127
})
171128
})
172129

@@ -176,9 +133,7 @@ describe('NIP-44', () => {
176133
})
177134

178135
it('returns undefined for a freshly encrypted payload', () => {
179-
const pub2 = pubkeyFromPrivkey(SEC2)
180-
const conversationKey = getConversationKey(SEC1, pub2)
181-
const payload = nip44Encrypt('hello', conversationKey)
136+
const payload = nip44Encrypt('hello', CONVERSATION_KEY)
182137

183138
expect(validateNip44Payload(payload)).to.be.undefined
184139
})
@@ -228,11 +183,9 @@ describe('NIP-44', () => {
228183

229184
for (const [unpaddedLen, expectedPaddedLen] of cases) {
230185
it(`pads ${unpaddedLen} bytes to ${expectedPaddedLen} bytes`, () => {
231-
const pub2 = pubkeyFromPrivkey(SEC2)
232-
const conversationKey = getConversationKey(SEC1, pub2)
233186
const plaintext = 'a'.repeat(unpaddedLen)
234187

235-
const payload = nip44Encrypt(plaintext, conversationKey)
188+
const payload = nip44Encrypt(plaintext, CONVERSATION_KEY)
236189
const decoded = Buffer.from(payload, 'base64')
237190

238191
// Layout: 1 (version) + 32 (nonce) + paddedLen + 2 (length prefix) + 32 (mac)

0 commit comments

Comments
 (0)