【问题标题】:Vigenère cipher implementation维吉尼亚密码实现
【发布时间】:2013-10-02 18:16:02
【问题描述】:

我必须实现Vigenère cipher 的变体。我得到了加密部分没有问题,但我在解密代码中有一个错误,我不明白我做错了什么。

要求是:

  • 密钥只能包含A - Z(大写)

  • 关键字符的代码值为 A 为 0,B 为 1,...,Z 为 25

  • 如果代码为

  • 加密字符码=原始字符码+关键字符码

  • 最终加密字符必须介于 32 和 126 之间,因此如果最终加密字符 > 126,则必须通过将值加上 32 然后减去 126 将其带回到 32 - 126 范围内

加密代码:

// it works ok
// I have tested it with some provided strings and the results are as expected

public String encrypt(String plainText)
{
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < plainText.length(); i++) {
        char c = plainText.charAt(i);
        if (c >= 32) {
            int keyCharValue = theKey.charAt(i % theKey.length()) - 'A';
            c += keyCharValue;
            if (c > 126) {
                c = (char) (c + 32 - 126);
            }
        }
        sb.append(c);
    }
    return sb.toString();
}

解密代码:

// there probably is an off-by-one error somewhere
// everything is decrypted ok, except '~' which gets decrypted to ' ' (space)

public String decrypt(String cipherText)
{
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < cipherText.length(); i++) {
        char c = cipherText.charAt(i);
        if (c >= 32) {
            int keyCharValue = theKey.charAt(i % theKey.length()) - 'A';
            c -= keyCharValue;
            if (c < 32) {
                c = (char) (c + 126 - 32);
            }
        }
        sb.append(c);
    }
    return sb.toString();
}

示例(带有密钥ABCDEFGHIJKLMNOPQRSTUVWXYZ):

  • ~~~~~~~~~~~~~~~~~~~~~~~~~~

  • 加密~!"#$%&amp;'()*+,-./0123456789

  • 已解密 ~('~' 后跟空格)

编辑:

这是我用于测试的代码(它测试从 0 到 126 的每个字符作为字符串重复):

public static void main(String[] args) {
    int passed = 0;
    int failed = 0;
    String key = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    for (int c = 0; c <= 126; c++) {
        StringBuilder sbString = new StringBuilder();
        for (int i = 0; i <= 25; i++) {
            sbString.append((char) c);
        }
        String original = sbString.toString();
        Cipher cipher = Cipher(key);
        String encrypted = cipher.encrypt(original);
        String decrypted = cipher.decrypt(encrypted);
        if (!original.equals(decrypted)) {
            failed++;
            System.out.println("--FAILED--");
            System.out.println(original);
            System.out.println(encrypted);
            System.out.println(decrypted);
        } else {
            passed++;
        }
    }
    int tests = passed + failed;
    System.out.println(tests + " tests");
    System.out.println("passed: " + passed);
    System.out.println("failed: " + failed);
}

【问题讨论】:

  • @Pratik 好像是大写字母。
  • 您好,我运行了上述方法并且它工作正常......我正在从解密方法中获取原始消息。
  • 32-126 独占范围意味着 ~ 不是允许的结果。您的意思是包容性吗?

标签: java algorithm encryption vigenere


【解决方案1】:

我认为解密中的 If(c

推理:如果你取 Char(126) 或 '~' 的情况,然后在加密中添加一个你得到 127,它经过加密转换成为 33。

解密时得到 33 减去相同的 1,得到 32,这不会触发特殊的解密情况。通过在该语句中包含 32 将触发特殊解密并将 32 (" ") 更改为 126 ("~")

你是对的,这是一个错误,但它有点微妙

编辑:存在冲突错误,因为 char(32) 和 char(126) 正在散列到相同的值。在我之前的示例中,该值为 33,因此需要更改等式,以便 Char(126) 将散列为 32。

改变 c = (char) (c + 32 - 126);到 c = (char) (c + 32 - 127);应该释放额外的空间以防止发生碰撞。解密也必须从 c = (char) (c + 126 - 32);到 c = (char) (c + 127 - 32);

有人在我的 cmets 中发布了。

【讨论】:

  • 如果我将c &lt; 32 更改为c &lt;= 32,它会修复这种特殊情况,但只会产生另一个问题:` `(空格)被解密为~
  • @user2820314 这是一次性的,但修复不会改变限制,它会将32 - 126 更改为32 - 127126 - 32 更改为127 - 32
  • @Joachim Isaksson:没错,它不能解决问题。我已经查看了这段代码几个小时,但仍然没有看到错误。我被难住了。
  • @user2820314 我想你误解了我的意思。按照我的评论更改值可以解决问题。由于您希望序列为 125、126、32、33...(即 127 应转为 32),因此您需要减去 127 而不是 126。
  • 我在加密和解密中都将126 更改为127,它成功了!谢谢,你为我节省了很多灰色单元格。这将教会我将指令视为理所当然,而不是检查它们的有效性。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-01-18
  • 1970-01-01
  • 2023-03-15
  • 2015-12-01
  • 2015-11-14
相关资源
最近更新 更多