This question is the inverse of the existing one here: Encrypt in python 3.7 and decode in NODEJS 12 .
I would prefer to use the exact equivalent of tweet-nacl on python but that project says it is old and not recommended https://github.com/warner/python-tweetnacl . Their recommended replacement is https://github.com/pyca/pynacl : but that one is an interface to libsodium not tweet-nacl and there is no clear documentation on how to achieve the decryption.
Here is the JS encryption:
let msgArr = naclutil.decodeUTF8(jprint(msg))
let nonce = nacl.randomBytes(nacl.box.nonceLength)
let keyPair = this.genKeyPair()
let encrypted = nacl.box(
msgArr,
nonce,
naclutil.decodeBase64(pubKey),
naclutil.decodeBase64(keyPair.privkey)
)
let nonce64 = naclutil.encodeBase64(nonce)
let encrypted64 = naclutil.encodeBase64(encrypted)
The (working) tweet-nacl javascript decryption code is:
const decryptedMessage = nacl.box.open(
naclutil.decodeBase64(payload.encrypted.encrypted),
naclutil.decodeBase64(payload.encrypted.nonce),
naclutil.decodeBase64(payload.encrypted.ephemPubKey),
naclutil.decodeBase64(privKey)
)
const decodedMessage = naclutil.encodeUTF8(decryptedMessage)
My problem is that for pynacl
they do not show any examples of using the ephemPubKey for decryption. The examples I could find were like the following:
import binascii
from nacl.encoding import HexEncoder
from nacl.exceptions import CryptoError
from nacl.secret import Aead, SecretBox
benc= binascii.unhexlify(encrypted)
bnonce = binascii.unhexlify(nonce)
box = SecretBox(privKey, encoder=HexEncoder)
decrypted = box.decrypt(benc, bnonce, encoder=HexEncoder),
Has anyone been able to get the tweet-nacl Javascript generated encryption successfully decrypted into python?
SecretBox
and thus the PyNaCl example you posted is for symmetric encryption, s. here. You can find the documentation for public key encryption with PyNaCl here and for PyNaCl in general here.
In the following example, a plaintext is encrypted with TweetNaCl.js and decrypted with PyNaCl.
var secretKey_js = nacl.util.decodeBase64("FJGsHP0dMkDNkpAkT4hZrcbv27L8XNO8ymhLxpPpDkE=");
var publicKey_py = nacl.util.decodeBase64("0EyrzGW6qn0EGEV0Cx2Z7tQeln6FdwZVINz0FezlvTM=");
var nonce = nacl.randomBytes(24)
var msgStr = "The quick brown fox jumps over the lazy dog";
var message = nacl.util.decodeUTF8(msgStr);
var box_js = nacl.box(message, nonce, publicKey_py, secretKey_js)
console.log(nacl.util.encodeBase64(nonce)) // 2e8WuEr0+5nc14VBxQrOl4ob6guOTySr
console.log(nacl.util.encodeBase64(box_js)) // eJ8sO0mFNaaWLeXVcNNpw0PurwfINp/BlnErSzOnxXJ5zqu3wLrW4fHIa4kIAxFkuMVJaf0AR4pYon0=
The code is basically the same as your code with the difference that the keys are not generated but imported.
import base64
from nacl.public import PrivateKey, PublicKey, Box
from nacl.encoding import Base64Encoder
secretKeyB64_py = "XVdFnozXd+7xm6MVazPemgSq6un+fGpDvwgxo9UbsdM=";
publicKeyB64_js = "ixxgLis2RzqMWys76HuoH7TwrwBbXoDrwl3jGsRysRI=";
secretKey_py = PrivateKey(secretKeyB64_py, encoder=Base64Encoder)
publicKey_js = PublicKey(publicKeyB64_js, encoder=Base64Encoder)
nonce = base64.b64decode("2e8WuEr0+5nc14VBxQrOl4ob6guOTySr");
box_js = base64.b64decode("eJ8sO0mFNaaWLeXVcNNpw0PurwfINp/BlnErSzOnxXJ5zqu3wLrW4fHIa4kIAxFkuMVJaf0AR4pYon0=");
box_py = Box(secretKey_py, publicKey_js)
data = box_py.decrypt(nonce + box_js)
print(data) # b'The quick brown fox jumps over the lazy dog'
In the example above, the keys have been imported. If a key pair needs to be generated, this is done with PyNaCl as follows:
from nacl.public import PrivateKey
secretKeyNew = PrivateKey.generate()
publicKeyNew = secretKeyNew.public_key
About compatibility:
TweetNaCl.js and PyNaCl are compatible. As you described, although PyNaCl is a wrapper of Libsodium for Python (s. here and here), but Libsodium itself is a port of NaCl (s. here), as is TweetNacl.js for JavaScript (here).
So ultimately, both TweetNaCl and PyNaCl are based on NaCl, the original library implemented by Bernstein et al., s. here, and are therefore compatible (except perhaps for a few minor syntactical differences).