使用原始128 ASCII表使用仿射密码对字符串进行加密/解密

时间:2019-02-07 22:46:25

标签: java encryption ascii stringbuilder

因此,我正在尝试使用仿射密码对邮件进行加密。我想使用所有128个ASCII字符来做到这一点。关于特定字母Q,R,S,T和U,我遇到错误。它们无法正确转换回原位并显示不正确的解密。有什么想法吗?

加密的邮件

Sub ProtectSheetCheckSpellCheck()
'Update by Extendoffice 2018/11/2
Dim xRg As Range
On Error Resume Next
Application.ScreenUpdating = False
    With ActiveSheet
        .Unprotect ("Password123")
        Set xRg = .UsedRange
        xRg.CheckSpelling
        .Protect Password:="Password123", AllowInsertingRows:=True, AllowInsertingColumns:=True
    End With
Application.ScreenUpdating = True
End Sub

解密的邮件

RUX[^adgjmpsvy|

我的代码;

ABCDEFGHIJKLMNOP/.-,+VWXYZ

1 个答案:

答案 0 :(得分:3)

问题的原因是,对于负分红a和/或除数nmodulo operation的数学定义通常可能与相应编程语言中的定义不同。

模运算的结果在数学上定义为Euclidean division的其余部分。该余数始终大于或等于零。对于正除数n,余数由下式给出:

a mod n = a - n * floor(a/n) 

其中floor(a/n)floor-function,它给出的最大整数小于或等于其输入(我不认为负除数n是因为n = 128 > 0在问题)。

正除数n = 128(正分红a = 559(上)和负除数a = -559(下)的示例:

559 mod 128 = 559 - 128 * floor(559/128) = 559 - 128 * floor(4.37) = 559 -128 * 4 = 47
-559 mod 128 = -559 - 128 * floor(-559/128) = -559 - 128 * floor(-4.37) = -559 -128 * (-5) = 81

但是,在许多编程语言(包括Java)中,对模运算使用不同的定义(有时称为对称变量):

a mod n = a - n * trunc(a/n) 

此处,trunc(a/n)表示商a/n朝四舍五入的舍位除法。

正除数n = 128(正股息为a = 559(上)和负股息为a = -559(如下)的示例:

559 mod 128 = 559 - 128 * trunc(559/128) = 559 - 128 * trunc(4.37) = 559 -128 * 4 = 47      
-559 mod 128 = -559 - 128 * trunc(-559/128) = -559 - 128 * trunc(-4.37) = -559 -128 * (-4) = -47

正如人们所看到的,无论是数学定义还是对称定义,都为负红利提供了不同的结果。

此问题的直接原因是,仿射密码的公式中是 mathematical 定义,而在代码中使用了 symmetrical 变体(因为Java使用对称变体)。可以通过字母Q的示例很好地证明这一点:在您的代码中,字母Q(= 81 dec)是加密的(A = 3B = 15M = 128

(3 * 81 + 15) % 128 = 2

解密(A = 43B = 15M = 128)是

(43 * (2 - 15)) % 128 = -559 % 128

取决于模变量,对称变量和数学变量的结果分别为-4781(请参见上文)。由于代码中使用了对称变体,因此您会得到“错误”结果-47

因此,解决方案是将代码中的模运算转换为数学定义。这可以通过以下公式实现:

a mMod n  = ((a sMod n) + n) sMod n

其中mModsMod分别表示数学和对称模运算符。为此,定义一个新方法:

private static int mathematicalMod(int a, int n) {
    return ((a % n) + n) % n;
}

并替换为affineEncryption方法

encryption.append((char)((A * s.charAt(i) + B) % M));

使用

encryption.append((char)mathematicalMod(A * s.charAt(i) + B, M));

以及affineDecryption方法

decryption.append((char)((A * Math.abs((s.charAt(i) - B))) % M));

使用

decryption.append((char)mathematicalMod(A * (s.charAt(i) - B),  M));

请注意,在后一种替换中,Math.abs方法也被删除,因为它不属于affine-cipher-decrypt-algorithm

进行了这些更改,然后输入以下内容

StringBuilder s = new StringBuilder("AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0=1!2\"34$5%6&7/8(9)^`+*#'-_.:,;<>\\[]~{}|@");

控制台中的输出变为:

enter image description here

在Java中,还有一个对称变体的实现:int Math.floorMod(int a, int n),当然也可以代替自定义实现int mathematicalMod(int a, int n)使用。