试图用Java确定一个简单的解密算法

时间:2014-09-07 06:19:31

标签: java algorithm encryption modulo

我一直在努力为Java中的以下加密方法找出一个简单的解密算法:

/**
 * Returns the encryption of the given card number using the given keys.
 * Precondition: it can be assumed that cardNum is a valid numeric string,
 * k1 is a positive integer at most 9, and
 * k2 is a positive integer at most 9.
 * Postcondition: the string returned is the encryption of cardNum using keys
 * k1 and k2
 */
public static String encrypt (String cardNum, int k1, int k2) {

    int currentNum;
    long encryptedNum;
    String cryptogram = "";
    for (int i = 0; i < cardNum.length(); i++) {
        currentNum = Character.getNumericValue(cardNum.charAt(i));
        encryptedNum = (k1 * currentNum + k2) % 10;//the encryption algorithm
        cryptogram += encryptedNum;//add the encrypted number to the cryptogram
    }
    return cryptogram;
}

以前的加密方法用于加密最多16位数的信用卡号码,目的是创建一种方法来反转算法并检索原始卡号。

我也知道,对于k1k2的某些值,由于在加密结束时使用模10,因此没有可能的解密,因此它也是用于确定k1k2的哪些值可以解密的分配。然后,假设使用cardNumk1的有效值,编写一个解密k2的方法

以下是我设法使用decrypt方法获得的内容,而且我也无法确定k1k2的有效值是什么。

/**
 * Returns the decryption of the given cryptogram using the given keys.
 * Precondition: it can be assumed that cryptogram is a valid numeric string,
 * k1 is a valid first encryption key,
 * k2 is a valid second encryption key.
 * Postcondition: the string returned is the decryption of cryptogram
 * using keys k1 and k2
 */
public static String decrypt (String cryptogram, int k1, int k2) {

    int currentNum;
    long decryptedNum;
    String cardNum = "";
    for (int i = 0; i < cryptogram.length(); i++) {
        currentNum = Character.getNumericValue(cryptogram.charAt(i));
        decryptedNum = (currentNum - k2)/k1;//the decryption algorithm
        cardNum += decryptedNum;//add the decrypted number to the cardNum
    }
    return cardNum;
}

1 个答案:

答案 0 :(得分:1)

让我们从解密可能失败的原因入手。

  • 首先,可能存在一个实际问题,对于某些值k1k2理论上可以编写解密算法,但实际上所有已知的算法都会慢下来才有用。 (这种算法的一个例子是&#34;加密&#34;函数e(m,k)=SHA512(k||m),它接收任何16字节消息m,任何16字节密钥k并输出SHA512哈希值km的串联。我已经在连字符中加密,作为加密函数的条件是有效的解密函数。)剧透:你的功能不属于第一类。
  • 其次,解密某些值是不可能的。这可能发生,当使用相同的密钥k1,k2时,两条消息cardNum1cardNum2获得加密&#34;相同的值cryptogram。因此,在给定cryptogram和密钥后,您无法确定哪个值是原始值。这是你面临的问题。你想要达到的财产被称为&#34; injectivity&#34; (没有两个值映射到同一图像)。

现在,要实现的下一步是加密在逐个数字的基础上进行细分。因此,如果您对整个信用卡号的加密或解密有问题,那么当且仅当您遇到单个数字时才会显示。

您需要知道的另一个因素是模运算的重要特性。如果对于任何三个整数x,y,z有任何两个基本运算A和B(例如+和*),则以下标识成立:(x A y)B z%10 =((x A y)%10) B z%10。也就是说,您可以在每个步骤后应用模数计算,或者在结束时应用一次,结果将保持不变。例如(5 * 100%10)* 12%10 =(5 * 100)* 12%10。您甚至可以先减少每个模数10:5 * 100%10 = 5 *(100%10)%10 = 0

使用此功能,您可以反转部分加密功能:(k1 * currentNum) % 10 = (k1 * currentNum + k2 - k2) % 10 = (((k1 * currentNum + k2) % 10) - k2) % 10 = (encryptedNum - k2) %10

剩下要做的是反转乘法运算。这部分我想留给你。您已经可以猜测,对于k1的某些值,两个值currentNum1currentNum2将具有相同的结果(k1 * currentNum) % 10。作为(k1 * currentNum) % 10 = ((k1%10) * currentNum) % 10k1只有10个有趣的值。使用currentNum的每个可能值尝试其中的每一个。使用Java打印,10个数字的10个表应该是一个简单的任务。然后尝试找出那些k1currentNum s导致相同值的{{1}}相互具有共同点和10的内容。一旦你有预感,请查看Extended Euclidean Algorithm ,尤其是关于multiplicative inverses的部分。

相关问题