问题描述
我正在开发一个使用 Vigenère 密码加密/解密数据的程序。除了解密部分,一切都很好。
加密和计算密钥背后的逻辑是:
-
输入:“qwerty”
-
Key : "asd" = 计算出的键是 "asdasd"
-
密码:“catdxn”
-
对于加密,我使用以下算法:
-
结果[i] = (输入[i]+key[i]) % 26
-
结果[i] += 3dH ;转换为asci数
-
密码[i] += 结果[i] 问题在于解密:
解密算法应该是
-
结果[i] = (INPUT[i] - KEY[i]) % 26
-
IN CASE INPUT[i] - KEY[i] = NEGATIVE NUMBER = 添加 26,所以公式变为
-
结果[i] = (INPUT[i] - KEY[i] + 26)% 26
-
结果[i] += 3dH
-
密码[i] += 结果[i] ;获取结果字符串
预期的结果应该是“qwerty”,但我得到的是“usgtrm”。
;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
问题在于减去数字,我对这个主题完全是菜鸟。 让我们说“catdxn”这个词。 63、61、74、64、78、6E 和关键 'asdasd' 61,73,64,61,64 在第二次迭代中,我们有 61 - 73 ( SUB DL,CL ) = 结果是 FFFF FFFF FFFF FFEE 或 - 18。 发生这种情况时,我需要将 26 添加到结果中,但我无法理解: SUB DL,CL STORES IN DL = EE 的结果这是十进制的 238,我如何添加 26 十进制或 (1A Hex) 到一个正数......它应该是'61h - 73h = -18d + 26d 或 1Ah = 8'。可能真的错了。
解决方法
问题在于解密
没有。连加密都错了!正如 Jester 所指出的,您正在使用 ASCII 代码,您应该使用字母表中字母的偏移量 [0,25]。
这是原始的 Vigenère 编码,减去/添加 97 来转换小写字母:
CIPHER[i] = ((INPUT[i]-97 + KEY[i]-97) % 26) + 97
INPUT : "qwerty"
KEY : "asdasd"
CIPHER : "qohrlb"
解密算法应该是
RESULT[i] = (INPUT[i] - KEY[i]) % 26
如何使用 INPUT 进行解密?这就是解密试图找出的东西!
您当前代码中的一些错误包括:
- 您在
DL
中有减法的结果,您想将其除以 26,但您改为将CX
除以 26 - 您使用字大小的除法,但忘记事先将
DX
归零
接下来使用字节大小的除法可以纠正以下几个错误:
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
为什么你认为加上 3Dh(十进制 61)会产生 ASCII ?
您当前的加密是这样做的:
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" ???
我不知道您从哪里获得密码。难道你把数字 63、61 和 64 解释为十六进制?那些确实代表“c”、“a”和“d”。
关于减法本身的问题。这完全取决于您如何查看编码后的数字。如果 DL
包含位模式 11101110b (EEh) 并且您以无符号方式查看它,那么它代表 238,但如果您以有符号方式查看它 ,那么它代表-18。
只需将其视为有符号数字并添加所需的 26。您最终会得到一个范围为 [0,25] 的数字。
sub dl,cl ; DH = 0
jns IsPositive
add dl,26
IsPositive:
mov ax,dx ; Store in AX the result of subtracting