I need help explaining what this means res += (char) ((c + key.charAt(j) – 2 * 'A') % 26 + 'A');

huangapple go评论76阅读模式
英文:

I need help explaining what this means res += (char) ((c + key.charAt(j) - 2 * 'A') % 26 + 'A');

问题

public static String encrypt(String text, final String key)
{
    String res = "";
    text = text.toUpperCase();
    for (int i = 0, j = 0; i < text.length(); i++)
    {
        char c = text.charAt(i);
        if (c < 'A' || c > 'Z')
            continue;
            
        res += (char) ((c + key.charAt(j) - 2 * 'A') % 26 + 'A');

        j = ++j % key.length();
    }
    return res;
}

The given code is a Java function named encrypt that takes two parameters: text (a plaintext string) and key (a secret key string). The purpose of the function is to encrypt the provided text using a simple substitution cipher based on the key.

Here's a brief explanation of what the code does:

  1. String res = "";: Initializes an empty string res to store the encrypted result.

  2. text = text.toUpperCase();: Converts the input text to uppercase to ensure consistent handling of characters.

  3. for (int i = 0, j = 0; i < text.length(); i++): Loops through each character in the input text.

  4. Inside the loop:

    • char c = text.charAt(i);: Retrieves the current character at position i in the input text.
    • if (c < 'A' || c > 'Z') continue;: Skips the current character if it's not an uppercase letter ('A' to 'Z').
  5. res += (char) ((c + key.charAt(j) - 2 * 'A') % 26 + 'A');: This line performs the encryption process. Let's break it down:

    • key.charAt(j) retrieves the character at position j in the key string.
    • ((c + key.charAt(j) - 2 * 'A') % 26 + 'A') calculates the new encrypted character:
      • (c + key.charAt(j) - 2 * 'A') adds the ASCII values of the current character and the key character (adjusted for 'A') and subtracts twice the ASCII value of 'A'.
      • % 26 calculates the result modulo 26 to ensure it wraps within the range of 0 to 25.
      • + 'A' adds the ASCII value of 'A' to bring the value back into the range of uppercase letters.
  6. j = ++j % key.length();: Increments the value of j (key index) and wraps it around based on the length of the key string.

  7. The loop continues until all characters in the input text are processed.

  8. The encrypted result string res is returned.

In summary, the code uses the provided key to perform a basic Caesar cipher-like encryption on the input text, shifting the characters by a value derived from the key. The encrypted result is stored in the res string, which is then returned.

