Vatsyayana Cipher

This cipher is sometimes referred to as the Karma Sutra cipher since that is where its first description appears. The name is of its supposed author. Dating to the 4th century, it is a substitution cipher where the cipher alphabet is constructed by pairing letters together and subtituting each one with its pair when enciphering.

Since this cipher is monoalphabetic, we can treat it as a subset of arbitrary letter substitution ciphers with 2 rules about the construction of the cipher alphabet,

  • RULE 1: The cipher letter cannot be the same as its plain equivalent.
  • RULE 2: The cipher letter and plain letter form a pair. If the letters 'A' & 'D' are paired, then 'D' is always substituted for 'A' and 'A' is always substituted for 'D'.

An example of a cipher alphabet for this cipher is,

PLAINABCDEFGHIJKLMNOPQRSTUVWXYZ
CIPHERYCBGNIDLFVXHREZQPMWUTJSKAO

Clearly, if we are working by hand, all we would need would be the letter pairs,

A Y
B C
D G
E N
F I
H L
J V
K X
M R
O Z
P Q
S W
T U

This cipher is its own inverse, re-encrypting cipher text restores the plain text. This makes the next section a little easier,

Programming The Cipher

You can use the exact same approach for this as with the arbitrary letter substitution cipher. As long as you have a valid string for the cipher alphabet, you're away.

cipherAlphabet ← "YCBGNIDLFVXHREZQPMWUTJSKAO"
plain ← "The secret is out."
upper ← UPPERCASE(plain)
cipherText ← ""
FOR letter ← 0 TO upper.LENGTH - 1
   tmpASC ← ASCII CODE OF upper[letter]
   IF tmpASC > = 65 AND tmpASC <= 90 THEN
      cipherText ← cipherText + cipherAlphabet[tmpASC-65]
   ELSE
      cipherText ← cipherText + upper[letter]
   END IF
END FOR
OUTPUT cipherText

You can get the user to input the letter pairs, and you'd want to do that if you were using the program to decrypt a message. A fancy user interface can guarantee you get a usable cipher alphabet string. Alternatively and, to help when developing programs, you will need to validate the cipher alphabet string. A number of things have to be true for the string to be valid.

  • There must be exactly 26 characters. There is no point checking anything else if this is not the case.
  • The string must consist only of upper case characters. You can check this with a FOR loop counting from 0 to 25. If the ASCII code of the character at the counter's position is not in the 65 - 90 range, then the string is not valid, you should exit the loop and stop checking further.
  • Every letter of the alphabet must appear exactly once in the string. You can use a loop and count from 65 to 90. CHR(loop counter) will provide you with access to each letter of the alphabet in turn. If the cipher string does not contain a letter, exit the loop and stop checking further.
  • None of the letters can be in its normal position in the alphabet. You can do this with a FOR loop counting from 0 to 25. Find the ASCII code of the character at that position and subtract 65. If the result is equal to the counter, a letter is in its normal place and you should exit the loop and stop checking further.

The letter pairs of the cipher are meant to be chosen at random. Pseudocode for creating a cipher string is written below,

plain ← "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
DECLARE STRING cipher[25]
FOR i ← 0 TO 25
   cipher[i] ← ""
END FOR
counter ← 0
WHILE plain.LENGTH > 0
   IF counter[i] = "" THEN
      plain ← plain.SUBSTRING(1, plain.LENGTH-1)
      cipher[counter] = plain[random integer less than plain.LENGTH]
      plain ← plain.REPLACE(cipher[counter], "")
      cipher[]ASC(cipher[counter])-65] ← CHR(counter + 65)
   END IF
   counter ← counter + 1
END WHILE
cipherAlphabet ← ""
FOR i &larr 0 TO 25
   cipherAlphabet ← cipherAlphabet + cipher[i]
END FOR