3

我有这个简单的函数,用于通过 Java 中的 Vigenère 加密字符串。我省略了解密,因为这只是计算新值的行中的“-”而不是“+”。

但此功能仅适用于普通字母 AZ。如何更改函数以使其支持小写字母、大写字母和所有其他 UTF-8 字符?

public static String vigenere_encrypt(String plaintext, String key) {
    String encryptedText = "";
    for (int i = 0, j = 0; i < plaintext.length(); i++, j++) {
        if (j == key.length()) { j = 0; } // use key again if end reached
        encryptedText += (char) ((plaintext.charAt(i)+key.charAt(j)-130)%26 + 65);
    }
    return encryptedText;
}

非常感谢您的帮助!

4

3 回答 3

4

好吧,你要求它,我感到很困惑,但是打印出密文,你就会知道你刚才要求的是什么......

public static String vigenereUNICODE(String plaintext, String key, boolean encrypt) {

    final int textSize = plaintext.length();
    final int keySize = key.length();

    final StringBuilder encryptedText = new StringBuilder(textSize);
    for (int i = 0; i < textSize; i++) {
        final int plainNR = plaintext.codePointAt(i);
        final int keyNR = key.codePointAt(i % keySize);

        final long cipherNR;
        if (encrypt) {
            cipherNR = ((long) plainNR + (long) keyNR) & 0xFFFFFFFFL;
        } else {
            cipherNR = ((long) plainNR - (long) keyNR) & 0xFFFFFFFFL;
        }

        encryptedText.appendCodePoint((int) cipherNR);
    }

    return encryptedText.toString();
}

编辑:请不要在生产代码使用,因为我不知道代码点是否确实可以编码/解码。据我所知,并不是所有的点都被定义了,标准是一个移动的目标。

于 2012-04-23T21:17:24.220 回答
4

如果不可能完全支持 unicode 并且您必须定义有效字符列表,那么为什么不直接使用这样的函数呢?

public static String vigenere_cipher(String plaintext, String key, boolean encrypt) {

    String alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ ,.-"; // including some special chars
    final int alphabetSize = alphabet.length();
    final int textSize = plaintext.length();
    final int keySize = key.length();
    final StringBuilder encryptedText = new StringBuilder(textSize);

    for (int i = 0; i < textSize; i++) {
        final char plainChar = plaintext.charAt(i); // get the current character to be shifted
        final char keyChar = key.charAt(i % keySize); // use key again if the end is reached
        final int plainPos = alphabet.indexOf(plainChar); // plain character's position in alphabet string
        if (plainPos == -1) { // if character not in alphabet just append unshifted one to the result text
            encryptedText.append(plainChar);
        }
        else { // if character is in alphabet shift it and append the new character to the result text
            final int keyPos = alphabet.indexOf(keyChar); // key character's position in alphabet string
            if (encrypt) { // encrypt the input text
                encryptedText.append(alphabet.charAt((plainPos+keyPos) % alphabetSize));
            }
            else { // decrypt the input text
                int shiftedPos = plainPos-keyPos;
                if (shiftedPos < 0) { // negative numbers cannot be handled with modulo
                    shiftedPos += alphabetSize;
                }
                encryptedText.append(alphabet.charAt(shiftedPos));
            }
        }
    }

    return encryptedText.toString();

}

这应该是一个非常简短且有效的版本。并且字母表可以很容易地存储在一个始终可以扩展的字符串中(这会导致不同的密文)。

于 2012-04-24T23:39:54.687 回答
3

另一个答案,它确实对大小写字符执行 Vigenere 密码,只需插入其他字符。使用此技术创建多组字符进行编码。

public static String vigenere(String plaintext, String key, boolean encrypt) {

    final int textSize = plaintext.length();
    final int keySize = key.length();

    final int groupSize1 = 'Z' - 'A' + 1; 
    final int groupSize2 = 'z' - 'a' + 1;
    final int totalGroupSize = groupSize1 + groupSize2;

    final StringBuilder encryptedText = new StringBuilder(textSize);
    for (int i = 0; i < textSize; i++) {
        final char plainChar = plaintext.charAt(i);

        // this should be a method, called for both the plain text as well as the key
        final int plainGroupNumber; 
        if (plainChar >= 'A' && plainChar <= 'Z') {
            plainGroupNumber = plainChar - 'A';
        } else if (plainChar >= 'a' && plainChar <= 'z') {
            plainGroupNumber = groupSize1 + plainChar - 'a';
        } else {
            // simply leave spaces and other characters
            encryptedText.append(plainChar);
            continue;
        }

        final char keyChar = key.charAt(i % keySize);
        final int keyGroupNumber; 
        if (keyChar >= 'A' && keyChar <= 'Z') {
            keyGroupNumber = keyChar - 'A';
        } else if (keyChar >= 'a' && keyChar <= 'z') {
            keyGroupNumber = groupSize1 + keyChar - 'a';
        } else {
            throw new IllegalStateException("Invalid character in key");
        }

        // this should be a separate method
        final int cipherGroupNumber;
        if (encrypt) {
            cipherGroupNumber = (plainGroupNumber + keyGroupNumber) % totalGroupSize;
        } else {
            // some code to go around the awkward way of handling % in Java for negative numbers
            final int someCipherGroupNumber = plainGroupNumber - keyGroupNumber;
            if (someCipherGroupNumber < 0) {
                cipherGroupNumber = (someCipherGroupNumber + totalGroupSize);
            } else {
                cipherGroupNumber = someCipherGroupNumber;
            }
        }

        // this should be a separate method
        final char cipherChar;
        if (cipherGroupNumber < groupSize1) {
            cipherChar = (char) ('A' + cipherGroupNumber);
        } else {
            cipherChar = (char) ('a' + cipherGroupNumber - groupSize1);
        }
        encryptedText.append(cipherChar);
    }

    return encryptedText.toString();
}

同样,这是不安全的代码,因为使用的密码已被破解多年。不要在你的键中使用太多的“A”字符:) 但是字符编码应该是正确的。

于 2012-04-23T22:41:01.127 回答