I'm aware that the difference between the NaCL sign keys vs the box keys is that the secret key that comes from the NaCL box keypair is the 32 bit secret key + 32 bit public key
.
So I decided to use the tweetnacl.js library to create a signing key and use the box functions to encrypt and decrypt data.
I used the nacl.sign.keyPair()
to generate a sign key then I stripped off the last 32 bits (public key) off the secretKey
Uint8Array then used the following 2 functions to encrypt and decrypt the data.
The encryption works fine, but the decryption always fails most probably because of an incorrect key. I'm not sure if there's some other nuance of NaCL that I'm not considering here.
const nacl = require("tweetnacl")
const util = require("tweetnacl-util")
// Encrypt function
function encrypt(receiverPublicKey, msgParams) {
const ephemeralKeyPair = nacl.box.keyPair()
const pubKeyUInt8Array = util.decodeBase64(receiverPublicKey)
const msgParamsUInt8Array = util.decodeUTF8(msgParams)
const nonce = nacl.randomBytes(nacl.box.nonceLength)
const encryptedMessage = nacl.box(
msgParamsUInt8Array,
nonce,
pubKeyUInt8Array,
ephemeralKeyPair.secretKey
)
return {
ciphertext: util.encodeBase64(encryptedMessage),
ephemPubKey: util.encodeBase64(ephemeralKeyPair.publicKey),
nonce: util.encodeBase64(nonce),
version: "x25519-xsalsa20-poly1305"
}
}
// Decrypt function
function decrypt(receiverSecretKey, encryptedData) {
const receiverSecretKeyUint8Array = util.decodeBase64(
receiverSecretKey
)
const nonce = util.decodeBase64(encryptedData.nonce)
const ciphertext = util.decodeBase64(encryptedData.ciphertext)
const ephemPubKey = util.decodeBase64(encryptedData.ephemPubKey)
const decryptedMessage = nacl.box.open(
ciphertext,
nonce,
ephemPubKey,
receiverSecretKeyUint8Array
)
return util.encodeUTF8(decryptedMessage)
}
Note - I have passed in the public and private keys encoded in base64 into the encrypt and decrypt function respectively.