diff --git a/lib_base/src/main/java/com/android/base/utils/security/AESUtils.java b/lib_base/src/main/java/com/android/base/utils/security/AESUtils.java
index 1d7ac61..a3c0dbb 100644
--- a/lib_base/src/main/java/com/android/base/utils/security/AESUtils.java
+++ b/lib_base/src/main/java/com/android/base/utils/security/AESUtils.java
@@ -1,5 +1,7 @@
package com.android.base.utils.security;
+import android.util.Base64;
+
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
@@ -12,7 +14,7 @@ import androidx.annotation.Nullable;
@SuppressWarnings("unused")
public class AESUtils {
- //算法/模式/填充
+ //算法/加密模式/填充模式
public static String AES = "AES";
public static String AES_CBC_ISO10126PADDING = "AES/CBC/ISO10126Padding";
public static String AES_CBC_NOPADDING = "AES/CBC/NoPadding";
@@ -69,4 +71,20 @@ public class AESUtils {
return null;
}
+ /**
+ * @param content base64 编码的密文
+ */
+ @Nullable
+ public static byte[] decryptData(String content, String algorithm, String password) {
+ try {
+ SecretKeySpec key = generateAESKey(algorithm, password);
+ Cipher cipher = Cipher.getInstance(algorithm);
+ cipher.init(Cipher.DECRYPT_MODE, key);
+ return cipher.doFinal(Base64.decode(content, Base64.DEFAULT));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
}
\ No newline at end of file
diff --git a/lib_base/src/main/java/com/android/base/utils/security/RSAUtils.java b/lib_base/src/main/java/com/android/base/utils/security/RSAUtils.java
index e1776e9..5a0367a 100644
--- a/lib_base/src/main/java/com/android/base/utils/security/RSAUtils.java
+++ b/lib_base/src/main/java/com/android/base/utils/security/RSAUtils.java
@@ -7,6 +7,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.math.BigInteger;
+import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
@@ -22,46 +23,47 @@ import javax.crypto.Cipher;
import androidx.annotation.Nullable;
+/**
+ * @see cryptography-changes-in-android-p.html
+ * @see Android使用RSA加密和解密cryptography-changes-in-android-p.html
+ * @see rsa-encryption-decryption-in-android/12474193
+ * @see secure-data-in-android-encrypting-large-data-dda256a55b36
+ */
@SuppressWarnings("WeakerAccess,unused")
public final class RSAUtils {
private final static String KEY_PAIR = "RSA";
- private final static String CIPHER = "RSA/ECB/PKCS1Padding";
/**
- * 随机生成RSA密钥对(默认密钥长度为1024)
+ * 默认
*/
- public static KeyPair generateRSAKeyPair() {
- return generateRSAKeyPair(1024);
- }
+ public static final String TRANSFORMATION_DEFAULT = KEY_PAIR;
/**
- * 随机生成RSA密钥对
- *
- * @param keyLength 密钥长度,范围:512~2048,一般1024
+ * JDK标准
*/
- public static KeyPair generateRSAKeyPair(int keyLength) {
- try {
- KeyPairGenerator kpg = KeyPairGenerator.getInstance(KEY_PAIR);
- kpg.initialize(keyLength);
- return kpg.genKeyPair();
- } catch (NoSuchAlgorithmException e) {
- e.printStackTrace();
- return null;
- }
- }
+ public static final String TRANSFORMATION_ECB_PKCS1PADDING = "RSA/ECB/PKCS1Padding";
/**
- * 用公钥加密,每次加密的字节数,不能超过密钥的长度值减去11
+ * Android标准
+ */
+ public static final String TRANSFORMATION_ECB_NOPADDING = "RSA/ECB/NoPadding";
+
+ ///////////////////////////////////////////////////////////////////////////
+ // 加解密
+ ///////////////////////////////////////////////////////////////////////////
+
+ /**
+ * 用公钥加密,每次加密的字节数,不能超过密钥的长度值减去 11。
*
* @param data 需加密数据的byte数据
* @param publicKey 公钥
* @return 加密后的byte型数据
*/
@Nullable
- public static byte[] encryptData(byte[] data, PublicKey publicKey) {
+ public static byte[] encryptData(String transformation, byte[] data, PublicKey publicKey) {
try {
- Cipher cipher = Cipher.getInstance(CIPHER);
+ Cipher cipher = Cipher.getInstance(transformation);
// 编码前设定编码方式及密钥
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
// 传入编码数据并返回编码结果
@@ -75,13 +77,13 @@ public final class RSAUtils {
/**
* 用私钥解密
*
- * @param encryptedData 经过encryptedData()加密返回的byte数据
+ * @param encryptedData 经过 encryptedData() 加密返回的 byte 数据
* @param privateKey 私钥
*/
@Nullable
- public static byte[] decryptData(byte[] encryptedData, PrivateKey privateKey) {
+ public static byte[] decryptData(String transformation, byte[] encryptedData, PrivateKey privateKey) {
try {
- Cipher cipher = Cipher.getInstance(CIPHER);
+ Cipher cipher = Cipher.getInstance(transformation);
cipher.init(Cipher.DECRYPT_MODE, privateKey);
return cipher.doFinal(encryptedData);
} catch (Exception e) {
@@ -90,7 +92,56 @@ public final class RSAUtils {
}
/**
- * 通过公钥byte[](publicKey.getEncoded())将公钥还原,适用于RSA算法
+ * 用公钥解密
+ *
+ * @param encryptedData 经过 encryptedData() 加密返回的 byte 数据
+ * @param publicKey 公钥
+ */
+ @Nullable
+ public static String decryptData(String transformation, byte[] encryptedData, PublicKey publicKey) {
+ try {
+ Cipher cipher = Cipher.getInstance(transformation);
+ cipher.init(Cipher.DECRYPT_MODE, publicKey);
+ return new String(cipher.doFinal(encryptedData), StandardCharsets.UTF_8);
+ } catch (Exception e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // 生成新的私钥/密钥
+ ///////////////////////////////////////////////////////////////////////////
+
+ /**
+ * 随机生成 RSA 密钥对(默认密钥长度为 1024)
+ */
+ public static KeyPair generateRSAKeyPair() {
+ return generateRSAKeyPair(1024);
+ }
+
+ /**
+ * 随机生成 RSA 密钥对
+ *
+ * @param keyLength 密钥长度,范围:512~2048,一般1024
+ */
+ public static KeyPair generateRSAKeyPair(int keyLength) {
+ try {
+ KeyPairGenerator kpg = KeyPairGenerator.getInstance(KEY_PAIR);
+ kpg.initialize(keyLength);
+ return kpg.genKeyPair();
+ } catch (NoSuchAlgorithmException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // 根据key创建 PublicKey 或 PrivateKey
+ ///////////////////////////////////////////////////////////////////////////
+
+ /**
+ * 通过公钥 byte[](publicKey.getEncoded()) 将公钥还原,适用于 RSA 算法。
*
* @throws NoSuchAlgorithmException NoSuchAlgorithm
* @throws InvalidKeySpecException InvalidKeySpec
@@ -102,7 +153,7 @@ public final class RSAUtils {
}
/**
- * 通过私钥byte[]将公钥还原,适用于RSA算法
+ * 通过私钥 byte[] 将私钥还原,适用于 RSA 算法。
*
* @throws NoSuchAlgorithmException NoSuchAlgorithm
* @throws InvalidKeySpecException InvalidKeySpec
@@ -114,7 +165,7 @@ public final class RSAUtils {
}
/**
- * 使用N、e值还原公钥
+ * 使用 N、e 值还原公钥
*
* @throws NoSuchAlgorithmException NoSuchAlgorithm
* @throws InvalidKeySpecException InvalidKeySpec
@@ -128,7 +179,7 @@ public final class RSAUtils {
}
/**
- * 使用N、d值还原私钥
+ * 使用 N、d 值还原私钥
*
* @throws NoSuchAlgorithmException NoSuchAlgorithm
* @throws InvalidKeySpecException InvalidKeySpec
@@ -144,13 +195,13 @@ public final class RSAUtils {
/**
* 从字符串中加载公钥
*
- * @param publicKeyStr 公钥数据字符串
+ * @param publicKeyStr Base64 编码的公钥数据字符串
* @throws Exception 加载公钥时产生的异常
*/
public static PublicKey loadPublicKey(String publicKeyStr) throws Exception {
try {
byte[] buffer = Base64.decode(publicKeyStr, Base64.DEFAULT);
- KeyFactory keyFactory = KeyFactory.getInstance(KEY_PAIR, "BC");
+ KeyFactory keyFactory = KeyFactory.getInstance(KEY_PAIR);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer);
return keyFactory.generatePublic(keySpec);
} catch (NoSuchAlgorithmException e) {
@@ -164,7 +215,9 @@ public final class RSAUtils {
}
/**
- * 从字符串中加载私钥,加载时使用的是PKCS8EncodedKeySpec(PKCS#8编码的Key指令)。
+ * 从字符串中加载私钥,加载时使用的是 PKCS8EncodedKeySpec(PKCS#8编码的Key指令)。
+ *
+ * @param privateKeyStr Base64 编码的私钥数据字符串
*/
public static PrivateKey loadPrivateKey(String privateKeyStr) throws Exception {
try {
diff --git a/lib_base/src/main/java/com/android/base/utils/security/SimpleRsa.java b/lib_base/src/main/java/com/android/base/utils/security/SimpleRsa.java
deleted file mode 100644
index e1a0dfd..0000000
--- a/lib_base/src/main/java/com/android/base/utils/security/SimpleRsa.java
+++ /dev/null
@@ -1,100 +0,0 @@
-package com.android.base.utils.security;
-
-import android.os.Build;
-import android.util.Base64;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.InputStream;
-import java.nio.charset.StandardCharsets;
-import java.security.KeyFactory;
-import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
-import java.security.PublicKey;
-import java.security.spec.InvalidKeySpecException;
-import java.security.spec.X509EncodedKeySpec;
-
-import javax.crypto.Cipher;
-
-import androidx.annotation.Nullable;
-
-
-public class SimpleRsa {
-
- private static final String ALGORITHM = "RSA";
- private static final String TRANSFORMATION = "RSA/ECB/PKCS1Padding";
-
- /**
- * 得到公钥
- *
- * @param algorithm 算法
- * @param bysKey key
- * @return 公钥
- */
- private static PublicKey getPublicKeyFromX509(String algorithm, String bysKey) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchProviderException {
- byte[] decodedKey = Base64.decode(bysKey, Base64.DEFAULT);
- X509EncodedKeySpec x509 = new X509EncodedKeySpec(decodedKey);
- KeyFactory keyFactory;
- //适配Android P及以后版本,否则报错NoSuchAlgorithmException
- //https://android-developers.googleblog.com/2018/03/cryptography-changes-in-android-p.html
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
- keyFactory = KeyFactory.getInstance(algorithm);
- } else {
- keyFactory = KeyFactory.getInstance(algorithm, "BC");
- }
- return keyFactory.generatePublic(x509);
- }
-
- /**
- * 使用公钥加密
- *
- * @param content 加密字符串
- * @return 加密后的字符串
- */
- @Nullable
- public static String encryptByPublic(String content, String RSA_PUBLIC_KEY) {
- try {
- PublicKey pubKey = getPublicKeyFromX509(ALGORITHM, RSA_PUBLIC_KEY);
- Cipher cipher = Cipher.getInstance(TRANSFORMATION);
- cipher.init(Cipher.ENCRYPT_MODE, pubKey);
- byte[] plaintext = content.getBytes(StandardCharsets.UTF_8);
- byte[] output = cipher.doFinal(plaintext);
- return new String(Base64.encode(output, Base64.DEFAULT));
- } catch (Exception e) {
- return null;
- }
- }
-
- /**
- * 使用公钥解密
- *
- * @param content 密文
- * @return 解密后的字符串
- */
- @Nullable
- public static String decryptByPublic(String content, String RSA_PUBLIC_KEY) {
- try {
- PublicKey pubkey = getPublicKeyFromX509(ALGORITHM, RSA_PUBLIC_KEY);
- Cipher cipher = Cipher.getInstance(TRANSFORMATION);
- cipher.init(Cipher.DECRYPT_MODE, pubkey);
- InputStream ins = new ByteArrayInputStream(Base64.decode(content, Base64.DEFAULT));
- ByteArrayOutputStream writer = new ByteArrayOutputStream();
- byte[] buf = new byte[128];
- int offset;
- while ((offset = ins.read(buf)) != -1) {
- byte[] block;
- if (buf.length == offset) {
- block = buf;
- } else {
- block = new byte[offset];
- System.arraycopy(buf, 0, block, 0, offset);
- }
- writer.write(cipher.doFinal(block));
- }
- return new String(writer.toByteArray(), StandardCharsets.UTF_8);
- } catch (Exception e) {
- return null;
- }
- }
-
-}
\ No newline at end of file