从客户端(Android)发送的服务器端RSA公钥加密数据解密失败

时间:2016-06-15 02:05:34

标签: java android encryption

服务器将公钥加密数据发送到客户端,客户端也发送到服务器。

客户端解密很好。服务器端不是。

相同的解密程序似乎适用于Android,但是,它显然不在服务器端。

这是我的服务器端解密代码:

int bytesRead;
int current = 0;
FileOutputStream fos = null;
byte[] EncryptedClientAES = new byte[10000];
InputStream is = clientSocket.getInputStream();
fos = new FileOutputStream("ClientAESFile");
BufferedOutputStream bos = new BufferedOutputStream(fos);
bytesRead = is.read(EncryptedClientAES, 0, EncryptedClientAES.length);
current = bytesRead;
System.out.println("Size of read data: " + current);

bos.write(EncryptedClientAES, 0, current);

bos.flush();
bos.close();
fos.close();
clientSocket.close();

Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] decryptedAESKeyOfClient = null;
decryptedAESKeyOfClient = cipher.doFinal(EncryptedClientAES);

这失败, IllegalBlockSizeException 表示数据不应超过64个字节,这使得我将字节数组 EncryptedClientAES 的大小更改为 64 因为读取数据的大小也是 64 。继续使用它给了我 BadPaddingException ,但是,同样的程序适用于Android端。

以下是我从Android发送代码的加密数据:

SecureRandom secureRandom = new SecureRandom();
KeyGenerator kg = null;
kg = KeyGenerator.getInstance("AES");
kg.init(128, secureRandom);
SecretKey ClientSecretKey = kg.generateKey(); // Client AES is generated here.

String ServerModulus = ServerRSAPublicKey.substring(40, 194);
String ServerExponent = ServerRSAPublicKey.substring(214, 219);
BigInteger bigInteger = new BigInteger(ServerModulus, 10);
BigInteger bigInteger1 = new BigInteger(ServerExponent);

RSAPublicKeySpec rsaPublicKeySpec = new RSAPublicKeySpec(bigInteger, bigInteger1);
KeyFactory keyFactory = null;
try {
    keyFactory = KeyFactory.getInstance("RSA");
} catch (NoSuchAlgorithmException e) {
    e.printStackTrace();
}
RSAPublicKey publicKeyOfServer = null;
try {
    assert keyFactory != null;
    publicKeyOfServer = (RSAPublicKey) keyFactory.generatePublic(rsaPublicKeySpec);
} catch (InvalidKeySpecException e) {
    e.printStackTrace();
}

Cipher c = null;
try {
    c = Cipher.getInstance("RSA");
} catch (NoSuchPaddingException e) {
    e.printStackTrace();
}
try {
    assert c != null;
    c.init(Cipher.ENCRYPT_MODE, publicKeyOfServer);
} catch (InvalidKeyException e) {
    e.printStackTrace();
}

byte[] encryptedBytes = null;
try {
    encryptedBytes = c.doFinal(ClientSecretKey.getEncoded());
} catch (IllegalBlockSizeException | BadPaddingException e) {
    e.printStackTrace();
}
OutputStream outputStream;
outputStream = client.getOutputStream();
assert encryptedBytes != null;
outputStream.write(encryptedBytes, 0, encryptedBytes.length);

outputStream.flush();
outputStream.close();
client.close(); // closing the connection

我在Android端工作的解密代码是

Socket client = new Socket("192.168.1.169", 4444);

int bytesRead;
int current = 0;
FileOutputStream fos;
byte[] EncryptedServerAES = new byte[100000];
InputStream is = client.getInputStream();
fos = new FileOutputStream("ServerAESKeyFile");
BufferedOutputStream bos = new BufferedOutputStream(fos);
bytesRead = is.read(EncryptedServerAES, 0, EncryptedServerAES.length);
current = bytesRead;
do {
    bytesRead =
            is.read(EncryptedServerAES, current, (EncryptedServerAES.length - current));
    if (bytesRead >= 0) current += bytesRead;
} while (bytesRead > -1);

