Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
4.1k views
in Technique[技术] by (71.8m points)

encryption - Assembly 8086 - Subtracting in x86

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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:

  • You have the result of the subtraction in DL and you want to divide that by 26, but you divide CX by 26 instead
  • You use the word-sized division, but forget to zero DX beforehand

Next 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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...