我正在制作一个系统,我想通过RSA验证服务器的身份,但我似乎无法让服务器正确解密客户端的消息。
公钥和私钥位于数组的插槽0中,mod位于插槽1中,因此它们设置正确。
客户端代码
int keyLength = 3072 / 8;//RSA key size
byte[] data = new byte[keyLength];
//Generate some random data. Note that
//Only the fist half of this will be used.
new SecureRandom().nextBytes(data);
int serverKeySize = in.readInt();
if (serverKeySize != keyLength) {//Definitely not the right heard
return false;
}
//Take the server's half of the random data and pass ours
in.readFully(data, keyLength / 2 , keyLength / 2);
//Encrypt the data
BigInteger[] keys = getKeys();
BigInteger original = new BigInteger(data);
BigInteger encrypted = original.modPow(keys[0], keys[1]);
data = encrypted.toByteArray();
out.write(data);
//If the server's hash doesn't match, the server has the wrong key!
in.readFully(data, 0, data.length);
BigInteger decrypted = new BigInteger(data);
return original.equals(decrypted);
服务器端代码
int keyLength = 3072 / 8;//Key length
byte[] data = new byte[keyLength];
//Send the second half of the key
out.write(data, keyLength / 2, keyLength / 2);
in.readFully(data);
BigInteger[] keys = getKeys();
BigInteger encrypted = new BigInteger(data);
BigInteger original = encrypted.modPow(keys[0], keys[1]);
data = original.toByteArray();
out.write(data);
AFAIK的实现是正确的,但它似乎没有产生正确的输出。也不,我不希望出于各种原因使用密码。
答案 0 :(得分:2)
有一些关键细节未被考虑。您要应用RSA的数据必须编码为BigInteger x,其中0 <= x&lt; n,其中n是你的模数。你不是那样做的。实际上,因为您使用随机数据填充整个数据数组,所以无法保证这一点。 PKCS#1填充算法旨在正确执行此操作,但由于您自己滚动,因此您必须在代码中修复此问题。另外,仔细检查BigInteger(byte[])
构造函数和BigInteger.toByteArray()
解码/编码整数的方式。天真的很多人只期望基数256编码,并且忘记BigInteger也必须容纳负整数。它通过使用ASN.1 DER整数规则来实现。如果正整数的高位字节将> = 128,则添加前导零字节。