1.2.2 增加RSA签名

This commit is contained in:
maxf 2018-11-20 20:21:15 +08:00
parent 286c65b868
commit 3ba0e22e65
4 changed files with 170 additions and 6 deletions

View File

@ -1,6 +1,13 @@
yexuejc-base 更新记录
------------------
#### version 1.2.2
**time2018-11-20 20:20:12** <br/>
**branch** master <br/>
**update** <br/>
>1. 优化RSA 加解密
>1. 增加RSA 签名
#
#### version 1.2.1
**time2018-11-9 15:05:06** <br/>
**branch** master <br/>

View File

@ -6,7 +6,7 @@
<groupId>com.yexuejc.base</groupId>
<artifactId>yexuejc-base</artifactId>
<version>1.2.1</version>
<version>1.2.2</version>
<name>${project.artifactId}</name>

View File

@ -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";
/**
* 加密方式
* <pre>
* RSA 可选择isChangeSign 是否每次改变加密结果
* RSA/None/NoPadding 不改变加密结果
* RSA/ECB/PKCS1Padding 改变加密结果
* </pre>
*/
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<String, String> 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
* <p>
* 签名算法 {@link SignAlgorithm}
* </p>
*
* @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;
}
}

View File

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