bos.write(EncryptedServerAES, 0, current);
bos.flush();
fos.close();
bos.close();
client.close(); // closing the connection

// try to decrypt and get AES key back.
BigInteger Modulus;
BigInteger publicExponent;
BigInteger privateExponent;
BigInteger primeP;
BigInteger primeQ;
BigInteger primeExpP;
BigInteger primeExpQ;
BigInteger crtCoeff;
Modulus = new BigInteger(ClientPrivateKey.substring(32, 161));
publicExponent = new BigInteger("10001");
privateExponent = new BigInteger(ClientPrivateKey.substring(198, 327));
primeP = new BigInteger(ClientPrivateKey.substring(334, 399));
primeQ = new BigInteger(ClientPrivateKey.substring(406, 471));
primeExpP = new BigInteger(ClientPrivateKey.substring(486, 551));
primeExpQ = new BigInteger(ClientPrivateKey.substring(566, 631));
crtCoeff = new BigInteger(ClientPrivateKey.substring(646, 711));

Cipher cipher = Cipher.getInstance("RSA");
// realise client's private key string as private key.
RSAPrivateCrtKeySpec rsaPrivateCrtKeySpec = new RSAPrivateCrtKeySpec(Modulus, publicExponent, privateExponent, primeP, primeQ, primeExpP, primeExpQ, crtCoeff);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
RSAPrivateKey ClientPrivateKEY = null;
try {
    ClientPrivateKEY = (RSAPrivateKey) keyFactory.generatePrivate(rsaPrivateCrtKeySpec);
} catch (InvalidKeySpecException e) {
    e.printStackTrace();
}
try {
    cipher.init(Cipher.DECRYPT_MODE, ClientPrivateKEY);
} catch (InvalidKeyException e) {
    e.printStackTrace();
}
try {
    decryptedAESKeyOfServer = cipher.doFinal(EncryptedServerAES);
} catch (IllegalBlockSizeException | BadPaddingException e) {
    e.printStackTrace();
}

对于Android(客户端)方面的上述成功解密,服务器发送了此数据

Cipher c = null;
try {
    c = Cipher.getInstance("RSA");
} catch (NoSuchAlgorithmException | NoSuchPaddingException ex) {
    Logger.getLogger(SecureServer.class.getName()).log(Level.SEVERE, null, ex);
}
 {
    try {
        c.init(Cipher.ENCRYPT_MODE, publicKeyofClient);
    } catch (InvalidKeyException ex) {
        Logger.getLogger(SecureServer.class.getName()).log(Level.SEVERE, null, ex);
    }
}
byte[] encryptedBytes = null;
 {
    try {
        encryptedBytes = c.doFinal(ServerSecretKey.getEncoded());
    } catch (IllegalBlockSizeException | BadPaddingException ex) {
        Logger.getLogger(SecureServer.class.getName()).log(Level.SEVERE, null, ex);
    }
}

OutputStream outputStream;
outputStream = clientSocket.getOutputStream();
outputStream.write(encryptedBytes, 0, encryptedBytes.length);

outputStream.flush();
outputStream.close();
clientSocket.close(); // closing the connection

这就是我在双方生成RSA密钥的方式

secureRandom = new SecureRandom();
try {
    keyPairGenerator = KeyPairGenerator.getInstance("RSA");
} catch (NoSuchAlgorithmException ex) {
    Logger.getLogger(SecureServer.class.getName()).log(Level.SEVERE, null, ex);
}

keyPairGenerator.initialize(512, secureRandom);
keyPair = keyPairGenerator.generateKeyPair();
privateKey = (RSAPrivateKey) keyPair.getPrivate();
publicKey = (RSAPublicKey) keyPair.getPublic();

我想我在这里很蠢。

更新1

它仍然失败。

这是我的(Android)客户端加密代码

