Nodes/ComfyUI ARG Toolkit/RSA Public Key Bytes
ComfyUI Node

RSA Public Key Bytes

One mode throws the private half away

By AzelusLightvale·Created about a year ago·Updated a day ago· 2
RSA Public Key Bytes
  • serialized_key
  • key_object
  • public_key
  • public_numbers
◄key_sourceFresh Key►
◄encodingPEM►
◄formattingSubjectPublicKeyInfo►
◄fresh_key_size2048►
◄public_exponent65537►

Everyone remembers to generate the private key. Almost nobody wires up the public one, and then the verification node returns false forever and they assume the signer is broken. If you're signing images or messages in ComfyUI, this is the node that produces the half you publish - and it has one mode you should probably never use.

What it's for

An RSA signature is only useful if someone can check it without holding your private key. That's the whole point: you sign with the private half and hand out the public half so anyone can confirm the message wasn't touched. In ComfyUI ARG Toolkit, this is what RSA Signature Verification wants, and what you'd paste next to a puzzle image so a solver can prove they found the real clue.

How it works

The mechanism is quieter than the name suggests. Depending on key_source, the node either calls rsa.generate_private_key(...) itself and takes .public_key() off the result, or accepts a private key object you hand it and derives the public half. Either way only the public part gets serialized, via public_bytes(encoding, format).

Which is the catch worth saying out loud: "Fresh Key" mode generates a private key, keeps it just long enough to compute the public one, then discards it. The keypair exists; you only get the half you can't sign with, so a sign-then-verify loop built entirely on this node can never succeed. Use Fresh Key for a plausible key to publish - an ARG prop, a decoy - and "From Loaded Key" for everything real.

In that second mode, the serialized_key input must be a private key object. The source checks isinstance(serialized_key, rsa.RSAPrivateKey) and throws "Missing private keys for RSA public key generation." otherwise, so feeding it a PEM Serialized Public Key Loader output - the intuitive move - fails. Valid sources are key_object from RSA Private Key Bytes, an RSA Private Numbers into Key output, or a private key loader (PEM/DER/OpenSSH, all of which take the key's bytes on keyfile, not a file path).

The inputs that matter

  • key_source - "Fresh Key" or "From Loaded Key". Note the tooltips mention "From Fresh Key"; the actual enum value is "Fresh Key". Mirror-image of the usual confusion, no functional harm.
  • formatting - SubjectPublicKeyInfo (default) gives the standard BEGIN PUBLIC KEY block that OpenSSL, Python, Node and everything else reads. PKCS1 gives the older BEGIN RSA PUBLIC KEY block. Pick it only if the other end demands it; both are RSA-specific anyway, so PKCS1 buys compatibility and nothing more.
  • encoding - PEM (text, wraps nicely) or DER (raw bytes).
  • fresh_key_size and public_exponent - both are labelled as applying only in Fresh Key mode, and they genuinely are ignored otherwise. Wire them, leave them, doesn't matter.

Outputs mirror the private node: key_object (KEYOBJ, goes straight into the verifier or RSA Encrypt Data), public_key (BYTESLIKE, the serialized bytes you'd decode to text and share), and public_numbers (NUMOBJ, the n and e as integers - feed it to RSA Public Numbers Values if you need to print the modulus, or to reconstruct a key from numbers you were handed).

The workflow you actually want

Private key node → key_object → this node in "From Loaded Key" → key_object → verifier. Same private key object you gave the signer. The derivation is deterministic, and that's exactly the property that makes verify return true instead of quietly lying.

Installing

Manager: search ComfyUI ARG Toolkit, install, restart. Manual:

cd ComfyUI/custom_nodes
git clone https://github.com/AzelusLightvale/ComfyUI-ARG-Toolkit

Then install only what's missing. The repo's requirements.txt is a uv lockfile pinning torch==2.14.1 and torchaudio==2.11.0; run it against a live ComfyUI environment and you risk replacing the torch you built CUDA against. These nodes need cryptography and nothing else:

pip install cryptography

The pack also declares Python >=3.12, and its __init__.py imports every module in src/ eagerly - miss stegano or invisible-watermark and the whole pack fails to load, so you see no ARG Toolkit nodes at all, not just a missing one. The traceback names the culprit.

When it goes wrong

Missing private keys for RSA public key generation - you fed it a public key (or nothing at all) while in "From Loaded Key". Switch source or wire the private object.

Verifier says false - check which public key you derived from. A Fresh Key public key verifies nothing.

Garbled PEM after decoding - encoding here and the decode mode on Bytes-like Object Decode are unrelated axes. DER bytes decoded as UTF-8 give replacement characters; base64 them instead.

This is a solo-authored, WIP corner of a niche pack, so there's no crowd-sourced answer key when it misbehaves - the source is about sixty lines and is the real documentation.

CategoryARG Toolkit/Cryptography/Modern/Asymmetric

Inputs (6)

NameTypeDefaultDescription
key_sourceCOMBOFresh KeyThe source of the private key to be used to sign the message
encodingCOMBOPEM2 options: PEM, DER
formattingCOMBOSubjectPublicKeyInfo2 options: SubjectPublicKeyInfo, PKCS1
serialized_keyoptKEYOBJOnly applicable if key_source is `From Loaded Key`.
fresh_key_sizeoptINT2048512–8192Only applicable if key_source is `From Fresh Key`.
public_exponentoptINT655371–4294967296Only applicable if key_sourcce if `From Fresh Key`.

Outputs (3)

NameTypeDescription
key_objectKEYOBJ—
public_keyBYTESLIKE—
public_numbersNUMOBJ—