Take the 2-minute tour ×
Cryptography Stack Exchange is a question and answer site for software developers, mathematicians and others interested in cryptography. It's 100% free, no registration required.

I wrote a simple python script to preform one time pad encryption I would like to be able to decrypt the ciphertext by hand. In my script I use mod 26.

This is how I was shown to calculate a mod using a calculator:

  • 467%26 = 25
  • 467/26 = 17.9615...
  • 17*26=442
  • 467-442=25

I used this code to preform the one time pad in my script

ciphertext = plaintext+key%26
plaintext =  ciphertext-key%26

I’m using CT-46 to convert letters to numbers

-----------------------------------------------------
|  A    E    I    N    O    R    |      CT-46       |
|  1    2    3    4    5    6    |                  |
|---------------------------------------------------|
|  B    C    D    F    G    H    J    K    L    M   |
|  70   71   72   73   74   75   76   77   78   79  |
|---------------------------------------------------|
|  P    Q    S    T    U    V    W    X    Y    Z   |
|  80   81   82   83   84   85   86   87   88   89  |
|---------------------------------------------------|
|  SPC  .    ,    :    ?    /    (    )    "  CODE  |
|  90   91   92   93   94   95   96   97   98   99  |
|---------------------------------------------------|
|  0    1    2    3    4    5    6    7    8    9   |
|  00   01   02   03   04   05   06   07   08   09  |
-----------------------------------------------------
  • plaintext = tavares -> CT-46 chart-> 83,1,85,1,6,2,82
  • the key is 48,5,03,1,9,3,25
  • ciphertext = 105,6,88,2,15,5,107

To decrypt the ciphertext you would do this in python:

105-48%26 = 83 that is T on the CT-46 chart 

Now if I try to decrypt by hand using a calculator, this is what I get:

  • 105-48=57
  • 57/26 = 2.1923076923076923076923076923077
  • 2*26=52
  • 57-52=5

The Difference should be 83, not 5. What is it that I'm doing wrong ?

share|improve this question

3 Answers 3

up vote 1 down vote accepted

a bit of history

Historically, one-time pads written on paper were almost invariably one of two types: "alphabetic" or "decimal". CT-46 is one type of straddling checkerboard encoding -- but CT-46 assumes you are using a decimal one-time pad.

  • Alphabetic ("base 26"): the key pad has groups of 5 alphabetic letters 'A' through 'Z'. Using these pads requires using "modulo 26". Each letter on an alphabetic key pad should be generated with a 1/26 chance to be any particular letter.
  • Decimal ("base 10"): The key pad has groups of 5 decimal digits '0' through '9'. Using these pads requires using "modulo 10". Decimal one-time pads also require some "encoding" for converting each letter in the message into decimal digits. Each digit on a decimal key pad should be generated with a 1/10 chance to be any particular digit.

The "/dev/random" is a good source of random values that you can convert into a one-time pad -- a series of alphabetic letters -- or a series of decimal digits. My understanding is that python uses that source for ssl.RAND_bytes() and uuid.uuid4() and os.urandom() and a few other functions. Historically, many people have been tricked into using a so-called "random" function that is completely inappropriate for generating one-time pads, such as RANDU.

Your choice

You must choose some base. Either base 10 (decimal) or base 26 (alphabetic) work great for one time pads. In principle, you could pick any base. However -- as you have seen -- mixing both CT-46 (i.e., decimal) and also base-26 creates an incompatible mixture that doesn't work. It only seems to work for the first letter because another bug involving operator precedence cancels out that problem in the first letter, as described by Ilmari Karonen. Fix that bug by adding more parenthesis: change

plaintext = ciphertext-key%26

to

plaintext = (ciphertext-key)%26

When two bugs cancel each other out like this -- that can be difficult to fix.

You might consider starting by writing one program to do alphabetic one-time pads (this is easier to write and debug), and once that is working, re-using most of that program in a separate program that uses CT-46 encoding (which adds some complexity).

I'm mystified as to how the value "48" got into your key?

Alphabetic

 t  a  v  a  r  e  s  : plaintext
20  1 22  1 18  5 19  : standard A-->1, B-->2, C-->3, etc. encoding.
48  5  3  1  9  3 25  : key ("48"? where did that come from?)
68  6 25  2 27  8 44  : sum
16  6 25  2  1  8 18  : sum modulo 26
 p  f  y  b  a  h  r  : standard A-->1, B-->2, C-->3, etc. encoding.  
 pfyba  ahr           : ciphertext

straddling checkerboard

On a hand calculator, modulo 10 is much easier than modulo 26: I simply read last digit -- the digit in the one's place. I ignore all the other digits -- the digit in the 10's place, the 100's place, etc. (Modulo with negative numbers is a bit more complex).

encoding:

 t    a  v  a  r  e  s  : plaintext
 83   1 85  1  6  2 82  : CT-46 chart encoding.
 8  3 1 8 5 1  6 2  8 2 : split into individual digits
 4  8 5 0 3 1  9 3  2 5 : key (also individual digits)
12 11 6 8 8 2 15 5 10 7 : sum
 2  1 6 8 8 2  5 5  0 7 : sum modulo 10
 21688 25507            : ciphertext

decoding:

 21688 25507            : ciphertext
 2  1  6  8  8  2  5  5  0  7 : split into individual digits
 4  8  5  0  3  1  9  3  2  5 : key (also individual digits)
-2 -7  1  8  5  1 -4  2 -2  2 : difference
 8  3  1  8  5  1  6  2  8  2 : difference modulo 10
  83   1   85   1  6  2   82  : pair up in the CT-46 style
  T    A   V    A  R  E   S   : CT-46 chart decoding
share|improve this answer

In modular calculations such as this, the divisor (in your case 26) must be at least the size of your character code space. Your code space is 46 characters, so that is not going to work.

Any output of the modular calculation will be less than the divisor, so you will never get 83 for x mod 26, it is not going to happen. For a 46 character code space, 46 is the appropriate divisor.

Also the code space for your message characters is inconsistent, 06 codes to both "6" and "R". 92 will also code the same as 00 mod 46, so your code book values will never work. They must all be unique mod 46.

You have even more problems with your key and ciphertext. There was no modular calculation in generating your ciphertext, or all values would be less than 26. I also have no idea how you got 83+48=105, and 48 is once again outside the code space.

share|improve this answer
    
ok i see what when wrong with the code space I was using A = 0 B = 1 C = 2 ....... using mod 26 when i wrote the script –  user13120 Apr 19 at 13:10
    
So what do i need to change the codebook and what else ? –  user13120 Apr 19 at 13:26
    
@user13120 : $\:$ You need to put in parentheses. $\;\;\;\;$ –  Ricky Demer Apr 19 at 15:52

Your calculator is correct: $$105-48 = 57 \equiv 5 \pmod{26}.$$

Your Python code, however, calculates 105 - 48 % 26, which Python, due to its operator precedence rules, evaluates as 105 - (48 % 26) = 105 - 22 = 83.

To get the correct remainder modulo 26, you need to add parentheses to your Python code so that it reads (105 - 48) % 26 instead. This will return the correct answer 5. In any case, it's obvious that 83 cannot be the correct remainder modulo 26, since it is greater than the modulus!

Of course, to get your encryption working (in the sense that it can be correctly decrypted), you'll also need to fix the issue pointed out by Richie Frame: if your alphabet has 46 symbols, you'll need to use a modulus of at least 46 in your modular arithmetic, or you'll end up encrypting several plaintext symbols to the same ciphertext symbol.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.