Skip to main content

How to Implement a Simple Caesar Cipher in Batch Script

The Caesar cipher is one of the oldest and simplest encryption techniques. It is a substitution cipher where each letter in the plaintext is shifted a certain number of places down the alphabet. For instance, with a shift of 1, 'A' becomes 'B', 'B' becomes 'C', and so on. Understanding and implementing it in a Batch script is a classic exercise in algorithmic logic and string manipulation.

In this guide, we will demonstrate how to build an interactive Caesar cipher encoder and decoder in Batch.

The Strategy: Alphabet Arrays and Index Shifting

Native Batch scripts do not have a built-in .indexOf() function for strings. To build a Caesar cipher:

  1. Define the alphabet sequence as a string.
  2. Accept a numeric shift key from the user (e.g., 3).
  3. Loop through the input string character by character.
  4. For each character, find its position in the alphabet string.
  5. Apply the shift key, handle wrap-around (using modulo arithmetic), and retrieve the new character.
  6. Append it to the output string.

Implementation Script

@echo off
setlocal EnableDelayedExpansion

:: 1. Ask for input
set /p "userInput=Enter text to encrypt: "
set /p "shiftKey=Enter shift number (e.g., 3): "

:: Define the alphabet maps (both upper and lower cases)
set "charsLower=abcdefghijklmnopqrstuvwxyz"
set "charsUpper=ABCDEFGHIJKLMNOPQRSTUVWXYZ"

set "output="
set "idx=0"

:: 2. Determine input string length
call :string_length "%userInput%" len

:: 3. Process each character
set /a "lastIdx=len - 1"
for /l %%A in (0,1,!lastIdx!) do (
set "currentChar=!userInput:~%%A,1!"
set "matched=0"

:: 4. Search in Lowercase Alphabet
for /l %%B in (0,1,25) do (
if "!currentChar!"=="!charsLower:~%%B,1!" if "!matched!"=="0" (
:: Calculate new index with modulo 26 for wrap-around
set /a "newIndex=((%%B + shiftKey) %% 26 + 26) %% 26"

:: Append shifted character
for %%N in (!newIndex!) do set "output=!output!!charsLower:~%%N,1!"
set "matched=1"
)
)

:: 5. Search in Uppercase Alphabet
if "!matched!"=="0" (
for /l %%B in (0,1,25) do (
if "!currentChar!"=="!charsUpper:~%%B,1!" if "!matched!"=="0" (
set /a "newIndex=((%%B + shiftKey) %% 26 + 26) %% 26"

for %%N in (!newIndex!) do set "output=!output!!charsUpper:~%%N,1!"
set "matched=1"
)
)
)

:: 6. If not a letter (space, number, punctuation), keep original
if "!matched!"=="0" (
set "output=!output!!currentChar!"
)
)

echo.
echo ==========================================
echo ORIGINAL: !userInput!
echo SHIFT : !shiftKey!
echo RESULT : !output!
echo ==========================================
pause
exit /b

:string_length
:: Usage: call :string_length "string" variableName
setlocal
set "s=%~1"
set "sLen=0"
if defined s (
for /l %%I in (0,1,8191) do (
if not "!s:~%%I,1!"=="" (set /a "sLen+=1") else (goto :doneLen)
)
)
:doneLen
endlocal & set "%2=%sLen%"
exit /b

How It Works

  1. Modulo Arithmetic: The core logic lies in set /a "newIndex=((%%B + shiftKey) %% 26 + 26) %% 26". The double-modulo pattern ((x % 26) + 26) % 26 ensures the result is always a positive index between 0 and 25, regardless of whether the intermediate value is negative.
  2. Negative Shifts (Decryption): The script works for decryption as well. If you provide a negative shift value (e.g., -3), the double-modulo expression correctly wraps backwards through the alphabet in a single step.
  3. Character Preservation: The script loops 26 times to find a match. If a match is completely missed (because the character is a space, comma, or number), that character is appended as-is.
  4. Match Guard: The if "!matched!"=="0" check on the same line as the character comparison prevents a character from being shifted multiple times when matching successive alphabet positions within the inner loop.

Simplifying with a PowerShell Bridge

Batch is notorious for its sluggish character-by-character loops. For encrypting huge log files, using PowerShell's native object array iteration is thousands of times faster.

warning

The PowerShell bridge passes user input directly into a command string. Avoid using characters that break quoting (such as single quotes, double quotes, backticks, or dollar signs) in the input text, or add proper escaping for production use.

@echo off
setlocal EnableDelayedExpansion

set /p "str=Enter string: "
set /p "shift=Enter shift: "

:: Build the PowerShell command separately for readability
set "psCmd=$s='%str%';"
set "psCmd=!psCmd! $k=%shift%;"
set "psCmd=!psCmd! $arr=$s.ToCharArray();"
set "psCmd=!psCmd! for($i=0;$i -lt $arr.Length;$i++){"
set "psCmd=!psCmd! [int]$c=$arr[$i];"
set "psCmd=!psCmd! if($c -ge 97 -and $c -le 122){"
set "psCmd=!psCmd! $arr[$i]=[char]((($c-97+$k)%%26+26)%%26+97)"
set "psCmd=!psCmd! } elseif($c -ge 65 -and $c -le 90){"
set "psCmd=!psCmd! $arr[$i]=[char]((($c-65+$k)%%26+26)%%26+65)"
set "psCmd=!psCmd! }"
set "psCmd=!psCmd! };"
set "psCmd=!psCmd! -join $arr"

:: Delegate to PowerShell
for /f "delims=" %%I in ('powershell -NoProfile -Command "!psCmd!"') do set "encoded=%%I"

echo Result: !encoded!
pause

Why Implement a Caesar Cipher?

  1. Computer Science Fundamentals: It serves as an exceptional training ground for understanding arrays, indices, bounds checking, and integer wrap-around.
  2. Basic Data Masking: While not cryptographically secure, applying a cipher to a text file prevents casual end-users from reading connection strings or API tokens in plain-text at first glance.
  3. Puzzle Generation: Creating automated riddles and geocaching clues locally over an entire directory of text files for a team-building exercise.

Conclusion

Building a Caesar Cipher demonstrates advanced control flow string manipulation within Windows Batch. Dealing with character positioning, simulating arrays via substrings, and using modulo arithmetic builds a formidable foundation for writing more sophisticated data-transformation scripts. While it won't stop a dedicated hacker, the Caesar cipher remains an elegant tool for basic text obfuscation.