java BigInteger如何解释字符串中的字节?
我正在开发一个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
# 1 楼答案
答案是在输出中,“test”被编码成4字节的数组[116、101、115、116]。然后,BigInteger将其解释为二进制整数表示。这个值可以这样计算
# 2 楼答案
这实际上可以归结为理解这条线的作用:
让我们把它分解一下
我们从一个字符串(
string
)开始。Java字符串是以Unicode代码点(用UCS-16编码…)表示的字符序列然后
getBytes("UTF-8")
将字符编码为字节序列,并在新分配的字节数组中返回它们BigInteger(byte[])
构造函数将该字节数组解释为一个数字。正如javadoc所说:这里使用的方法不是给出一个本质上有意义的数字,而是一个对应于字节编码字符串的数字。从字节数组到数字,就是把字节当作一个位序列,以2的补码形式表示一个整数。。。这是现代硬件上最常见的整数表示形式
关键是,从文本到(未加密的)BigInteger的转换是无损且可逆的。可以使用具有这些属性的任何其他转换
参考资料:
看到模式了吗