Skip to content

FEAT: Add VigenereConverter #2304

Description

@diamond8658

Is your feature request related to a problem? Please describe.

PyRIT's converter library includes several classical cipher converters — CaesarConverter (fixed single-letter shift), AtbashConverter (fixed substitution), and ROT13Converter (fixed 13-shift) — used to test model robustness against cipher-based obfuscation/jailbreak techniques. There is currently no converter for the Vigenère cipher, a well-known polyalphabetic cipher that generalizes Caesar by using a repeating keyword to vary the shift per character. Cipher-based prompting (asking a model to "decode" text encoded this way) is a documented jailbreak/evasion technique, and Vigenère is a natural, commonly-referenced addition alongside the existing single-shift ciphers.

Describe the solution you'd like

Add a VigenereConverter class to pyrit/converter/, following the same structure as CaesarConverter/AtbashConverter:

init(self, , key: str, append_description: bool = False) — validates key is non-empty and alphabetic.
_build_identifier() — returns a ComponentIdentifier with the key as a param.
convert_async(
, prompt, input_type) — encodes the prompt using the Vigenère cipher, with the same append_description behavior (rendering a vigenere_description.yaml seed prompt) as the Caesar/Atbash converters.
A private _vigenere(text: str) -> str helper implementing the per-letter keyed shift, preserving case and passing through non-alphabetic characters unchanged (matching Caesar's handling of digits/punctuation).
Unit tests mirroring tests/unit/converter/test_caesar_converter.py.
Export it from pyrit/converter/init.py and add it to the converters doc page alongside the other cipher converters.

Describe alternatives you've considered, if relevant

Could be implemented as a WordLevelConverter subclass instead (like ROT13Converter), but a full-prompt Converter matches Caesar/Atbash more closely since the key's position needs to track across the whole string, not reset per word.

Additional context

Happy to open a PR for this if it sounds like a good fit — I've contributed converter/loader work to PyRIT before (#1552, #1548) and this seems like a well-scoped follow-on.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions