具有Ascii字符的凯撒密码

时间:2017-12-07 00:38:48

标签: java ascii

我尝试使用带有键位置整数的ascii字符加密字符串。我有两种方法,一种用于加密,一种用于解密。

问题是,当字符值高于126时,我尝试对其进行修改126然后再添加32,但是我得到的数字远远超出这些限制。

public static String encrypt(String s, int k) {
    char[] arr = s.toCharArray();
    int ascii;
    for(int i = 0; i < arr.length; i++) {
        ascii = (int) arr[i];
        ascii = ascii + k;
        // System.out.println(ascii);
        if (ascii > 126) {
            ascii = 32 + (126 % ascii);
            // System.out.print("Changed: " + ascii);
        }

        arr[i] = (char) ascii;
    }
    return String.valueOf(arr);
}

两条注释掉的线路用于测试,并且更改的值是疯狂的高,而不是从127%126 = 1 + 32到总共33(预期值),我得到15870。

2 个答案:

答案 0 :(得分:0)

你的modulo语句是向后写的一个开始。尝试:

ascii = 32 + (ascii % 126);

答案 1 :(得分:0)

首先,正如mypetlion所提到的,当a除以b时,模运算a%b等于余数。例如。 11%4 = 3,8%15 = 8.准确地说,它是满足b * n + k = a,b *(n + 1)>的值k。 a,k&lt; b其中n是整数。使用离散数学有更合适的描述,我忽略了否定的论点,但它们并不重要。所以在你的情况下你应该做ascii%128。

为什么模数应该是128而不是126,7位ascii代码从0-127,总共128个值。另外我对+32的含义感到有点困惑,因为你已经做了+ k。

此外,您可以完全省略if块,因为c%128 = c表示[0,128]范围内的任何c。

所以我会写下面的代码:

public static String encrypt(String s, int k) {
    char[] arr = s.toCharArray();
    for(int i = 0; i < arr.length; i++){
        arr[i] = (char) ((arr[i] + k) % 128);
    }
    return String.valueOf(arr);
}
public static String decrypt(String s, int k) {
    char[] arr = s.toCharArray();
    for(int i = 0; i < arr.length; i++){
        arr[i] = (char) ((arr[i] + 128 - k % 128) % 128);
        // + 128 - k % 128 because I don't want do deal with negative numbers.
    }
    return String.valueOf(arr);
}

我相信我的代码会起作用(对于k的所有正值),但我无法解释为什么你的代码产生了一些疯狂的高ascii值。当我在我的IDE上运行你的代码时,它没有那样做,也不能从你的代码中看到它的原因。

最后,这个密码方法会加密和解密,但请注意,ascii确实包含许多不易打印的控制字符。因此,如果您希望将密码词汇限制为仅字母和标点符号,则需要进行一些字符映射以限制要加密和加密的字符。这将会复杂得多,更不用说你必须考虑像Windows v.LF中的CR + LF这样的问题。以下是仅加密和解密字母的简单示例。

public static int asciiToCustom(char ascii) {
// Maps 65-90 & 97-122 to 0-51.
    int customCode;
    if(ascii >= 65 && ascii <= 90){
        customCode = ascii - 65;
    }
    else if(ascii >= 97 && ascii <= 122){
        customCode = ascii - 71;
    }
    else{
        throw new RuntimeException("not a letter!");
    }
    return customCode;
}
public static char customToAscii(int custom) {
// Maps 0-51 to 65-90 & 97-122.
    int ascii;
    if(custom >= 0 && custom <= 25){
        ascii = custom + 65;
    }
    else if(custom >= 26 && custom <= 51){
        ascii = custom + 71;
    }
    else{
        throw new RuntimeException("not a valid custom code!");
    }
    return (char) ascii;
}
public static String encrypt(String s, int k) {
    char[] arr = s.toCharArray();
    for(int i = 0; i < arr.length; i++){
        if(Character.isLetter(arr[i])){
            arr[i] = customToAscii((asciiToCustom(arr[i]) + k) % 52);
        }
    }
    return String.valueOf(arr);
}
public static String decrypt(String s, int k) {
    char[] arr = s.toCharArray();
    for(int i = 0; i < arr.length; i++){
        if(Character.isLetter(arr[i])){
            arr[i] = customToAscii((asciiToCustom(arr[i]) + 52 - k % 52) % 52);
            // + 52 - k % 52 because I don't want do deal with negative numbers.
        }
    }
    return String.valueOf(arr);
}