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; + } +}