【问题标题】:How does BigInteger interpret the bytes from a string?BigInteger 如何解释字符串中的字节?
【发布时间】:2014-03-16 03:25:10
【问题描述】:

我正在开发一个实现 RSA 加密算法的程序,就像个人练习一样,它不会保护任何人的信息或任何东西。我试图了解如何以数字方式解释明文段落,从而对其进行加密。我知道大多数 UTF-8 字符最终只使用 1 个字节的空间,而不是人们可能认为的 2 个字节,但仅此而已。这是我的代码:

BigInteger ONE = new BigInteger("1");
   SecureRandom rand = new SecureRandom();

   BigInteger d, e, n;
   BigInteger p = BigInteger.probablePrime(128, rand);
   BigInteger q = BigInteger.probablePrime(128, rand);
   BigInteger phi = (p.subtract(ONE)).multiply(q.subtract(ONE));

   n = p.multiply(q);
   e = new BigInteger("65537");
   d = e.modInverse(phi);

   String string = "test";
   BigInteger plainText = new BigInteger(string.getBytes("UTF-8"));
   BigInteger cipherText = plainText.modPow(e, n);
   BigInteger originalMessage = cipherText.modPow(d, n);
   String decrypted = new String(originalMessage.toByteArray(),"UTF-8");

   System.out.println("original: " + string);
   System.out.println("decrypted: " + decrypted);
   System.out.println(plainText);
   System.out.println(cipherText);
   System.out.println(originalMessage);
   System.out.println(string.getBytes("UTF-8"));

   byte byteArray[] = string.getBytes("UTF-8");

   for(byte littleByte:byteArray){
       System.out.println(littleByte);
   }

它输出:

original: test
decrypted: test
1952805748
16521882695662254558772281277528769227027759103787217998376216650996467552436
1952805748
[B@60d70b42
116
101
115
116

也许更具体地说,我想知道这一行:

BigInteger plainText = new BigInteger(string.getBytes("UTF-8"));

“test”的每个字母是否都有值,并且它们在这里按字面意思相加?就像说 t=1,e=2,s=3,t=1 例如,如果您从该字符串中获取字节,您最终会得到 7 还是只是像 1231 一样将这些值放在一起?为什么

BigInteger plainText = new BigInteger(string.getBytes("UTF-8")); 输出1952805748

【问题讨论】:

    标签: java encryption encoding utf-8 biginteger


    【解决方案1】:

    我试图了解如何以数字方式解释纯文本段落,从而对其进行加密。

    真正归结为理解这条线的作用:

       BigInteger plainText = new BigInteger(string.getBytes("UTF-8"));
    

    让我们分解一下。

    1. 我们从字符串 (string) 开始。 Java 字符串是表示为 Unicode 代码点的字符序列(以 UCS-16 编码 ...)。

    2. getBytes("UTF-8") 然后将字符编码为字节序列,并将它们返回到新分配的字节数组中。

    3. BigInteger(byte[]) 构造函数将该字节数组解释为一个数字。正如 javadoc 所说:

      将包含 BigInteger 的二进制补码表示的字节数组转换为 BigInteger。输入数组是 假定为大端字节序:最高有效字节为 在第零个元素中。

    这里使用的方法不是给出一个具有内在意义的数字,只是一个对应于字节编码字符串的数字。从字节数组到数字只是将字节视为一个位序列,以 2 的补码形式表示整数......这是现代硬件上整数的最常见表示。

    关键是从文本到(未加密的)BigInteger 的转换是无损且可逆的。可以使用具有这些属性的任何其他转换。

    参考资料:


    我还是不太明白“test”中每个字符的 UTF-8 值,116,101,115,116 分别是如何组合成 1952805748 的?

    1. 将数字 116,101,115,116 转换为十六进制。
    2. 将数字 1952805748 转换为十六进制
    3. 比较它们

    看到图案了吗?

    【讨论】:

    • 我还是不太明白“test”中每个字符的 UTF-8 值是如何分别形成 1952805748 的 116,101,115,116?
    【解决方案2】:

    答案在输出中,“test”被编码为 4 字节数组 [116, 101, 115, 116]。然后由 BigInteger 将其作为二进制整数表示进行干预。值可以这样计算

    value = (116 << 24) + (101 << 16) + (115 << 8) + 116;
    

    【讨论】:

    • 这些值是什么?以及为什么BigInteger plainText = new BigInteger(string.getBytes("UTF-8")); 输出1952805748
    • 这些值如何结合起来产生 1952805748?
    • 好的,所以我读到 UTF-8 作为前 127 个字符的 ASCII,这对 t=116=01110100 部分是有意义的。但是 (116
    • 你能把你的答案再扩大一点吗,你是怎么得出这个计算的?
    • 二进制表示1952805748 = 0x74657374,4字节,十进制表示116,101,115,116
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-12
    • 2012-07-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-27
    • 1970-01-01
    相关资源
    最近更新 更多