UNPKG

3.27 kBJavaScriptView Raw
1/* eslint-disable camelcase */
2const { crypto_hash_sha512 } = require('./crypto_hash')
3const { crypto_scalarmult, crypto_scalarmult_base } = require('./crypto_scalarmult')
4const { randombytes } = require('./randombytes')
5const { crypto_generichash_batch } = require('./crypto_generichash')
6const { crypto_secretbox_open_easy, crypto_secretbox_easy } = require('./crypto_secretbox')
7const xsalsa20 = require('xsalsa20')
8const assert = require('nanoassert')
9
10const crypto_box_PUBLICKEYBYTES = 32
11const crypto_box_SECRETKEYBYTES = 32
12const crypto_box_NONCEBYTES = 24
13const crypto_box_ZEROBYTES = 32
14const crypto_box_BOXZEROBYTES = 16
15const crypto_box_SEALBYTES = 48
16const crypto_box_SEEDBYTES = 32
17const crypto_box_BEFORENMBYTES = 32
18
19module.exports = {
20 crypto_box_keypair,
21 crypto_box_seed_keypair,
22 crypto_box_seal,
23 crypto_box_seal_open,
24 crypto_box_PUBLICKEYBYTES,
25 crypto_box_SECRETKEYBYTES,
26 crypto_box_NONCEBYTES,
27 crypto_box_ZEROBYTES,
28 crypto_box_BOXZEROBYTES,
29 crypto_box_SEALBYTES,
30 crypto_box_SEEDBYTES,
31 crypto_box_BEFORENMBYTES
32}
33
34function crypto_box_keypair (pk, sk) {
35 check(pk, crypto_box_PUBLICKEYBYTES)
36 check(sk, crypto_box_SECRETKEYBYTES)
37 randombytes(sk, 32)
38 return crypto_scalarmult_base(pk, sk)
39}
40
41function crypto_box_seed_keypair (pk, sk, seed) {
42 assert(pk.byteLength === crypto_box_PUBLICKEYBYTES, "pk should be 'crypto_box_PUBLICKEYBYTES' bytes")
43 assert(sk.byteLength === crypto_box_SECRETKEYBYTES, "sk should be 'crypto_box_SECRETKEYBYTES' bytes")
44 assert(sk.byteLength === crypto_box_SEEDBYTES, "sk should be 'crypto_box_SEEDBYTES' bytes")
45
46 const hash = new Uint8Array(64)
47 crypto_hash_sha512(hash, seed, 32)
48 sk.set(hash.subarray(0, 32))
49 hash.fill(0)
50
51 return crypto_scalarmult_base(pk, sk)
52}
53
54function crypto_box_seal (c, m, pk) {
55 check(c, crypto_box_SEALBYTES + m.length)
56 check(pk, crypto_box_PUBLICKEYBYTES)
57
58 var epk = c.subarray(0, crypto_box_PUBLICKEYBYTES)
59 var esk = new Uint8Array(crypto_box_SECRETKEYBYTES)
60 crypto_box_keypair(epk, esk)
61
62 var n = new Uint8Array(crypto_box_NONCEBYTES)
63 crypto_generichash_batch(n, [epk, pk])
64
65 var s = new Uint8Array(crypto_box_PUBLICKEYBYTES)
66 crypto_scalarmult(s, esk, pk)
67
68 var k = new Uint8Array(crypto_box_BEFORENMBYTES)
69 var zero = new Uint8Array(16)
70 xsalsa20.core_hsalsa20(k, zero, s, xsalsa20.SIGMA)
71
72 crypto_secretbox_easy(c.subarray(epk.length), m, n, k)
73
74 cleanup(esk)
75}
76
77function crypto_box_seal_open (m, c, pk, sk) {
78 check(c, crypto_box_SEALBYTES)
79 check(m, c.length - crypto_box_SEALBYTES)
80 check(pk, crypto_box_PUBLICKEYBYTES)
81 check(sk, crypto_box_SECRETKEYBYTES)
82
83 var epk = c.subarray(0, crypto_box_PUBLICKEYBYTES)
84
85 var n = new Uint8Array(crypto_box_NONCEBYTES)
86 crypto_generichash_batch(n, [epk, pk])
87
88 var s = new Uint8Array(crypto_box_PUBLICKEYBYTES)
89 crypto_scalarmult(s, sk, epk)
90
91 var k = new Uint8Array(crypto_box_BEFORENMBYTES)
92 var zero = new Uint8Array(16)
93 xsalsa20.core_hsalsa20(k, zero, s, xsalsa20.SIGMA)
94
95 return crypto_secretbox_open_easy(m, c.subarray(epk.length), n, k)
96}
97
98function check (buf, len) {
99 if (!buf || (len && buf.length < len)) throw new Error('Argument must be a buffer' + (len ? ' of length ' + len : ''))
100}
101
102function cleanup (arr) {
103 for (let i = 0; i < arr.length; i++) arr[i] = 0
104}