I'm working on a program to encrypt / decrypt data using the Vigenère Cipher. All is well except the decrypt part.
The logic behind the encryption and to compute the key is:
INPUT : "qwerty"
Key : "asd" = The computed key is "asdasd"
CIPHER: "catdxn"
For encrypting I use the following algorithm:
RESULT[i] = (INPUT[i]+key[i]) % 26
RESULT[i] += 3dH ; to transform to asci number
CIPHER[i] += RESULT[i] The problem is at decrypt:
The decrypt algorithm should be
RESULT[i] = (INPUT[i] - KEY[i]) % 26
IN CASE INPUT[i] - KEY[i] = NEGATIVE NUMBER = add 26 so the formula changes to
RESULT[i] = (INPUT[i] - KEY[i] + 26 ) % 26
RESULT[i] += 3dH
CIPHER[i] += RESULT[i] ; Get the result String
The expected result should be "qwerty" but I'm getting "usgtrm".
So following the algorithm described above I have the following code:
;inputKey = KEY,
;inputWORD = Input,
;cipherText = Result
;inputWORDLENGTH = length of input = CX
XOR DI,DI
vigDECLOOP:
cmp di,cx
JNB DONELOOPDEC
PUSH CX
mov si, offset inputWORD
ADD SI,DI
XOR DX,DX
MOV DL, DS:[SI] ; DL = INPUT[I]
xor SI,SI
MOV SI, OFFSET inputKEY
ADD SI, DI
XOR CX,CX
MOV CL, DS:[SI] ; CL = KEY[I]
SUB DL, CL
; ========
; Here in case is negative number I somehow need to add 26 to DL (result of DIV )
; IT 2: 61- 73 = EE in DL and should be -18, I know is something about the signed bit
; but I dont know what to read and where about this.
; ========
mov ax, cx ; Store in AX the result of subtracting
mov bx, 26 ; add in bx 26
div bx ; To obtain the reminder from % 26
; ========
; ========
add dl, 3Dh ; add 3dH to DL(reminder of DIV) to get the asci
xor si,si
mov si, offset cipherText
add si,di
xor dh,dh
add dl, DS:[si]
mov DS:[si],dl
INC DI
POP CX
jmp vigDECLOOP
DONELOOPDEC:
RET
The problem is at subtracting numbers and I'm totally noob on this subject. Let's say for the word "catdxn". 63, 61, 74, 64, 78, 6E AND THE KEY 'asdasd' 61, 73, 64, 61, 73, 64 At the 2'nd Iteration we have 61 - 73 ( SUB DL, CL ) = The result is FFFF FFFF FFFF FFEE or - 18. When this happens I need to add 26 to the result but I cant put my head to understand: The result of SUB DL, CL STORES IN DL = EE And this is 238 in decimal, how can I add 26 decimal or (1A Hex) to a number that is positive... it should be '61h - 73h = -18d + 26d or 1Ah = 8'. Could be really wrong about it.
The problem is at decrypt
No. Even the encryption is wrong! As Jester noted, you're working with ASCII codes where you should be working with the offsets [0,25] of the letters in the alphabet.
This is the original Vigenère encoding, subtracting/adding 97 to convert from/to lowercase letters:
CIPHER[i] = ((INPUT[i]-97 + KEY[i]-97) % 26) + 97
INPUT : "qwerty"
KEY : "asdasd"
CIPHER : "qohrlb"
The decrypt algorithm should be
RESULT[i] = (INPUT[i] - KEY[i]) % 26
How can decryption even be using the INPUT? That's what decryption is trying to find out!
Some errors in your current code include:
DL
and you want to divide that by 26, but you divide CX
by 26 insteadDX
beforehandNext use of the byte-sized division corrects these few errors:
sub dl, cl
mov ax, dx ; Store in AX the result of subtracting
mov bl, 26
div bl ; To obtain the reminder from % 26
add ah, 3Dh ; add 3Dh to AH (remainder of DIV) to get the ascii
mov si, offset cipherText
add si, di
add [si], ah
Why do you think that adding 3Dh (61 in decimal) produces ASCII ?
Your current encryption does this:
113 119 101 114 116 121 INPUT[] : "qwerty"
97 115 100 97 115 100 KEY[] : "asdasd"
--- --- --- --- --- ---
210 234 201 211 231 221 INPUT[]+KEY[]
2 0 19 3 23 13 (INPUT[]+KEY[]) % 26
cipher 63 61 80 64 84 74 (INPUT[]+KEY[]) % 26 + 3Dh
? = P @ T J CIPHER[] : "catdxn" ???
I don't see where you get your CIPHER from. Could it be that you interpret the numbers 63, 61, and 64 as hexadecimals? Those do represent "c", "a", and "d".
And for the question about subtraction itself. It all depends on how you look at the encoded number. If DL
contains the bitpattern 11101110b (EEh) and you look at it the unsigned way, then it represents 238, but if you look at it the signed way, then it represents -18.
Just treat it as a signed number and add the required 26. You'll end up with a number in range [0,25].
sub dl, cl ; DH = 0
jns IsPositive
add dl, 26
IsPositive:
mov ax, dx ; Store in AX the result of subtracting