1 |
|
2 | const assert = require('nanoassert')
|
3 | const { crypto_stream, crypto_stream_xor } = require('./crypto_stream')
|
4 | const { crypto_onetimeauth, crypto_onetimeauth_verify, crypto_onetimeauth_BYTES, crypto_onetimeauth_KEYBYTES } = require('./crypto_onetimeauth')
|
5 |
|
6 | const crypto_secretbox_KEYBYTES = 32
|
7 | const crypto_secretbox_NONCEBYTES = 24
|
8 | const crypto_secretbox_ZEROBYTES = 32
|
9 | const crypto_secretbox_BOXZEROBYTES = 16
|
10 | const crypto_secretbox_MACBYTES = 16
|
11 |
|
12 | module.exports = {
|
13 | crypto_secretbox,
|
14 | crypto_secretbox_open,
|
15 | crypto_secretbox_detached,
|
16 | crypto_secretbox_open_detached,
|
17 | crypto_secretbox_easy,
|
18 | crypto_secretbox_open_easy,
|
19 | crypto_secretbox_KEYBYTES,
|
20 | crypto_secretbox_NONCEBYTES,
|
21 | crypto_secretbox_ZEROBYTES,
|
22 | crypto_secretbox_BOXZEROBYTES,
|
23 | crypto_secretbox_MACBYTES
|
24 | }
|
25 |
|
26 | function crypto_secretbox (c, m, n, k) {
|
27 | assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
|
28 | const mlen = m.byteLength
|
29 | assert(mlen >= crypto_secretbox_ZEROBYTES, "mlen must be at least 'crypto_secretbox_ZEROBYTES'")
|
30 | assert(n.byteLength === crypto_secretbox_NONCEBYTES, "n must be 'crypto_secretbox_NONCEBYTES' bytes")
|
31 | assert(k.byteLength === crypto_secretbox_KEYBYTES, "k must be 'crypto_secretbox_KEYBYTES' bytes")
|
32 |
|
33 | crypto_stream_xor(c, m, n, k)
|
34 | crypto_onetimeauth(
|
35 | c.subarray(crypto_secretbox_BOXZEROBYTES, crypto_secretbox_BOXZEROBYTES + crypto_onetimeauth_BYTES),
|
36 | c.subarray(crypto_secretbox_BOXZEROBYTES + crypto_onetimeauth_BYTES, c.byteLength),
|
37 | c.subarray(0, crypto_onetimeauth_KEYBYTES)
|
38 | )
|
39 | c.fill(0, 0, crypto_secretbox_BOXZEROBYTES)
|
40 | return 0
|
41 | }
|
42 |
|
43 | function crypto_secretbox_open (m, c, n, k) {
|
44 | assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
|
45 | const mlen = m.byteLength
|
46 | assert(mlen >= crypto_secretbox_ZEROBYTES, "mlen must be at least 'crypto_secretbox_ZEROBYTES'")
|
47 | assert(n.byteLength === crypto_secretbox_NONCEBYTES, "n must be 'crypto_secretbox_NONCEBYTES' bytes")
|
48 | assert(k.byteLength === crypto_secretbox_KEYBYTES, "k must be 'crypto_secretbox_KEYBYTES' bytes")
|
49 |
|
50 | const x = new Uint8Array(crypto_onetimeauth_KEYBYTES)
|
51 | crypto_stream(x, n, k)
|
52 | const validMac = crypto_onetimeauth_verify(
|
53 | c.subarray(crypto_secretbox_BOXZEROBYTES, crypto_secretbox_BOXZEROBYTES + crypto_onetimeauth_BYTES),
|
54 | c.subarray(crypto_secretbox_BOXZEROBYTES + crypto_onetimeauth_BYTES, c.byteLength),
|
55 | x
|
56 | )
|
57 |
|
58 | if (validMac === false) return false
|
59 | crypto_stream_xor(m, c, n, k)
|
60 | m.fill(0, 0, 32)
|
61 | return true
|
62 | }
|
63 |
|
64 | function crypto_secretbox_detached (o, mac, msg, n, k) {
|
65 | assert(o.byteLength === msg.byteLength, "o must be 'msg.byteLength' bytes")
|
66 | assert(mac.byteLength === crypto_secretbox_MACBYTES, "mac must be 'crypto_secretbox_MACBYTES' bytes")
|
67 | assert(n.byteLength === crypto_secretbox_NONCEBYTES, "n must be 'crypto_secretbox_NONCEBYTES' bytes")
|
68 | assert(k.byteLength === crypto_secretbox_KEYBYTES, "k must be 'crypto_secretbox_KEYBYTES' bytes")
|
69 |
|
70 | const tmp = new Uint8Array(msg.byteLength + mac.byteLength)
|
71 | crypto_secretbox_easy(tmp, msg, n, k)
|
72 | o.set(tmp.subarray(0, msg.byteLength))
|
73 | mac.set(tmp.subarray(msg.byteLength))
|
74 | return true
|
75 | }
|
76 |
|
77 | function crypto_secretbox_open_detached (msg, o, mac, n, k) {
|
78 | assert(o.byteLength === msg.byteLength, "o must be 'msg.byteLength' bytes")
|
79 | assert(mac.byteLength === crypto_secretbox_MACBYTES, "mac must be 'crypto_secretbox_MACBYTES' bytes")
|
80 | assert(n.byteLength === crypto_secretbox_NONCEBYTES, "n must be 'crypto_secretbox_NONCEBYTES' bytes")
|
81 | assert(k.byteLength === crypto_secretbox_KEYBYTES, "k must be 'crypto_secretbox_KEYBYTES' bytes")
|
82 |
|
83 | const tmp = new Uint8Array(o.byteLength + mac.byteLength)
|
84 | tmp.set(o)
|
85 | tmp.set(mac, msg.byteLength)
|
86 | return crypto_secretbox_open_easy(msg, tmp, n, k)
|
87 | }
|
88 |
|
89 | function crypto_secretbox_easy (o, msg, n, k) {
|
90 | assert(o.byteLength === msg.byteLength + crypto_secretbox_MACBYTES, "o must be 'msg.byteLength + crypto_secretbox_MACBYTES' bytes")
|
91 | assert(n.byteLength === crypto_secretbox_NONCEBYTES, "n must be 'crypto_secretbox_NONCEBYTES' bytes")
|
92 | assert(k.byteLength === crypto_secretbox_KEYBYTES, "k must be 'crypto_secretbox_KEYBYTES' bytes")
|
93 |
|
94 | const m = new Uint8Array(crypto_secretbox_ZEROBYTES + msg.byteLength)
|
95 | const c = new Uint8Array(m.byteLength)
|
96 | m.set(msg, crypto_secretbox_ZEROBYTES)
|
97 | if (crypto_secretbox(c, m, n, k) === false) return false
|
98 | o.set(c.subarray(crypto_secretbox_BOXZEROBYTES))
|
99 | return true
|
100 | }
|
101 |
|
102 | function crypto_secretbox_open_easy (msg, box, n, k) {
|
103 | assert(box.byteLength === msg.byteLength + crypto_secretbox_MACBYTES, "box must be 'msg.byteLength + crypto_secretbox_MACBYTES' bytes")
|
104 | assert(n.byteLength === crypto_secretbox_NONCEBYTES, "n must be 'crypto_secretbox_NONCEBYTES' bytes")
|
105 | assert(k.byteLength === crypto_secretbox_KEYBYTES, "k must be 'crypto_secretbox_KEYBYTES' bytes")
|
106 |
|
107 | const c = new Uint8Array(crypto_secretbox_BOXZEROBYTES + box.byteLength)
|
108 | const m = new Uint8Array(c.byteLength)
|
109 | c.set(box, crypto_secretbox_BOXZEROBYTES)
|
110 | if (crypto_secretbox_open(m, c, n, k) === false) return false
|
111 | msg.set(m.subarray(crypto_secretbox_ZEROBYTES))
|
112 | return true
|
113 | }
|