diff --git a/UPDATE.md b/UPDATE.md
index 9919182..fbc09a5 100644
--- a/UPDATE.md
+++ b/UPDATE.md
@@ -1,6 +1,13 @@
yexuejc-base 更新记录
------------------
+#### version :1.2.2
+**time:2018-11-20 20:20:12**
+**branch:** master
+**update:**
+>1. 优化RSA 加解密
+>1. 增加RSA 签名
+#
#### version :1.2.1
**time:2018-11-9 15:05:06**
**branch:** master
diff --git a/pom.xml b/pom.xml
index 4364178..9115823 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
com.yexuejc.base
yexuejc-base
- 1.2.1
+ 1.2.2
${project.artifactId}
diff --git a/src/main/java/com/yexuejc/base/encrypt/RSA.java b/src/main/java/com/yexuejc/base/encrypt/RSA.java
index bbd5363..968d0fa 100644
--- a/src/main/java/com/yexuejc/base/encrypt/RSA.java
+++ b/src/main/java/com/yexuejc/base/encrypt/RSA.java
@@ -3,9 +3,12 @@ package com.yexuejc.base.encrypt;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.IOUtils;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
import javax.crypto.Cipher;
+import javax.crypto.NoSuchPaddingException;
import java.io.ByteArrayOutputStream;
+import java.io.UnsupportedEncodingException;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
@@ -27,6 +30,25 @@ public class RSA {
public static final String CHARSET = "UTF-8";
public static final String RSA_ALGORITHM = "RSA";
+ /**
+ * 加密方式
+ *
+ * RSA 可选择isChangeSign 是否每次改变加密结果
+ * RSA/None/NoPadding 不改变加密结果
+ * RSA/ECB/PKCS1Padding 改变加密结果
+ *
+ */
+ public static String RSA_ALGORITHM_ECB = "RSA";
+ /**
+ * 是否每次改变加密结果
+ * 只针对于RSA_ALGORITHM_ECB = "RSA"有效
+ */
+ public static boolean isChangeSign = true;
+ /**
+ * 签名算法
+ */
+ public static SignAlgorithm signAlgorithm = SignAlgorithm.SHA1withRSA;
+
public static Map initKeys(int keySize) {
//为RSA算法创建一个KeyPairGenerator对象
@@ -61,7 +83,7 @@ public class RSA {
* @param publicKey 密钥字符串(经过base64编码)
* @throws Exception
*/
- public static RSAPublicKey getPublicKey(String publicKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
+ public static RSAPublicKey getPublicKey(String publicKey) throws NoSuchAlgorithmException, InvalidKeySpecException{
//通过X509编码的Key指令获得公钥对象
KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKey));
@@ -92,7 +114,7 @@ public class RSA {
*/
public static String publicEncrypt(String data, RSAPublicKey publicKey) {
try {
- Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
+ Cipher cipher = getCipher();
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
return Base64.encodeBase64URLSafeString(rsaSplitCodec(cipher, Cipher.ENCRYPT_MODE, data.getBytes(CHARSET), publicKey.getModulus().bitLength()));
} catch (Exception e) {
@@ -109,7 +131,7 @@ public class RSA {
*/
public static String privateDecrypt(String data, RSAPrivateKey privateKey) {
try {
- Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
+ Cipher cipher = getCipher();
cipher.init(Cipher.DECRYPT_MODE, privateKey);
return new String(rsaSplitCodec(cipher, Cipher.DECRYPT_MODE, Base64.decodeBase64(data), privateKey.getModulus().bitLength()), CHARSET);
} catch (Exception e) {
@@ -117,6 +139,7 @@ public class RSA {
}
}
+
/**
* 私钥加密
*
@@ -127,7 +150,7 @@ public class RSA {
public static String privateEncrypt(String data, RSAPrivateKey privateKey) {
try {
- Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
+ Cipher cipher = getCipher();
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
return Base64.encodeBase64URLSafeString(rsaSplitCodec(cipher, Cipher.ENCRYPT_MODE, data.getBytes(CHARSET), privateKey.getModulus().bitLength()));
} catch (Exception e) {
@@ -145,7 +168,7 @@ public class RSA {
public static String publicDecrypt(String data, RSAPublicKey publicKey) {
try {
- Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
+ Cipher cipher = getCipher();
cipher.init(Cipher.DECRYPT_MODE, publicKey);
return new String(rsaSplitCodec(cipher, Cipher.DECRYPT_MODE, Base64.decodeBase64(data), publicKey.getModulus().bitLength()), CHARSET);
} catch (Exception e) {
@@ -153,6 +176,25 @@ public class RSA {
}
}
+ /**
+ * 获取 Cipher
+ *
+ * @return
+ * @throws NoSuchPaddingException
+ * @throws NoSuchAlgorithmException
+ * @throws NoSuchProviderException
+ */
+ private static Cipher getCipher() throws NoSuchPaddingException, NoSuchAlgorithmException, NoSuchProviderException {
+ Cipher cipher;
+ if ("RSA".equals(RSA_ALGORITHM_ECB) && isChangeSign) {
+ cipher = Cipher.getInstance(RSA_ALGORITHM_ECB);
+ } else {
+ Security.addProvider(new BouncyCastleProvider());
+ cipher = Cipher.getInstance(RSA_ALGORITHM_ECB, "BC");
+ }
+ return cipher;
+ }
+
private static byte[] rsaSplitCodec(Cipher cipher, int opmode, byte[] datas, int keySize) {
int maxBlock = 0;
if (opmode == Cipher.DECRYPT_MODE) {
@@ -183,4 +225,66 @@ public class RSA {
return resultDatas;
}
+ private static Signature signature;
+
+ /**
+ * 私钥签名:默认算法SHA1withRSA
+ *
+ * 签名算法 {@link SignAlgorithm}
+ *
+ *
+ * @param plaintext 签名字符串
+ * @param privateKey 签名私钥
+ * @return
+ * @throws NoSuchAlgorithmException
+ */
+ public static String sign(String plaintext, RSAPrivateKey privateKey) throws NoSuchAlgorithmException {
+ signature = Signature.getInstance(signAlgorithm.getValue());
+ String signBase64Str = "";
+
+ try {
+ signature.initSign(privateKey);
+ try {
+ signature.update(plaintext.getBytes(CHARSET));
+ } catch (UnsupportedEncodingException e) {
+ e.printStackTrace();
+ throw new RuntimeException("签名字符串[" + plaintext + "]的数据时发生异常", e);
+ }
+
+ signBase64Str = Base64.encodeBase64String(signature.sign());
+ return signBase64Str;
+ } catch (InvalidKeyException var6) {
+ var6.printStackTrace();
+ throw new RuntimeException("签名字符串[" + plaintext + "]的数据时发生异常", var6);
+ } catch (SignatureException var7) {
+ var7.printStackTrace();
+ throw new RuntimeException("签名字符串[" + plaintext + "]的数据时发生异常", var7);
+ }
+ }
+
+ /**
+ * 公钥校验签名
+ *
+ * @param plaintext 原串
+ * @param signStr 签名串
+ * @param publicKey 公钥
+ * @return
+ * @throws UnsupportedEncodingException
+ */
+ public static boolean verify(String plaintext, String signStr, RSAPublicKey publicKey) throws UnsupportedEncodingException {
+ boolean isValid = false;
+ try {
+ signature.initVerify(publicKey);
+ signature.update(plaintext.getBytes(CHARSET));
+ isValid = signature.verify(Base64.decodeBase64(signStr));
+ } catch (InvalidKeyException var6) {
+ var6.printStackTrace();
+ throw new RuntimeException("校验签名字符串[" + plaintext + "]的数据时发生异常", var6);
+ } catch (SignatureException var7) {
+ var7.printStackTrace();
+ throw new RuntimeException("校验签名字符串[" + plaintext + "]的数据时发生异常", var7);
+ }
+
+ return isValid;
+ }
}
diff --git a/src/main/java/com/yexuejc/base/encrypt/SignAlgorithm.java b/src/main/java/com/yexuejc/base/encrypt/SignAlgorithm.java
new file mode 100644
index 0000000..efbda90
--- /dev/null
+++ b/src/main/java/com/yexuejc/base/encrypt/SignAlgorithm.java
@@ -0,0 +1,53 @@
+package com.yexuejc.base.encrypt;
+
+/**
+ * 签名算法类型
+ * 参考Hutool
+ * see: https://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html#Signature
+ */
+public enum SignAlgorithm {
+ // The RSA signature algorithm
+ NONEwithRSA("NONEwithRSA"),
+
+ // The MD2/MD5 with RSA Encryption signature algorithm
+ MD2withRSA("MD2withRSA"),
+ MD5withRSA("MD5withRSA"),
+
+ // The signature algorithm with SHA-* and the RSA
+ SHA1withRSA("SHA1withRSA"),
+ SHA256withRSA("SHA256withRSA"),
+ SHA384withRSA("SHA384withRSA"),
+ SHA512withRSA("SHA512withRSA"),
+
+ // The Digital Signature Algorithm
+ NONEwithDSA("NONEwithDSA"),
+ // The DSA with SHA-1 signature algorithm
+ SHA1withDSA("SHA1withDSA"),
+
+ // The ECDSA signature algorithms
+ NONEwithECDSA("NONEwithECDSA"),
+ SHA1withECDSA("SHA1withECDSA"),
+ SHA256withECDSA("SHA256withECDSA"),
+ SHA384withECDSA("SHA384withECDSA"),
+ SHA512withECDSA("SHA512withECDSA");
+
+ private String value;
+
+ /**
+ * 构造
+ *
+ * @param value 算法字符表示,区分大小写
+ */
+ private SignAlgorithm(String value) {
+ this.value = value;
+ }
+
+ /**
+ * 获取算法字符串表示,区分大小写
+ *
+ * @return 算法字符串表示
+ */
+ public String getValue() {
+ return this.value;
+ }
+}