英文:
public static String encrypt(String text, final String key)
{
    String res = &quot;&quot;;
    text = text.toUpperCase();
    for (int i = 0, j = 0; i &lt; text.length(); i++)
    {
        char c = text.charAt(i);
        if (c &lt; &#39;A&#39; || c &gt; &#39;Z&#39;)
            continue;
        //				(0 + A - 2 * A) % 26 + A
        
        res += (char) ((c + key.charAt(j) - 2 * &#39;A&#39;) % 26 + &#39;A&#39;);

        //System.out.println(&quot;C: &quot;+ c +&quot; i: &quot;+i+ &quot; j: &quot;+j + &quot; key.char: &quot;+key.charAt(j) + &quot; res: &quot; + res);
        
        j = ++j % key.length();
    }
    return res;
}

I basically just want to understand what " res += (char) ((c + key.charAt(j) - 2 * 'A') % 26 + 'A');
" this means. I pretty much figured out that its some kind of append to string? but I can figure out what the rest of it means.

答案1

得分: 2

这个方法的命名错误。这不是加密。如果是加密,那么这是一种三岁小狒狒都能“解密”的加密方式。

char 实际上是一种数值数据类型,这就是为什么你可以执行像 2*'A' 这样的操作。这个数字是 Unicode 编码。因为这显然是基于 ASCII 的,而且所有的 ASCII 码都直接映射到它们的 Unicode 等价物,没有任何改变,你可以在网上搜索任何 ASCII 码表。例如,'A' 只是写 65 的另一种方式。

因此,让我们从这里开始:

c + key.charAt(j) - 2 * 'A'

按照 Java 的优先级规则,首先解析 2*'A',所以这会从 c + key.charAt(j) 减去 130。如果你将它视为 (c - 'A') + (key.charAt(j) - 'A'),它会变得更容易理解。这个公式总是产生与你的公式完全相同的结果,我只是重新排列了一下(我将 -2*'A' 拆分为 - 'A' - 'A',这总是能够运算出来的,然后重新排列了一下)。

c 是一个字符值,但由于前面的 if,我们可以确定内容位于 'A' (65) 和 'Z' (90) 之间,有保证。

密钥可以是任何东西(从你的粘贴内容中不太清楚),但看起来一般的想法是密钥仅由大写字母组成,因此也是 65-90。

假设密钥是 'WORLD',要加密的文本是 'HELLO'。

那么这可以简化为:('W' - 'A') + ('H' - 'A')('W' - 'A') 只是计算字母 W 在字母表中的索引。A 是第 0 个字母,B 是第 1 个字母,C 是第 2 个字母,W 是第 22 个字母。然后我们对密钥在这个位置的字母做同样的事情... 然后把它们加在一起。W 是第 22 个字母,H 是第 7 个字母,所以结果是 29

接下来,对它进行 %26 运算。% 是取余数:将 29 除以 26,保留余数。所以,余数是 3。(26%26 = 0,27%26 = 1,依此类推)。之所以是 26,是因为字母表中有 26 个字母。如果我让你给 'B' 加上 'D',你可能会告诉我:好的,那就是 'E'。但是如果我让你给 'Z' 加上 'B',这该怎么办?嗯,我们会“循环”,结果变成 'A'。这就是 % 26 的作用:实现这种循环行为。

然后,我们将其加上 'A',并将结果视为一个字符。3+'A' 变成了 'D'。这只是将索引号(第 5 个字母)重新转换回实际字母。0+'A' 是 A,1+'A' 是 B,依此类推。

请注意,如果密钥包含非大写字母(例如,包含一个空格),此算法会产生奇怪的结果,甚至得到负数。显然,这个“编码器环”的作者没有考虑到这一点。

那么,这行代码的目的是什么?

这就是这个加密协议的工作方式:

给定密钥 'ABC' 和明文 'HELLOWORLD',我们循环遍历明文中的每个字母。对于每个字母,我们在密钥中找到相匹配的字母。这里明文的长度超过了密钥,通过简单地循环密钥来解决这个问题。所以,'HELLOWORLD' 匹配的密钥是 'ABCABCABCA'(为什么?这就是 j = ++j % key.length(); 的用途)。

因此,加密 'HELLO WORLD' 中的 'H' 的结果是:

(/*明文*/ 'H' + /*密钥*/ 'A' - 'A' - 'A') % 26 + 'A',结果就是 H

加密 'HELLO WORLD' 中的 'E' 的结果是:

(/*明文*/ 'E' + /*密钥*/ 'B' - 'A' - 'A') % 26 + 'A',结果就是 F

换句话说,如果密钥字符是 'C',那么明文中的字母通过加 2 进行“加密”。D 变成 F,A 变成 C,X 变成 Z。并且它会循环进行;Z 变成 B。

使用密钥 ABC 加密文本 HELLOWORLD 的结果是:HFNLPZOSND

英文:

The method is misnamed. This isn't encryption. Or if it is, it is the kind of encryption a 3 year old baboon can 'decrypt'.

char is actually a numeric datatype, hence why you can do things like 2*&#39;A&#39;. The number is the unicode code. As this is clearly ascii based, and all ascii codes map straight to their unicode equivalent with no changes, you can just search the web for any ascii code chart. 'A' is just an alternate way to write 65, for example.

Thus, let's start with:

c + key.charAt(j) - 2 * &#39;A&#39;

The way java's precedence rules work, the 2*&#39;A&#39; is resolved first, so this subtracts 130 from c + key.charAt(j). It becomes easier to understand if you treat it as: (c - &#39;A&#39;) + (key.charAt(j) - &#39;A&#39;). That formula always produces the exact same result as what you have, as I just moved terms around (I deconstructed -2*&#39;A&#39; into -&#39;A&#39;-&#39;A&#39; which always works out, then moved terms around).

c is a character value, but because of the if that precedes it, we know for sure that the content is between 'A' (65) and 'Z' (90), guaranteed.

The key could be anything (not clear from your paste), but it looks like the general idea is that the key consists of solely uppercase letters, so, that too is 65-90.

Let's say the key is 'WORLD' and the text to encrypt is 'HELLO'.

Then that boils down to: (&#39;W&#39; - &#39;A&#39;) + (&#39;H&#39; - &#39;A&#39;). (&#39;W&#39;-&#39;A&#39;) is just calculating the 'index' of the letter W in the alphabet. 'A' is the 0 letter. B is the 1 letter. C is the 2 letter. W is the 22 letter. Then we do the same thing ot the letter in the key for this position... and adding them together. W is the 22 letter, H is the 7 letter, so this becomes 29.

Next, it does %26 to that getup. % is remainder: divide 29 by 26, toss the result, keep the remainder. So, 3. (26%26 = 0, 27%26 1. etcetera). The reason it's 26 is because there are 26 letters in the alphabet. If I ask you to add 'B' to 'D' you might tell me: okay, that is 'E'. But if I ask you to add 'Z' to 'B', how does that work? Well, we 'loop' around, that becomes 'A'. That's what the % 26 is accomplishing: That looping behaviour.

Then, we add that to 'A', and treat the result as a character . 3+&#39;A&#39; becomes &#39;D&#39;. That's just turning an index number (the 5 letter) back into the actual letter. 0+&#39;A&#39; is A, 1+&#39;A&#39; is B, etcetera.

Note that this algorithm does weird things and ends up with negative numbers if the key contains non-capitals (for example, if it contains a space). Clearly the author of this 'encoder ring' level craziness did not consider this.

So, what is the point of this line?

This is how this encryption protocol works:

Given a key 'ABC' and plaintext 'HELLOWORLD', we loop through each letter in the plaintext. For each letter, we find the matching letter in the key. Here the plaintext is longer than the key, and that's fixed by just looping the key. So, 'HELLOWORLD' is matched by 'ABCABCABCA' (why? That's what j = ++j % key.length(); is about).

The result of encrypting that H in hello world is therefore:

(/*plaintext */ &#39;H&#39; + /* key */ &#39;A&#39; - &#39;A&#39; - &#39;A&#39;) % 26 + &#39;A&#39; which is just H.

The result of encrypting that E in hello world is therefore:

(/*plaintext */ &#39;E&#39; + /* key */ &#39;B&#39; - &#39;A&#39; - &#39;A&#39;) % 26 + &#39;A&#39; which is just F.

In other words, if the key character is, say, 'C', then the letter in the plaintext is 'encrypted' by adding 2 to it. D becomes F. A becomes C. X becomes Z. And it loops around; Z becomes B.

The result of this 'encryption' protocol with key ABC to encrypt text HELLOWORLD is: HFNLPZOSND.

huangapple
  • 本文由 发表于 2020年10月4日 22:59:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/64196173.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定