【发布时间】:2015-01-09 08:28:01
【问题描述】:
我已从 android 向服务器发出 https api 请求。 API 请求包含一个在发送前需要加密的参数(即,它是一个密码)。 RSA/ECB/PKCS1Padding是两端使用的加密方式。
android端的加密做了以下事情:
/*Encrypt the password using public key.public key is obtained from generateRsaPublicKey(BigInteger modulus, BigInteger publicExponent) function)*/
public static String rsaEncrypt(String originalString, PublicKey key) {
try {
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] cipherByte = cipher.doFinal(original);
return bytesToHex(cipherByte);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
//generate public key with given module and exponent value
public static PublicKey generateRsaPublicKey(BigInteger modulus, BigInteger publicExponent) {
PublicKey key = null;
try {
key = KeyFactory.getInstance("RSA").generatePublic(new RSAPublicKeySpec(modulus, publicExponent));
return key;
} catch (Exception e) {
Log.e("error", e.toString());
// return null;
}
return key;
}
// Helper methods
final protected static char[] hexArray = "0123456789abcdef".toCharArray();
public static String bytesToHex(byte[] bytes) {
char[] hexChars = new char[bytes.length * 2];
for ( int j = 0; j < bytes.length; j++ ) {
int v = bytes[j] & 0xFF;
// Log.d("byte array representaion","value in integrer"+v);
hexChars[j * 2] = hexArray[v >>> 4];
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
}
return new String(hexChars);
}
下面是服务器上解密密码的源代码
// *** setup private key
RSAPrivateKeySpec privateRPKS
= new RSAPrivateKeySpec(new BigInteger(gModulusPlainS, 16), new BigInteger(privateExponentPlainS, 16));
KeyFactory keyFactoryKF = KeyFactory.getInstance("RSA");
RSAPrivateKey gPrivateKeyRPK = (RSAPrivateKey) keyFactoryKF.generatePrivate(privateRPKS);
// *** setup cipher
Cipher cipherC = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipherC.init(Cipher.DECRYPT_MODE, gPrivateKeyRPK);
// *** decrypt hex-encoded cipherTxS
byte[] baCipherText = hexToBin(cipherTxS.getBytes());
byte[] baPlainText2 = cipherC.doFinal(baCipherText);
String decryptedTextS = new String(baPlainText2);
但我得到以下错误日志
javax.crypto.IllegalBlockSizeException: Data size too large
at com.ibm.crypto.provider.RSASSL.a(Unknown Source)
at com.ibm.crypto.provider.RSASSL.engineDoFinal(Unknown Source)
at javax.crypto.Cipher.doFinal(Unknown Source)
javax.crypto.BadPaddingException: Not PKCS#1 block type 2 or Zero padding
但它正在 websight 部分工作。为什么它在android中不起作用?
感谢您查看我的代码。
【问题讨论】:
-
1) HTTPS 已经加密了所有内容。那么再次加密有什么意义。 2) PKCS#1v1.5 填充是不安全的。请改用 OAEP。
-
第 1 点:https 对整个 url 字符串进行加密。但为了提高安全性,我们需要使用 ssl 加密,因此使用加密密码。这是每次身份验证中使用的常用方法。对于第2点:我已经知道因素。但是api是从客户端提供的。实际上oaep是PKCS#1v1.5填充的较新版本。无论如何感谢您的帮助。您可以帮助解决这个问题吗?
-
您的代码以及您对 CodesInChaos 的评论都显示出对密码学的重大误解。也就是说,我认为你教 Codes 密码学是非常勇敢的。
-
在移动端,我使用以下在线 rsa 计算器检查了我的加密,这似乎都是正确的(nmichaels.org/rsa.py).So 我认为移动端存在字节到十六进制转换的问题,而服务器端存在反向问题。我尊重codeInChaos,但我只是评论为什么我应该代表它的安全性遵循该方法。这里是android端的rsa加密和服务器端解密的问题。不是缺点或优点。
标签: java android encryption cryptography