RSA Decrypt Data
The mirror node, and why it says decryption failed
- private_key
- data
- label
- decrypted_data
RSA Decrypt Data takes ciphertext bytes and a private key and gives you plaintext bytes. That's it. The interesting part isn't the node, it's the fact that every way RSA decryption fails - wrong key, wrong padding, wrong hash, wrong label - fails the same loud way, and the node's error won't tell you which one it was.
Why you'd have a private key in a graph
The short answer: you're solving a puzzle, or you built the puzzle. The ComfyUI ARG Toolkit is AzelusLightvale's grab-bag of cryptography and steganography nodes for ARGs and secret-message workflows, and the RSA corner of it (ARG Toolkit/Cryptography/Modern/Asymmetric) is the "modern" half - pyca cryptography under the hood, as opposed to the classical-cipher nodes that wrap secretpy.
In a ComfyUI world where almost every node moves pixels or embeddings, this one moves bytes nobody can read without a secret. The realistic uses are narrow and that's fine: a challenge where an image hides a ciphertext and players have to find the key, or a private workflow where you keep one file of ciphertext around and only your key opens it.
The mechanism
Straight from the source: it builds a hash object from signature_algorithm, then calls private_key.decrypt(data, padding) with either OAEP or PKCS1v15. With OAEP, the padding object is constructed as OAEP(mgf=MGF1(algorithm), algorithm=algorithm, label=label), which is why the hash choice actually matters here - the same hash has to be used for the MGF1 mask generation and the digest.
The padding is also the integrity check. OAEP is a labelled construction with a built-in verification step, so tampered ciphertext raises instead of decrypting to noise. That's good cryptography and mildly annoying ergonomics: you get an exception, not partial output.
Inputs and the one output
private_key- typeKEYOBJ, forced input. Comes from RSA Private Key Bytes, which generates a fresh key and serializes it, or from RSA Private Numbers into Key if you're rebuilding one from its numeric parts.data- typeBYTESLIKE, forced input. Feed it from Bytes-like Object Encode (Hexadecimal or Base64 mode is what you want for a ciphertext you copy-pasted) or straight from the output of another crypto node.signature_algorithm- despite the name, this is the OAEP hash, not a signing hash.SHA256unless the ciphertext says otherwise.padding_alg-OAEP(default) orPKCS1v15. On the PKCS1v15 path the hash choice is ignored entirely; the source just passes plainPKCS1v15().label- optionalBYTESLIKE. OAEP's tag. Must be byte-identical to what the encryptor used.
Output: decrypted_data (BYTESLIKE). Send it to Bytes-like Object Decode to see it as text, hex or Base64.
The thing beginners miss about KEYOBJ: it's a live Python key object living in that run, not a file. There's nothing to save, and re-running the key-generation node mints a new key that won't decrypt anything you made five minutes ago. If the point is to keep a key, serialize it and store the bytes somewhere outside ComfyUI.
Install
ComfyUI Manager, search ComfyUI ARG Toolkit, install, restart, hard-refresh the browser. Or by hand:
cd ComfyUI/custom_nodes
git clone https://github.com/AzelusLightvale/ComfyUI-ARG-Toolkit
pip install -r requirements.txt
That requirements file is a fully pinned uv lock and it includes torch and torchaudio. Installing it into a working ComfyUI environment can swap your CUDA-enabled torch for a different pinned build, which is the kind of thing you discover twenty minutes later when every generation crawls. Manager is the safer route; if you install manually, verify torch afterwards. Nothing in this node needs a downloaded model.
Common issues
"Decryption failed" / a red node instead of text. RSA gives you one error for four different mistakes. Check in this order: is it the right private key (does the modulus match the public key you encrypted with)? Did you pick the same padding_alg? Same signature_algorithm? Did the encryptor use a label? Two minutes of matching settings beats twenty of guessing.
It decrypts to garbage. That basically cannot happen with OAEP - a wrong setup raises. If you're on PKCS1v15 and get plausible-looking junk, you've got the wrong key: PKCS1v15 has no integrity check, which is one of the good reasons to stay on OAEP in the first place.
The link won't connect. Both main inputs are forceInput with pack-only types. A plain string widget and a BYTESLIKE socket don't link, ever. Add the converter node.
Everything worked yesterday, nothing today. The key existed only in memory. Regenerating keys on each run is the pack's default behavior for the key nodes, so a graph that decrypts must persist its key material outside the graph. This is a small pack with a manual-testing testing story, so treat it as a puzzle tool rather than infrastructure.
Inputs (5)
| Name | Type | Default | Description |
|---|---|---|---|
| private_key | KEYOBJ | — | |
| data | BYTESLIKE | — | |
| signature_algorithm | COMBO | The hashing algorithm used for the signature. | |
| padding_alg | COMBO | OAEP | 2 options: OAEP, PKCS1v15 |
| labelopt | BYTESLIKE | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| decrypted_data | BYTESLIKE | — |