讀取私鑰時報錯
java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException : algid parse error, not a sequence
at sun.security.rsa.RSAKeyFactory.engineGeneratePrivate(RSAKeyFactory.java:217)
at java.security.KeyFactory.generatePrivate(KeyFactory.java:372)
複製程式碼
在獲取私鑰時需增加以下程式碼
if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) {
Security.addProvider(new BouncyCastleProvider());
}
//需要導包
api 'org.bouncycastle:bcprov-jdk16:1.46'
複製程式碼
載入的字串大於117時會報錯
需要分段加密 公鑰加密時,加密的最長位元組時117個 私鑰解密出來長度都是128 注意:必須在每段加密完成後再用Base64加密,否則Base64解密時會出錯
獲取私鑰時報
IllegalArgumentException: Illegal base64 character d
複製程式碼
祕鑰裡面有換行或其他符號,去掉即可
解密時報BadPaddingException
javax.crypto.BadPaddingException: Decryption error
at sun.security.rsa.RSAPadding.unpadV15(RSAPadding.java:380)
at sun.security.rsa.RSAPadding.unpad(RSAPadding.java:291)
at com.sun.crypto.provider.RSACipher.doFinal(RSACipher.java:363)
at com.sun.crypto.provider.RSACipher.engineDoFinal(RSACipher.java:389)
at javax.crypto.Cipher.doFinal(Cipher.java:2223)
複製程式碼
加密和解密的填充模式不一致導致的
統一對齊方式:"RSA/NONE/PKCS1Padding"
RSA加密完整程式碼
// 返回 RSA 加密的結果
public static String encryptRSA(Key publicKey, String text) {
try {
Cipher rsa = Cipher.getInstance("RSA/NONE/PKCS1Padding");
rsa.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] originBytes = text.getBytes();
//大於117時進行分段 加密
int subLength = originBytes.length / 117 + (originBytes.length % 117 == 0 ? 0 : 1);
byte[] finalByte = new byte[128 * subLength];
for (int i = 0; i < subLength; i++) {
//需要加密的位元組長度
int len = i == subLength - 1 ? (originBytes.length - i * 117) : 117;
//加密完成的位元組陣列
byte[] doFinal = rsa.doFinal(originBytes, i * 117, len);
//複製這次加密的陣列
System.arraycopy(doFinal, 0, finalByte, i * 128, doFinal.length);
}
return new String(Base64Utlis.encode(finalByte, Base64Utlis.NO_WRAP),
Charset.forName("UTF-8"));
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 返回 RSA 解密的結果
*/
public static String decryptRSA(Key privateKey, String content) {
try {
byte[] text = Base64Utlis.decode(content, Base64Utlis.NO_WRAP);
Cipher rsa = Cipher.getInstance("RSA/NONE/PKCS1Padding");
rsa.init(Cipher.DECRYPT_MODE, privateKey);
//大於128時進行分段 解密
int subLength = text.length / 128;
StringBuilder finalString = new StringBuilder();
for (int i = 0; i < subLength; i++) {
byte[] doFinal = rsa.doFinal(text, i * 128, 128);
finalString.append(new String(doFinal, Charset.forName("UTF-8")));
}
return finalString.toString();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
//根據檔案路徑返回公匙
public static PublicKey readPublicKey(String filePath) throws IOException {
FileInputStream fis = new FileInputStream(new File(filePath));
return readPublicKey(fis);
}
// 根據輸入流返回公匙
public static PublicKey readPublicKey(InputStream input) throws IOException {
final ByteArrayOutputStream output = new ByteArrayOutputStream();
int n = 0;
final byte[] buffer = new byte[1024 * 4];
while (-1 != (n = input.read(buffer))) {
output.write(buffer, 0, n);
}
byte[] keyBytes = output.toByteArray();
X509EncodedKeySpec spec =
new X509EncodedKeySpec(Base64Utlis.decode(keyBytes, Base64Utlis.NO_WRAP));
try {
KeyFactory kf = KeyFactory.getInstance("RSA");
return kf.generatePublic(spec);
} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
e.printStackTrace();
}
return null;
}
// 根據檔案路徑返回私匙
public static PrivateKey readPrivateKey(String filePath) throws IOException {
FileInputStream fis = new FileInputStream(new File(filePath));
return readPrivateKey(fis);
}
// 根據輸入流返回私匙
public static PrivateKey readPrivateKey(InputStream input) throws IOException {
final ByteArrayOutputStream output = new ByteArrayOutputStream();
int n = 0;
final byte[] buffer = new byte[1024 * 4];
while (-1 != (n = input.read(buffer))) {
output.write(buffer, 0, n);
}
if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) {
Security.addProvider(new BouncyCastleProvider());
}
byte[] keyBytes = output.toByteArray();
PKCS8EncodedKeySpec spec =
new PKCS8EncodedKeySpec(Base64Utlis.decode(keyBytes, Base64Utlis.NO_WRAP));
try {
KeyFactory kf = KeyFactory.getInstance("RSA");
return kf.generatePrivate(spec);
} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
e.printStackTrace();
}
return null;
}
複製程式碼