使用原始128 ASCII表使用仿射密码对字符串进行加密/解密 [英] Encrypting/Decrypting a string using a Affine cipher using the original 128 ASCII table

查看:103
本文介绍了使用原始128 ASCII表使用仿射密码对字符串进行加密/解密的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

So I am trying to encrypt a message using an affine cipher. I want to use all 128 ASCII characters to do it. I am getting an error when it comes to particular letters, Q, R, S, T, and U. They are not converting back correctly and displaying the incorrect decryption. Any ideas what is going on?

加密的邮件

RUX[^adgjmpsvy|

解密的邮件

ABCDEFGHIJKLMNOP/.-,+VWXYZ

我的代码;

public class EncryptionProject {

   public static void main(String[] args) {

        StringBuilder s = new StringBuilder("ABCDEFGHIJKLMNOPQRSTUVWXYZ");

        System.out.println("Encrypted Message");
        StringBuilder encryptedMessage = affineEncryption(s);
        System.out.print(encryptedMessage);

        System.out.println("\nDecrypted Message");
        StringBuilder decryptedMessage = affineDecryption(encryptedMessage);
        System.out.print(decryptedMessage);
    }

    /* use affine cipher to encrypt message */
    public static StringBuilder affineEncryption(StringBuilder s) {
        StringBuilder encryption = new StringBuilder();
        final int A = 3, B = 15, M = 128; // a * p + b (mod m)

        /* loop through string and compute affine cipher */
        for (int i = 0; i < s.length(); i++) {
            encryption.append((char)((A * s.charAt(i) + B) % M));
        }

        return encryption;
    }

    /* decryption method */
    public static StringBuilder affineDecryption(StringBuilder s) {
        final int A = 43, B = 15, M = 128;
        StringBuilder decryption = new StringBuilder();

        /* loop through and undo affine cipher using inverse of A */
        for (int i = 0; i < s.length(); i++) {
            decryption.append((char)((A * Math.abs((s.charAt(i) - B))) % M));
        }

        return decryption;
    }
}

推荐答案

问题的原因是,对于负股息a和/或除数n

The cause of the problem is that for negative dividends a and/or divisors n the mathematical definition of the modulo operation generally may differ from the definition in the respective programming language.

模运算的结果在数学上定义为欧几里得除法的余数. .该余数始终大于或等于零.对于正除数n,余数由下式给出:

The result of the modulo-operation is mathematically defined as the remainder of the Euclidean division. That remainder is always larger than or equal to zero. For positive divisors n the remainder is given by:

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

其中floor(a/n) floor-功能,它可以提供最大的输出小于或等于其输入的整数(我不考虑负除数n,因为问题中的n = 128 > 0).

where floor(a/n) is the floor-function which gives as output the greatest integer less than or equal to its input (I don't consider negative divisors n since n = 128 > 0 in the question).

正数除数n = 128的正数除法a = 559(上方)和负数除数a = -559(以下)的示例:

Examples for a positive divisor n = 128 with a positive dividend a = 559 (above) and a negative dividend a = -559 (below):

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)中,对模运算使用了不同的定义(有时称为对称变量):

However, in many programming languages (including Java) a different definition for the modulo-operation (sometimes referred to as symmetrical variant) is used:

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

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

Here, trunc(a/n) means the truncated division where the quotient a/n is rounded towards zero.

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

Example for a positive divisor n = 128 with a positive dividend a = 559 (above) and a negative dividend a = -559 (below):

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

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

As one can see, both definitions, the mathematical and the symmetrical, provide different results for negative dividends.

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

The immediate cause of the problem is that in the formula of the affine cipher, the mathematical definition is meant whereas in your code the symmetrical variant is used (because Java uses the symmetrical variant). This can be nicely demonstrated by the example of the letter Q: In your code the letter Q (= 81 dec) is encrypted (A = 3, B = 15, M = 128) to

(3 * 81 + 15) % 128 = 2

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

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

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

Depending on the modulo variant the result is -47 and 81 for the symmetrical and the mathematical variant, respectively (see above). Since the symmetrical variant is used in the code you get the "wrong" result -47.

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

Thus, the solution is to switch the modulo operation in your code to the mathematical definiton. This can be achieved by the following formula:

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

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

where mMod and sMod denote the mathematical and symmetrical modulo-operator, respectively. For this, define a new method:

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-方法也被删除,因为它不属于

Note, that in the latter replacement also the Math.abs-method is removed since it doesn't belong to the affine-cipher-decrypt-algorithm .

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

With those changes, and the following input

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

控制台中的输出变为:

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

In Java there is also an implementation of the symmetrical variant: int Math.floorMod(int a, int n) which, of course, can also be used instead of the custom implementation int mathematicalMod(int a, int n).

这篇关于使用原始128 ASCII表使用仿射密码对字符串进行加密/解密的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