1. 問題現象
話說近日博主的團隊中,有一個小盆友遇到了一個問題,即使用RSA進行加解密的時候,拋異常了:
java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException: DerInputStream.getLength(): lengthTag=118, too big.at sun.security.rsa.RSAKeyFactory.engineGeneratePublic(RSAKeyFactory.java:205)at java.security.KeyFactory.generatePublic(KeyFactory.java:334)at com.dfwy.common.core.utils.sign.SignHelper.main(SignHelper.java:205)
Caused by: java.security.InvalidKeyException: IOException: DerInputStream.getLength(): lengthTag=118, too big.at sun.security.x509.X509Key.decode(X509Key.java:398)at sun.security.x509.X509Key.decode(X509Key.java:403)at sun.security.rsa.RSAPublicKeyImpl.<init>(RSAPublicKeyImpl.java:86)at sun.security.rsa.RSAKeyFactory.generatePublic(RSAKeyFactory.java:298)at sun.security.rsa.RSAKeyFactory.engineGeneratePublic(RSAKeyFactory.java:201)... 2 more
博主眨眼一看,xx too big
,難道是content太長了? 顯然不像,于是盤問了幾句。
2. 解決過程
在盤問過程中,原來是在使用對方提供的證書過程中,出現了問題。
我們使用RSA公鑰加密的時候,通常需要對方提供證書(公鑰)。沒有公鑰,我們無法完成加、解密。博主正好有一篇博文,可以參考,回看請速戳:微服務實戰系列之加密RSA。
我們在使用公鑰解密時,對方提供的一般是公鑰證書(文件格式不一,與支持的web容器有關),博主以PEM
文件為例(Nginx一般使用pem)。
PEM
文件其實是把文件的編碼從DER轉碼為base64字符格式。因此在實際使用時,需要把它逆向轉回DER編碼,再轉為java.security.PublicKey
。接著我們可以愉快的獲取到公鑰進行加密操作了。
//獲取pubKey ,參考代碼
String pKey = "efa9c1223g5eced71940ff4029a7baa5ccc7e66021a03ss5ff29cb84c";
byte[] keyBytes = Base64.decode(pKey);
X509EncodedKeySpec x509 = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey pubKey = keyFactory.generatePublic(x509 );
3. 總結經驗
所以我們在使用RSA加解密時,如遇到諸如xx too big
的問題,可以從以下思路展開:
-
配置問題
比如我們通常使用springboot構建微服務,那是不是相關證書已支持等等,請檢查。 -
證書文件問題
比如對方提供的證書文件是否正確、有效。如證書不對,其他皆枉然。RSA公鑰和私鑰是天生一對,誰也離不開誰。如其中一個出了問題,另外一個必然可以“六親不認”
。 -
代碼
是否根據證書格式進行相應的編碼轉換,轉換是否正確等等,請檢查。