Cipher ciphertest = null;
ciphertest = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
ciphertest.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] encryptedBytes = null;
encryptedBytes = ciphertest.doFinal(Bytes_to_encrypt);

这是我的服务器端解密代码

Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPPadding");
OAEPParameterSpec oaepParams = new OAEPParameterSpec("SHA-256", "MGF1", new MGF1ParameterSpec("SHA-1"), PSource.PSpecified.DEFAULT);
cipher.init(Cipher.DECRYPT_MODE, privateKey, oaepParams);
byte[] decryptedAESKeyOfServer = null;
decryptedAESKeyOfServer = cipher.doFinal(EncryptedClientAES);

错误是 IllegalBlockSizeException (如果 decryptedAESKeyOfServer 的大小是随机大字节)或 BadPaddingException (如果 decryptedAESKeyOfServer 大小为256字节;从客户端接收的数据是这么多字节)。

更新2

  • 我已经修复了从Android发送到服务器的数据。 客户端在此之前发送了空。
  • 即使服务器正在发送256字节的数据,Android也会从服务器读取空值。

客户端上从服务器读取空值的代码

int bytesRead;
int current = 0;
FileOutputStream fos;
byte[] EncryptedServerAES = new byte[100000];
InputStream is = client.getInputStream();
fos = new FileOutputStream("ServerAESKeyFile");
BufferedOutputStream bos = new BufferedOutputStream(fos);
bytesRead = is.read(EncryptedServerAES, 0, EncryptedServerAES.length);
data_size = bytesRead; // data_size is 0.

Idk怎么样,但是,客户端仍在(尝​​试)解密它并且没有崩溃!

我的堆栈跟踪

06-15 15:18:03.619 23489-23927/com.avineshwar.secureclient W/System.err: java.io.FileNotFoundException: ServerAESKeyFile: open failed: EROFS (Read-only file system)
06-15 15:18:03.620 23489-23927/com.avineshwar.secureclient W/System.err:     at libcore.io.IoBridge.open(IoBridge.java:456)
06-15 15:18:03.622 23489-23927/com.avineshwar.secureclient W/System.err:     at java.io.FileOutputStream.<init>(FileOutputStream.java:87)
06-15 15:18:03.623 23489-23927/com.avineshwar.secureclient W/System.err:     at java.io.FileOutputStream.<init>(FileOutputStream.java:127)
06-15 15:18:03.623 23489-23927/com.avineshwar.secureclient W/System.err:     at java.io.FileOutputStream.<init>(FileOutputStream.java:116)
06-15 15:18:03.623 23489-23927/com.avineshwar.secureclient W/System.err:     at com.avineshwar.secureclient.Part3$SendMessage.doInBackground(Part3.java:128)
06-15 15:18:03.623 23489-23927/com.avineshwar.secureclient W/System.err:     at com.avineshwar.secureclient.Part3$SendMessage.doInBackground(Part3.java:115)
06-15 15:18:03.623 23489-23927/com.avineshwar.secureclient W/System.err:     at android.os.AsyncTask$2.call(AsyncTask.java:292)
06-15 15:18:03.623 23489-23927/com.avineshwar.secureclient W/System.err:     at java.util.concurrent.FutureTask.run(FutureTask.java:237)
06-15 15:18:03.623 23489-23927/com.avineshwar.secureclient W/System.err:     at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
06-15 15:18:03.623 23489-23927/com.avineshwar.secureclient W/System.err:     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
06-15 15:18:03.623 23489-23927/com.avineshwar.secureclient W/System.err:     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
06-15 15:18:03.623 23489-23927/com.avineshwar.secureclient W/System.err:     at java.lang.Thread.run(Thread.java:818)

Part3.java 中,第115行只是一个空白行,我认为是对的引用:

private class SendMessage extends AsyncTask<Void, Void, Void> {

Part3.java 中,第128行

InputStream is = client.getInputStream();

0 个答案:

没有答案