const argv = require('minimist')(process.argv.slice(2))
const sodium = require('sodium-javascript')
const assert = require('assert')
if (argv.sk && argv.pk) {
console.log('Attempting to decrypt shares', argv._)
if (!Array.isArray(argv.sk)) argv.sk = [argv.sk]
let shareSet = ''
for (const sk of argv.sk) {
const plaintext = attemptDecryptShareSet(argv._, argv.pk, sk)
console.log(plaintext
? 'Decrypted share!'
: 'Decryption failed'
)
shareSet += `${plaintext.toString('hex')} `
}
console.log(shareSet)
} else {
const numKeypairs = argv.keypairs || 3
console.log(`Generating ${numKeypairs} keypairs`)
let pkString = ''
let skString = ''
for (let i = 0; i < numKeypairs; i++) {
const { publicKey, secretKey } = generateKeypair()
console.log(` Public key: ${publicKey.toString('hex')}`)
console.log(` Secret key: ${secretKey.toString('hex')}\n`)
pkString += `--pk ${publicKey.toString('hex')} `
skString += `--sk ${secretKey.toString('hex')} `
}
console.log(pkString, '\n')
console.log(skString)
}
function generateKeypair (seed) {
seed = seed || generateSeed()
const publicKey = Buffer.alloc(sodium.crypto_box_PUBLICKEYBYTES)
const secretKey = Buffer.alloc(sodium.crypto_box_SECRETKEYBYTES)
sodium.crypto_box_seed_keypair(publicKey, secretKey, seed)
return { publicKey, secretKey }
function generateSeed () {
const seed = Buffer.alloc(sodium.crypto_box_SEEDBYTES)
sodium.randombytes_buf(seed)
return seed
}
}
function decrypt (ciphertextWithNonce, publicKey, secretKey) {
assert(ciphertextWithNonce.length > sodium.crypto_box_MACBYTES + sodium.crypto_box_NONCEBYTES, 'cipherText too short')
const nonce = ciphertextWithNonce.slice(0, sodium.crypto_box_NONCEBYTES)
const ciphertext = ciphertextWithNonce.slice(sodium.crypto_box_NONCEBYTES)
const plain = Buffer.alloc(ciphertext.length - sodium.crypto_box_MACBYTES)
const decrypted = sodium.crypto_box_open_easy(plain, ciphertext, nonce, publicKey, secretKey)
if (!decrypted) throw new Error('Decryption failed')
return plain
}
function attemptDecryptShareSet (shareSet, publicKey, secretKey) {
for (const share of shareSet) {
try {
return decrypt(
Buffer.from(share, 'hex'),
Buffer.from(publicKey, 'hex'),
Buffer.from(secretKey, 'hex')
)
} catch (e) {
continue
}
}
}