mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-07-21 15:09:48 +08:00
add jwt
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<packaging>jar</packaging>
|
||||
@@ -27,12 +27,12 @@
|
||||
<artifactId>hutool-core</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
<artifactId>bcprov-jdk15to18</artifactId>
|
||||
<version>${bouncycastle.version}</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
<artifactId>bcprov-jdk15to18</artifactId>
|
||||
<version>${bouncycastle.version}</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
@@ -367,6 +367,7 @@ public class KeyUtil {
|
||||
// ECIES算法对KEY的长度有要求,此处默认256
|
||||
keySize = 256;
|
||||
}
|
||||
|
||||
return generateKeyPair(algorithm, keySize);
|
||||
}
|
||||
|
||||
@@ -622,6 +623,7 @@ public class KeyUtil {
|
||||
* @since 4.5.2
|
||||
*/
|
||||
public static String getMainAlgorithm(String algorithm) {
|
||||
Assert.notBlank(algorithm, "Algorithm must be not blank!");
|
||||
final int slashIndex = algorithm.indexOf(CharUtil.SLASH);
|
||||
if (slashIndex > 0) {
|
||||
return algorithm.substring(0, slashIndex);
|
||||
|
@@ -1072,6 +1072,26 @@ public class SecureUtil {
|
||||
return mac;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建{@link Signature}
|
||||
*
|
||||
* @param algorithm 算法
|
||||
* @return {@link Signature}
|
||||
* @since 5.7.0
|
||||
*/
|
||||
public static Signature createSignature(String algorithm) {
|
||||
final Provider provider = GlobalBouncyCastleProvider.INSTANCE.getProvider();
|
||||
|
||||
Signature signature;
|
||||
try {
|
||||
signature = (null == provider) ? Signature.getInstance(algorithm) : Signature.getInstance(algorithm, provider);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new CryptoException(e);
|
||||
}
|
||||
|
||||
return signature;
|
||||
}
|
||||
|
||||
/**
|
||||
* RC4算法
|
||||
*
|
||||
|
@@ -1,8 +1,19 @@
|
||||
package cn.hutool.crypto.asymmetric;
|
||||
|
||||
import cn.hutool.core.codec.Base64;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import cn.hutool.core.util.CharsetUtil;
|
||||
import cn.hutool.core.util.HexUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.crypto.CryptoException;
|
||||
import cn.hutool.crypto.SecureUtil;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.Charset;
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.KeyPair;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
import java.security.Signature;
|
||||
@@ -11,14 +22,9 @@ import java.security.cert.X509Certificate;
|
||||
import java.security.spec.AlgorithmParameterSpec;
|
||||
import java.util.Set;
|
||||
|
||||
import cn.hutool.core.codec.Base64;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.crypto.CryptoException;
|
||||
import cn.hutool.crypto.SecureUtil;
|
||||
|
||||
/**
|
||||
* 签名包装,{@link Signature} 包装类
|
||||
*
|
||||
*
|
||||
* @author looly
|
||||
* @since 3.3.0
|
||||
*/
|
||||
@@ -30,7 +36,7 @@ public class Sign extends BaseAsymmetric<Sign> {
|
||||
// ------------------------------------------------------------------ Constructor start
|
||||
/**
|
||||
* 构造,创建新的私钥公钥对
|
||||
*
|
||||
*
|
||||
* @param algorithm {@link SignAlgorithm}
|
||||
*/
|
||||
public Sign(SignAlgorithm algorithm) {
|
||||
@@ -39,7 +45,7 @@ public class Sign extends BaseAsymmetric<Sign> {
|
||||
|
||||
/**
|
||||
* 构造,创建新的私钥公钥对
|
||||
*
|
||||
*
|
||||
* @param algorithm 算法
|
||||
*/
|
||||
public Sign(String algorithm) {
|
||||
@@ -49,7 +55,7 @@ public class Sign extends BaseAsymmetric<Sign> {
|
||||
/**
|
||||
* 构造 私钥和公钥同时为空时生成一对新的私钥和公钥<br>
|
||||
* 私钥和公钥可以单独传入一个,如此则只能使用此钥匙来做签名或验证
|
||||
*
|
||||
*
|
||||
* @param algorithm {@link SignAlgorithm}
|
||||
* @param privateKeyStr 私钥Hex或Base64表示
|
||||
* @param publicKeyStr 公钥Hex或Base64表示
|
||||
@@ -61,7 +67,7 @@ public class Sign extends BaseAsymmetric<Sign> {
|
||||
/**
|
||||
* 构造 私钥和公钥同时为空时生成一对新的私钥和公钥<br>
|
||||
* 私钥和公钥可以单独传入一个,如此则只能使用此钥匙来做签名或验证
|
||||
*
|
||||
*
|
||||
* @param algorithm {@link SignAlgorithm}
|
||||
* @param privateKey 私钥
|
||||
* @param publicKey 公钥
|
||||
@@ -69,11 +75,11 @@ public class Sign extends BaseAsymmetric<Sign> {
|
||||
public Sign(SignAlgorithm algorithm, byte[] privateKey, byte[] publicKey) {
|
||||
this(algorithm.getValue(), privateKey, publicKey);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 构造 私钥和公钥同时为空时生成一对新的私钥和公钥<br>
|
||||
* 私钥和公钥可以单独传入一个,如此则只能使用此钥匙来做签名或验证
|
||||
*
|
||||
*
|
||||
* @param algorithm {@link SignAlgorithm}
|
||||
* @param keyPair 密钥对(包括公钥和私钥)
|
||||
*/
|
||||
@@ -84,7 +90,7 @@ public class Sign extends BaseAsymmetric<Sign> {
|
||||
/**
|
||||
* 构造 私钥和公钥同时为空时生成一对新的私钥和公钥<br>
|
||||
* 私钥和公钥可以单独传入一个,如此则只能使用此钥匙来做签名或验证
|
||||
*
|
||||
*
|
||||
* @param algorithm {@link SignAlgorithm}
|
||||
* @param privateKey 私钥
|
||||
* @param publicKey 公钥
|
||||
@@ -96,7 +102,7 @@ public class Sign extends BaseAsymmetric<Sign> {
|
||||
/**
|
||||
* 构造 私钥和公钥同时为空时生成一对新的私钥和公钥<br>
|
||||
* 私钥和公钥可以单独传入一个,如此则只能使用此钥匙来做签名或验证
|
||||
*
|
||||
*
|
||||
* @param algorithm 非对称加密算法
|
||||
* @param privateKeyBase64 私钥Base64
|
||||
* @param publicKeyBase64 公钥Base64
|
||||
@@ -107,10 +113,10 @@ public class Sign extends BaseAsymmetric<Sign> {
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
*
|
||||
* 私钥和公钥同时为空时生成一对新的私钥和公钥<br>
|
||||
* 私钥和公钥可以单独传入一个,如此则只能使用此钥匙来做签名或验证
|
||||
*
|
||||
*
|
||||
* @param algorithm 算法
|
||||
* @param privateKey 私钥
|
||||
* @param publicKey 公钥
|
||||
@@ -121,11 +127,11 @@ public class Sign extends BaseAsymmetric<Sign> {
|
||||
SecureUtil.generatePublicKey(algorithm, publicKey)//
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 构造 私钥和公钥同时为空时生成一对新的私钥和公钥<br>
|
||||
* 私钥和公钥可以单独传入一个,如此则只能使用此钥匙来做签名或验证
|
||||
*
|
||||
*
|
||||
* @param algorithm 算法,见{@link SignAlgorithm}
|
||||
* @param keyPair 密钥对(包括公钥和私钥)
|
||||
*/
|
||||
@@ -135,10 +141,10 @@ public class Sign extends BaseAsymmetric<Sign> {
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
*
|
||||
* 私钥和公钥同时为空时生成一对新的私钥和公钥<br>
|
||||
* 私钥和公钥可以单独传入一个,如此则只能使用此钥匙来做签名或验证
|
||||
*
|
||||
*
|
||||
* @param algorithm 算法
|
||||
* @param privateKey 私钥
|
||||
* @param publicKey 公钥
|
||||
@@ -147,10 +153,10 @@ public class Sign extends BaseAsymmetric<Sign> {
|
||||
super(algorithm, privateKey, publicKey);
|
||||
}
|
||||
// ------------------------------------------------------------------ Constructor end
|
||||
|
||||
|
||||
/**
|
||||
* 初始化
|
||||
*
|
||||
*
|
||||
* @param algorithm 算法
|
||||
* @param privateKey 私钥
|
||||
* @param publicKey 公钥
|
||||
@@ -158,18 +164,14 @@ public class Sign extends BaseAsymmetric<Sign> {
|
||||
*/
|
||||
@Override
|
||||
public Sign init(String algorithm, PrivateKey privateKey, PublicKey publicKey) {
|
||||
try {
|
||||
signature = Signature.getInstance(algorithm);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new CryptoException(e);
|
||||
}
|
||||
signature = SecureUtil.createSignature(algorithm);
|
||||
super.init(algorithm, privateKey, publicKey);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 设置签名的参数
|
||||
*
|
||||
*
|
||||
* @param params {@link AlgorithmParameterSpec}
|
||||
* @return this
|
||||
* @since 4.6.5
|
||||
@@ -184,18 +186,138 @@ public class Sign extends BaseAsymmetric<Sign> {
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------- Sign and Verify
|
||||
/**
|
||||
* 生成文件签名
|
||||
*
|
||||
* @param data 被签名数据
|
||||
* @param charset 编码
|
||||
* @return 签名
|
||||
* @since 5.7.0
|
||||
*/
|
||||
public byte[] sign(String data, Charset charset) {
|
||||
return sign(StrUtil.bytes(data, charset));
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成文件签名
|
||||
*
|
||||
* @param data 被签名数据
|
||||
* @return 签名
|
||||
* @since 5.7.0
|
||||
*/
|
||||
public byte[] sign(String data) {
|
||||
return sign(data, CharsetUtil.CHARSET_UTF_8);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成文件签名,并转为16进制字符串
|
||||
*
|
||||
* @param data 被签名数据
|
||||
* @param charset 编码
|
||||
* @return 签名
|
||||
* @since 5.7.0
|
||||
*/
|
||||
public String signHex(String data, Charset charset) {
|
||||
return HexUtil.encodeHexStr(sign(data, charset));
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成文件签名
|
||||
*
|
||||
* @param data 被签名数据
|
||||
* @return 签名
|
||||
* @since 5.7.0
|
||||
*/
|
||||
public String signHex(String data) {
|
||||
return signHex(data, CharsetUtil.CHARSET_UTF_8);
|
||||
}
|
||||
|
||||
/**
|
||||
* 用私钥对信息生成数字签名
|
||||
*
|
||||
*
|
||||
* @param data 加密数据
|
||||
* @return 签名
|
||||
*/
|
||||
public byte[] sign(byte[] data) {
|
||||
return sign(new ByteArrayInputStream(data), -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成签名,并转为16进制字符串<br>
|
||||
*
|
||||
* @param data 被签名数据
|
||||
* @return 签名
|
||||
* @since 5.7.0
|
||||
*/
|
||||
public String signHex(byte[] data) {
|
||||
return HexUtil.encodeHexStr(sign(data));
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成签名,并转为16进制字符串<br>
|
||||
* 使用默认缓存大小,见 {@link IoUtil#DEFAULT_BUFFER_SIZE}
|
||||
*
|
||||
* @param data 被签名数据
|
||||
* @return 签名
|
||||
* @since 5.7.0
|
||||
*/
|
||||
public String signHex(InputStream data) {
|
||||
return HexUtil.encodeHexStr(sign(data));
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成签名,使用默认缓存大小,见 {@link IoUtil#DEFAULT_BUFFER_SIZE}
|
||||
*
|
||||
* @param data {@link InputStream} 数据流
|
||||
* @return 签名bytes
|
||||
* @since 5.7.0
|
||||
*/
|
||||
public byte[] sign(InputStream data) {
|
||||
return sign(data, IoUtil.DEFAULT_BUFFER_SIZE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成签名,并转为16进制字符串<br>
|
||||
* 使用默认缓存大小,见 {@link IoUtil#DEFAULT_BUFFER_SIZE}
|
||||
*
|
||||
* @param data 被签名数据
|
||||
* @param bufferLength 缓存长度,不足1使用 {@link IoUtil#DEFAULT_BUFFER_SIZE} 做为默认值
|
||||
* @return 签名
|
||||
* @since 5.7.0
|
||||
*/
|
||||
public String digestHex(InputStream data, int bufferLength) {
|
||||
return HexUtil.encodeHexStr(sign(data, bufferLength));
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成签名
|
||||
*
|
||||
* @param data {@link InputStream} 数据流
|
||||
* @param bufferLength 缓存长度,不足1使用 {@link IoUtil#DEFAULT_BUFFER_SIZE} 做为默认值
|
||||
* @return 签名bytes
|
||||
* @since 5.7.0
|
||||
*/
|
||||
public byte[] sign(InputStream data, int bufferLength){
|
||||
if (bufferLength < 1) {
|
||||
bufferLength = IoUtil.DEFAULT_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
final byte[] buffer = new byte[bufferLength];
|
||||
lock.lock();
|
||||
try {
|
||||
signature.initSign(this.privateKey);
|
||||
signature.update(data);
|
||||
return signature.sign();
|
||||
byte[] result;
|
||||
try {
|
||||
int read = data.read(buffer, 0, bufferLength);
|
||||
while (read > -1) {
|
||||
signature.update(buffer, 0, read);
|
||||
read = data.read(buffer, 0, bufferLength);
|
||||
}
|
||||
result = signature.sign();
|
||||
} catch (Exception e) {
|
||||
throw new CryptoException(e);
|
||||
}
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
throw new CryptoException(e);
|
||||
} finally {
|
||||
@@ -205,7 +327,7 @@ public class Sign extends BaseAsymmetric<Sign> {
|
||||
|
||||
/**
|
||||
* 用公钥检验数字签名的合法性
|
||||
*
|
||||
*
|
||||
* @param data 数据
|
||||
* @param sign 签名
|
||||
* @return 是否验证通过
|
||||
@@ -225,7 +347,7 @@ public class Sign extends BaseAsymmetric<Sign> {
|
||||
|
||||
/**
|
||||
* 获得签名对象
|
||||
*
|
||||
*
|
||||
* @return {@link Signature}
|
||||
*/
|
||||
public Signature getSignature() {
|
||||
@@ -234,7 +356,7 @@ public class Sign extends BaseAsymmetric<Sign> {
|
||||
|
||||
/**
|
||||
* 设置签名
|
||||
*
|
||||
*
|
||||
* @param signature 签名对象 {@link Signature}
|
||||
* @return 自身 {@link AsymmetricCrypto}
|
||||
*/
|
||||
@@ -246,7 +368,7 @@ public class Sign extends BaseAsymmetric<Sign> {
|
||||
/**
|
||||
* 设置{@link Certificate} 为PublicKey<br>
|
||||
* 如果Certificate是X509Certificate,我们需要检查是否有密钥扩展
|
||||
*
|
||||
*
|
||||
* @param certificate {@link Certificate}
|
||||
* @return this
|
||||
*/
|
||||
|
@@ -3,41 +3,45 @@ package cn.hutool.crypto.asymmetric;
|
||||
/**
|
||||
* 签名算法类型<br>
|
||||
* see: https://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html#Signature
|
||||
*
|
||||
* @author Looly
|
||||
*
|
||||
* @author Looly
|
||||
*/
|
||||
public enum SignAlgorithm {
|
||||
// The RSA signature algorithm
|
||||
NONEwithRSA("NONEwithRSA"), //
|
||||
NONEwithRSA("NONEwithRSA"),
|
||||
|
||||
// The MD2/MD5 with RSA Encryption signature algorithm
|
||||
MD2withRSA("MD2withRSA"), //
|
||||
MD5withRSA("MD5withRSA"), //
|
||||
MD2withRSA("MD2withRSA"),
|
||||
MD5withRSA("MD5withRSA"),
|
||||
|
||||
// The signature algorithm with SHA-* and the RSA
|
||||
SHA1withRSA("SHA1withRSA"), //
|
||||
SHA256withRSA("SHA256withRSA"), //
|
||||
SHA384withRSA("SHA384withRSA"), //
|
||||
SHA512withRSA("SHA512withRSA"), //
|
||||
SHA1withRSA("SHA1withRSA"),
|
||||
SHA256withRSA("SHA256withRSA"),
|
||||
SHA384withRSA("SHA384withRSA"),
|
||||
SHA512withRSA("SHA512withRSA"),
|
||||
|
||||
// The Digital Signature Algorithm
|
||||
NONEwithDSA("NONEwithDSA"), //
|
||||
NONEwithDSA("NONEwithDSA"),
|
||||
// The DSA with SHA-1 signature algorithm
|
||||
SHA1withDSA("SHA1withDSA"), //
|
||||
SHA1withDSA("SHA1withDSA"),
|
||||
|
||||
// The ECDSA signature algorithms
|
||||
NONEwithECDSA("NONEwithECDSA"), //
|
||||
SHA1withECDSA("SHA1withECDSA"), //
|
||||
SHA256withECDSA("SHA256withECDSA"), //
|
||||
SHA384withECDSA("SHA384withECDSA"), //
|
||||
SHA512withECDSA("SHA512withECDSA");//
|
||||
NONEwithECDSA("NONEwithECDSA"),
|
||||
SHA1withECDSA("SHA1withECDSA"),
|
||||
SHA256withECDSA("SHA256withECDSA"),
|
||||
SHA384withECDSA("SHA384withECDSA"),
|
||||
SHA512withECDSA("SHA512withECDSA"),
|
||||
|
||||
// 需要BC库加入支持
|
||||
SHA256withRSA_PSS("SHA256WithRSA/PSS"),
|
||||
SHA384withRSA_PSS("SHA384WithRSA/PSS"),
|
||||
SHA512withRSA_PSS("SHA512WithRSA/PSS");
|
||||
|
||||
private final String value;
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
*
|
||||
* @param value 算法字符表示,区分大小写
|
||||
*/
|
||||
SignAlgorithm(String value) {
|
||||
@@ -46,7 +50,7 @@ public enum SignAlgorithm {
|
||||
|
||||
/**
|
||||
* 获取算法字符串表示,区分大小写
|
||||
*
|
||||
*
|
||||
* @return 算法字符串表示
|
||||
*/
|
||||
public String getValue() {
|
||||
|
@@ -14,6 +14,7 @@ import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.io.Serializable;
|
||||
import java.nio.charset.Charset;
|
||||
import java.security.Key;
|
||||
import java.security.MessageDigest;
|
||||
|
||||
@@ -89,6 +90,15 @@ public class HMac implements Serializable {
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------- Constructor end
|
||||
|
||||
/**
|
||||
* 获得MAC算法引擎
|
||||
*
|
||||
* @return MAC算法引擎
|
||||
*/
|
||||
public MacEngine getEngine(){
|
||||
return this.engine;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------- Digest
|
||||
/**
|
||||
* 生成文件摘要
|
||||
@@ -97,7 +107,7 @@ public class HMac implements Serializable {
|
||||
* @param charset 编码
|
||||
* @return 摘要
|
||||
*/
|
||||
public byte[] digest(String data, String charset) {
|
||||
public byte[] digest(String data, Charset charset) {
|
||||
return digest(StrUtil.bytes(data, charset));
|
||||
}
|
||||
|
||||
@@ -108,7 +118,7 @@ public class HMac implements Serializable {
|
||||
* @return 摘要
|
||||
*/
|
||||
public byte[] digest(String data) {
|
||||
return digest(data, CharsetUtil.UTF_8);
|
||||
return digest(data, CharsetUtil.CHARSET_UTF_8);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -118,7 +128,7 @@ public class HMac implements Serializable {
|
||||
* @param charset 编码
|
||||
* @return 摘要
|
||||
*/
|
||||
public String digestHex(String data, String charset) {
|
||||
public String digestHex(String data, Charset charset) {
|
||||
return HexUtil.encodeHexStr(digest(data, charset));
|
||||
}
|
||||
|
||||
@@ -129,7 +139,7 @@ public class HMac implements Serializable {
|
||||
* @return 摘要
|
||||
*/
|
||||
public String digestHex(String data) {
|
||||
return digestHex(data, CharsetUtil.UTF_8);
|
||||
return digestHex(data, CharsetUtil.CHARSET_UTF_8);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -1,20 +1,15 @@
|
||||
package cn.hutool.crypto.digest.mac;
|
||||
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import cn.hutool.crypto.CryptoException;
|
||||
import org.bouncycastle.crypto.CipherParameters;
|
||||
import org.bouncycastle.crypto.Digest;
|
||||
import org.bouncycastle.crypto.Mac;
|
||||
import org.bouncycastle.crypto.macs.HMac;
|
||||
import org.bouncycastle.crypto.params.KeyParameter;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* BouncyCastle的HMAC算法实现引擎,使用{@link Mac} 实现摘要<br>
|
||||
* 当引入BouncyCastle库时自动使用其作为Provider
|
||||
*
|
||||
*
|
||||
* @author Looly
|
||||
* @since 4.5.13
|
||||
*/
|
||||
@@ -25,7 +20,7 @@ public class BCHMacEngine implements MacEngine {
|
||||
// ------------------------------------------------------------------------------------------- Constructor start
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
*
|
||||
* @param digest 摘要算法,为{@link Digest} 的接口实现
|
||||
* @param key 密钥
|
||||
* @since 4.5.13
|
||||
@@ -36,7 +31,7 @@ public class BCHMacEngine implements MacEngine {
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
*
|
||||
* @param digest 摘要算法
|
||||
* @param params 参数,例如密钥可以用{@link KeyParameter}
|
||||
* @since 4.5.13
|
||||
@@ -48,7 +43,7 @@ public class BCHMacEngine implements MacEngine {
|
||||
|
||||
/**
|
||||
* 初始化
|
||||
*
|
||||
*
|
||||
* @param digest 摘要算法
|
||||
* @param params 参数,例如密钥可以用{@link KeyParameter}
|
||||
* @return this
|
||||
@@ -59,40 +54,32 @@ public class BCHMacEngine implements MacEngine {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] digest(InputStream data, int bufferLength) {
|
||||
if (bufferLength < 1) {
|
||||
bufferLength = IoUtil.DEFAULT_BUFFER_SIZE;
|
||||
}
|
||||
final byte[] buffer = new byte[bufferLength];
|
||||
|
||||
byte[] result;
|
||||
try {
|
||||
int read = data.read(buffer, 0, bufferLength);
|
||||
|
||||
while (read > -1) {
|
||||
mac.update(buffer, 0, read);
|
||||
read = data.read(buffer, 0, bufferLength);
|
||||
}
|
||||
result = new byte[this.mac.getMacSize()];
|
||||
mac.doFinal(result, 0);
|
||||
} catch (IOException e) {
|
||||
throw new CryptoException(e);
|
||||
} finally {
|
||||
mac.reset();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得 {@link Mac}
|
||||
*
|
||||
*
|
||||
* @return {@link Mac}
|
||||
*/
|
||||
public Mac getMac() {
|
||||
return mac;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(byte[] in, int inOff, int len) {
|
||||
this.mac.update(in, inOff, len);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] doFinal() {
|
||||
final byte[] result = new byte[getMacLength()];
|
||||
this.mac.doFinal(result, 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
this.mac.reset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMacLength() {
|
||||
return mac.getMacSize();
|
||||
|
@@ -1,27 +1,24 @@
|
||||
package cn.hutool.crypto.digest.mac;
|
||||
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import cn.hutool.crypto.CryptoException;
|
||||
import cn.hutool.crypto.SecureUtil;
|
||||
|
||||
import javax.crypto.Mac;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.security.Key;
|
||||
|
||||
/**
|
||||
* 默认的HMAC算法实现引擎,使用{@link Mac} 实现摘要<br>
|
||||
* 当引入BouncyCastle库时自动使用其作为Provider
|
||||
*
|
||||
*
|
||||
* @author Looly
|
||||
*@since 4.5.13
|
||||
*/
|
||||
public class DefaultHMacEngine implements MacEngine {
|
||||
|
||||
private Mac mac;
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------- Constructor start
|
||||
/**
|
||||
* 构造
|
||||
@@ -32,7 +29,7 @@ public class DefaultHMacEngine implements MacEngine {
|
||||
public DefaultHMacEngine(String algorithm, byte[] key) {
|
||||
init(algorithm, key);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 构造
|
||||
* @param algorithm 算法
|
||||
@@ -43,7 +40,7 @@ public class DefaultHMacEngine implements MacEngine {
|
||||
init(algorithm, key);
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------- Constructor end
|
||||
|
||||
|
||||
/**
|
||||
* 初始化
|
||||
* @param algorithm 算法
|
||||
@@ -53,7 +50,7 @@ public class DefaultHMacEngine implements MacEngine {
|
||||
public DefaultHMacEngine init(String algorithm, byte[] key){
|
||||
return init(algorithm, (null == key) ? null : new SecretKeySpec(key, algorithm));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 初始化
|
||||
* @param algorithm 算法
|
||||
@@ -74,39 +71,35 @@ public class DefaultHMacEngine implements MacEngine {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] digest(InputStream data, int bufferLength) {
|
||||
if (bufferLength < 1) {
|
||||
bufferLength = IoUtil.DEFAULT_BUFFER_SIZE;
|
||||
}
|
||||
byte[] buffer = new byte[bufferLength];
|
||||
|
||||
byte[] result;
|
||||
try {
|
||||
int read = data.read(buffer, 0, bufferLength);
|
||||
|
||||
while (read > -1) {
|
||||
mac.update(buffer, 0, read);
|
||||
read = data.read(buffer, 0, bufferLength);
|
||||
}
|
||||
result = mac.doFinal();
|
||||
} catch (IOException e) {
|
||||
throw new CryptoException(e);
|
||||
} finally {
|
||||
mac.reset();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得 {@link Mac}
|
||||
*
|
||||
*
|
||||
* @return {@link Mac}
|
||||
*/
|
||||
public Mac getMac() {
|
||||
return mac;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(byte[] in) {
|
||||
this.mac.update(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(byte[] in, int inOff, int len) {
|
||||
this.mac.update(in, inOff, len);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] doFinal() {
|
||||
return this.mac.doFinal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
this.mac.reset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMacLength() {
|
||||
return mac.getMacLength();
|
||||
|
@@ -1,25 +1,81 @@
|
||||
package cn.hutool.crypto.digest.mac;
|
||||
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import cn.hutool.crypto.CryptoException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* MAC(Message Authentication Code)算法引擎
|
||||
*
|
||||
*
|
||||
* @author Looly
|
||||
* @since 4.5.13
|
||||
*/
|
||||
public interface MacEngine {
|
||||
|
||||
|
||||
/**
|
||||
* 加入需要被摘要的内容
|
||||
* @param in 内容
|
||||
* @since 5.7.0
|
||||
*/
|
||||
default void update(byte[] in){
|
||||
update(in, 0, in.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* 加入需要被摘要的内容
|
||||
* @param in 内容
|
||||
* @param inOff 内容起始位置
|
||||
* @param len 内容长度
|
||||
* @since 5.7.0
|
||||
*/
|
||||
void update(byte[] in, int inOff, int len);
|
||||
|
||||
/**
|
||||
* 结束并生成摘要
|
||||
*
|
||||
* @return 摘要内容
|
||||
* @since 5.7.0
|
||||
*/
|
||||
byte[] doFinal();
|
||||
|
||||
/**
|
||||
* 重置
|
||||
* @since 5.7.0
|
||||
*/
|
||||
void reset();
|
||||
|
||||
/**
|
||||
* 生成摘要
|
||||
*
|
||||
*
|
||||
* @param data {@link InputStream} 数据流
|
||||
* @param bufferLength 缓存长度,不足1使用 {@link IoUtil#DEFAULT_BUFFER_SIZE} 做为默认值
|
||||
* @return 摘要bytes
|
||||
*/
|
||||
byte[] digest(InputStream data, int bufferLength);
|
||||
default byte[] digest(InputStream data, int bufferLength){
|
||||
if (bufferLength < 1) {
|
||||
bufferLength = IoUtil.DEFAULT_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
final byte[] buffer = new byte[bufferLength];
|
||||
|
||||
byte[] result;
|
||||
try {
|
||||
int read = data.read(buffer, 0, bufferLength);
|
||||
|
||||
while (read > -1) {
|
||||
update(buffer, 0, read);
|
||||
read = data.read(buffer, 0, bufferLength);
|
||||
}
|
||||
result = doFinal();
|
||||
} catch (IOException e) {
|
||||
throw new CryptoException(e);
|
||||
} finally {
|
||||
reset();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取MAC算法块大小
|
||||
|
@@ -13,7 +13,7 @@ import java.util.Map;
|
||||
|
||||
/**
|
||||
* 签名单元测试
|
||||
*
|
||||
*
|
||||
* @author looly
|
||||
*
|
||||
*/
|
||||
@@ -22,7 +22,7 @@ public class SignTest {
|
||||
@Test
|
||||
public void signAndVerifyUseKeyTest() {
|
||||
String content = "我是Hanley.";
|
||||
|
||||
|
||||
String privateKey = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAJ4fG8vJ0tzu7tjXMSJhyNjlE5B7GkTKMKEQlR6LY3IhIhMFVjuA6W+DqH1VMxl9h3GIM4yCKG2VRZEYEPazgVxa5/ifO8W0pfmrzWCPrddUq4t0Slz5u2lLKymLpPjCzboHoDb8VlF+1HOxjKQckAXq9q7U7dV5VxOzJDuZXlz3AgMBAAECgYABo2LfVqT3owYYewpIR+kTzjPIsG3SPqIIWSqiWWFbYlp/BfQhw7EndZ6+Ra602ecYVwfpscOHdx90ZGJwm+WAMkKT4HiWYwyb0ZqQzRBGYDHFjPpfCBxrzSIJ3QL+B8c8YHq4HaLKRKmq7VUF1gtyWaek87rETWAmQoGjt8DyAQJBAOG4OxsT901zjfxrgKwCv6fV8wGXrNfDSViP1t9r3u6tRPsE6Gli0dfMyzxwENDTI75sOEAfyu6xBlemQGmNsfcCQQCzVWQkl9YUoVDWEitvI5MpkvVKYsFLRXKvLfyxLcY3LxpLKBcEeJ/n5wLxjH0GorhJMmM2Rw3hkjUTJCoqqe0BAkATt8FKC0N2O5ryqv1xiUfuxGzW/cX2jzOwDdiqacTuuqok93fKBPzpyhUS8YM2iss7jj6Xs29JzKMOMxK7ZcpfAkAf21lwzrAu9gEgJhYlJhKsXfjJAAYKUwnuaKLs7o65mtp242ZDWxI85eK1+hjzptBJ4HOTXsfufESFY/VBovIBAkAltO886qQRoNSc0OsVlCi4X1DGo6x2RqQ9EsWPrxWEZGYuyEdODrc54b8L+zaUJLfMJdsCIHEUbM7WXxvFVXNv";
|
||||
Sign sign = SecureUtil.sign(SignAlgorithm.SHA1withRSA, privateKey, null);
|
||||
Assert.assertNull(sign.getPublicKeyBase64());
|
||||
@@ -35,7 +35,7 @@ public class SignTest {
|
||||
boolean verify = sign.verify(content.getBytes(), signed);
|
||||
Assert.assertTrue(verify);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void signAndVerifyTest() {
|
||||
signAndVerify(SignAlgorithm.NONEwithRSA);
|
||||
@@ -60,7 +60,7 @@ public class SignTest {
|
||||
|
||||
/**
|
||||
* 测试各种算法的签名和验证签名
|
||||
*
|
||||
*
|
||||
* @param signAlgorithm 算法
|
||||
*/
|
||||
private void signAndVerify(SignAlgorithm signAlgorithm) {
|
||||
@@ -74,19 +74,19 @@ public class SignTest {
|
||||
boolean verify = sign.verify(data, signed);
|
||||
Assert.assertTrue(verify);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 测试MD5withRSA算法的签名和验证签名
|
||||
*/
|
||||
@Test
|
||||
public void signAndVerify2() {
|
||||
public void signAndVerifyTest2() {
|
||||
String str = "wx2421b1c4370ec43b 支付测试 JSAPI支付测试 10000100 1add1a30ac87aa2db72f57a2375d8fec http://wxpay.wxutil.com/pub_v2/pay/notify.v2.php oUpF8uMuAJO_M2pxb1Q9zNjWeS6o 1415659990 14.23.150.211 1 JSAPI 0CB01533B8C1EF103065174F50BCA001";
|
||||
byte[] data = StrUtil.utf8Bytes(str);
|
||||
Sign sign = SecureUtil.sign(SignAlgorithm.MD5withRSA);
|
||||
|
||||
|
||||
// 签名
|
||||
byte[] signed = sign.sign(data);
|
||||
|
||||
|
||||
// 验证签名
|
||||
boolean verify = sign.verify(data, signed);
|
||||
Assert.assertTrue(verify);
|
||||
@@ -105,4 +105,21 @@ public class SignTest {
|
||||
String sign3 = SecureUtil.signParamsSha1(build, "12345678", "abc");
|
||||
Assert.assertEquals("edee1b477af1b96ebd20fdf08d818f352928d25d", sign3);
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试MD5withRSA算法的签名和验证签名
|
||||
*/
|
||||
@Test
|
||||
public void signAndVerifyPSSTest() {
|
||||
String str = "wx2421b1c4370ec43b 支付测试 JSAPI支付测试 10000100 1add1a30ac87aa2db72f57a2375d8fec http://wxpay.wxutil.com/pub_v2/pay/notify.v2.php oUpF8uMuAJO_M2pxb1Q9zNjWeS6o 1415659990 14.23.150.211 1 JSAPI 0CB01533B8C1EF103065174F50BCA001";
|
||||
byte[] data = StrUtil.utf8Bytes(str);
|
||||
Sign sign = SecureUtil.sign(SignAlgorithm.SHA256withRSA_PSS);
|
||||
|
||||
// 签名
|
||||
byte[] signed = sign.sign(data);
|
||||
|
||||
// 验证签名
|
||||
boolean verify = sign.verify(data, signed);
|
||||
Assert.assertTrue(verify);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user