我正在对 Phoenix 网络服务器上的一些数据进行加密:
private_key = ExPublicKey.load!("private.pem")
token = %{username: user.username, mobile_phone: user.mobile_phone, email: user.email}
payload = Poison.encode!(token)
{:ok, signature} = ExPublicKey.encrypt_private(payload, private_key)
并在Java(实际上是Android)客户端上解密如下:
try {
byte[] keyBytes = Base64.decode(Constants.RSA_PUBLIC_KEY.getBytes(), Base64.DEFAULT);
X509EncodedKeySpec encodedKeySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey publicKey = keyFactory.generatePublic(encodedKeySpec) ;
Cipher cipher = Cipher.getInstance("RSA") ;
cipher.init(Cipher.DECRYPT_MODE, publicKey) ;
//
Log.e(DEBUG_TAG, jwt) ; // received token
String payload = new String(Base64.decode(jwt, Base64.DEFAULT), "UTF-8") ; // java does UTF16, elixir does UTF8
Log.e(DEBUG_TAG, payload) ; // base64 decoded token
byte[] cipherText = cipher.doFinal(payload.getBytes("UTF-8")) ; // decrypt
String token = new String(Base64.decode(cipherText, Base64.URL_SAFE), "UTF-8") ; // cipher text is urlencoded
Log.e(DEBUG_TAG, token) ;
return null ;
} catch (Exception e) {
e.printStackTrace();
}
Phoenix 端没有异常,但尝试在 java 上解密 token 会导致异常:
java.lang.ArrayIndexOutOfBoundsException: too much data for RSA block
at com.android.org.bouncycastle.jcajce.provider.asymmetric.rsa.CipherSpi.engineDoFinal(CipherSpi.java:459)
at javax.crypto.Cipher.doFinal(Cipher.java:1502
如果输入对于 RSA 模数来说太大,它应该会导致网络服务器上出现错误。所以我想知道到底出了什么问题。
更新:库似乎存在问题。通过对某些数据的 SHA256 摘要进行签名而生成的输出返回 344 字节,而所使用的 key 长度应该为 256 字节。恢复使用 Erlang 的 public_key
模块,现在工作正常。
最佳答案
不清楚真正的目的,这让事情变得困难,但如果你试图发行 JSON Web Tokens,看起来,你的实现是完全错误的
JWT 经过数字签名,未加密
用私钥加密!=数字签名
您正在“解密”整个 token ,而不是验证签名,签名应该是 JSON Web token 的最后一部分,如
hhhh.pppp.ssss
。
@zaph 描述了该错误,但如果您使用数字签名,则不会发生该错误。无法修复您的代码,因此请考虑重新实现它
关于Java解密RSA加密数据ArrayIndexOutOfBoundsException : too much data for RSA block,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45132082/