mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-04-19 03:01:48 +08:00
add ZUC
This commit is contained in:
parent
5be6c0103b
commit
02885bbcd3
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
# 5.7.12 (2021-09-08)
|
# 5.7.12 (2021-09-09)
|
||||||
|
|
||||||
### 🐣新特性
|
### 🐣新特性
|
||||||
* 【system 】 OshiUtil增加getCurrentProcess方法
|
* 【system 】 OshiUtil增加getCurrentProcess方法
|
||||||
@ -16,12 +16,13 @@
|
|||||||
* 【core 】 ZipReader支持Filter
|
* 【core 】 ZipReader支持Filter
|
||||||
* 【all 】 Sftp、Ftp、HttpDownloader增加download重载,支持避免传输文件损坏(pr#407@Gitee)
|
* 【all 】 Sftp、Ftp、HttpDownloader增加download重载,支持避免传输文件损坏(pr#407@Gitee)
|
||||||
* 【crypto 】 AES修改构造的IvParameterSpec为AlgorithmParameterSpec(issue#1814@Gitee)
|
* 【crypto 】 AES修改构造的IvParameterSpec为AlgorithmParameterSpec(issue#1814@Gitee)
|
||||||
* 【crypto 】 增加FPE(issue#1814@Gitee)
|
* 【crypto 】 增加FPE、ZUC(issue#1814@Gitee)
|
||||||
|
|
||||||
### 🐞Bug修复
|
### 🐞Bug修复
|
||||||
* 【core 】 修复ListUtil.split方法越界问题(issue#I48Q0P@Gitee)
|
* 【core 】 修复ListUtil.split方法越界问题(issue#I48Q0P@Gitee)
|
||||||
* 【core 】 修复QrCode的isTryHarder、isPureBarcode设置无效问题(issue#1815@Github)
|
* 【core 】 修复QrCode的isTryHarder、isPureBarcode设置无效问题(issue#1815@Github)
|
||||||
* 【core 】 修复DatePattern.CHINESE_DATE_FORMATTER错误问题(issue#I48ZE3@Gitee)
|
* 【core 】 修复DatePattern.CHINESE_DATE_FORMATTER错误问题(issue#I48ZE3@Gitee)
|
||||||
|
* 【core 】 修复ListUtil.split错误问题
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -40,6 +40,8 @@ public class AvgPartition<T> extends Partition<T> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<T> get(int index) {
|
public List<T> get(int index) {
|
||||||
|
final int size = this.size;
|
||||||
|
final int remainder = this.remainder;
|
||||||
// 当limit个数超过list的size时,size为0,此时每个分区分1个元素,直到remainder个分配完,剩余分区为[]
|
// 当limit个数超过list的size时,size为0,此时每个分区分1个元素,直到remainder个分配完,剩余分区为[]
|
||||||
int start = index * size + Math.min(index, remainder);
|
int start = index * size + Math.min(index, remainder);
|
||||||
int end = start + size;
|
int end = start + size;
|
||||||
|
@ -38,10 +38,11 @@ public class Partition<T> extends AbstractList<List<T>> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int size() {
|
public int size() {
|
||||||
// 此处采用动态计算,以应对list变化
|
// 此处采用动态计算,以应对list变
|
||||||
|
final int size = this.size;
|
||||||
final int total = list.size();
|
final int total = list.size();
|
||||||
int length = total / size;
|
int length = total / size;
|
||||||
if(total % length > 0){
|
if(total % size > 0){
|
||||||
length += 1;
|
length += 1;
|
||||||
}
|
}
|
||||||
return length;
|
return length;
|
||||||
|
@ -18,11 +18,19 @@ public class ListUtilTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void splitTest(){
|
public void splitTest(){
|
||||||
List<String> listAll = new ArrayList<>();
|
List<List<Object>> lists = ListUtil.split(null, 3);
|
||||||
listAll.add("1");
|
Assert.assertEquals(ListUtil.empty(), lists);
|
||||||
listAll.add("2");
|
|
||||||
List<List<String>> lists = ListUtil.split(listAll, 10);
|
lists = ListUtil.split(Arrays.asList(1, 2, 3, 4), 1);
|
||||||
Assert.assertEquals(1, lists.size());
|
Assert.assertEquals("[[1], [2], [3], [4]]", lists.toString());
|
||||||
|
lists = ListUtil.split(Arrays.asList(1, 2, 3, 4), 2);
|
||||||
|
Assert.assertEquals("[[1, 2], [3, 4]]", lists.toString());
|
||||||
|
lists = ListUtil.split(Arrays.asList(1, 2, 3, 4), 3);
|
||||||
|
Assert.assertEquals("[[1, 2, 3], [4]]", lists.toString());
|
||||||
|
lists = ListUtil.split(Arrays.asList(1, 2, 3, 4), 4);
|
||||||
|
Assert.assertEquals("[[1, 2, 3, 4]]", lists.toString());
|
||||||
|
lists = ListUtil.split(Arrays.asList(1, 2, 3, 4), 5);
|
||||||
|
Assert.assertEquals("[[1, 2, 3, 4]]", lists.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -4,8 +4,8 @@ import java.security.Provider;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 全局单例的 org.bouncycastle.jce.provider.BouncyCastleProvider 对象
|
* 全局单例的 org.bouncycastle.jce.provider.BouncyCastleProvider 对象
|
||||||
* @author looly
|
|
||||||
*
|
*
|
||||||
|
* @author looly
|
||||||
*/
|
*/
|
||||||
public enum GlobalBouncyCastleProvider {
|
public enum GlobalBouncyCastleProvider {
|
||||||
INSTANCE;
|
INSTANCE;
|
||||||
@ -23,6 +23,7 @@ public enum GlobalBouncyCastleProvider {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取{@link Provider}
|
* 获取{@link Provider}
|
||||||
|
*
|
||||||
* @return {@link Provider}
|
* @return {@link Provider}
|
||||||
*/
|
*/
|
||||||
public Provider getProvider() {
|
public Provider getProvider() {
|
||||||
|
@ -3,7 +3,7 @@ package cn.hutool.crypto;
|
|||||||
import java.security.Provider;
|
import java.security.Provider;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provider对象生产法工厂类
|
* Provider对象生产工厂类
|
||||||
*
|
*
|
||||||
* <pre>
|
* <pre>
|
||||||
* 1. 调用{@link #createBouncyCastleProvider()} 用于新建一个org.bouncycastle.jce.provider.BouncyCastleProvider对象
|
* 1. 调用{@link #createBouncyCastleProvider()} 用于新建一个org.bouncycastle.jce.provider.BouncyCastleProvider对象
|
||||||
|
@ -21,6 +21,7 @@ import cn.hutool.crypto.symmetric.DESede;
|
|||||||
import cn.hutool.crypto.symmetric.PBKDF2;
|
import cn.hutool.crypto.symmetric.PBKDF2;
|
||||||
import cn.hutool.crypto.symmetric.RC4;
|
import cn.hutool.crypto.symmetric.RC4;
|
||||||
import cn.hutool.crypto.symmetric.SymmetricCrypto;
|
import cn.hutool.crypto.symmetric.SymmetricCrypto;
|
||||||
|
import cn.hutool.crypto.symmetric.ZUC;
|
||||||
import cn.hutool.crypto.symmetric.fpe.FPE;
|
import cn.hutool.crypto.symmetric.fpe.FPE;
|
||||||
import org.bouncycastle.crypto.AlphabetMapper;
|
import org.bouncycastle.crypto.AlphabetMapper;
|
||||||
|
|
||||||
@ -1124,4 +1125,28 @@ public class SecureUtil {
|
|||||||
public static FPE fpe(FPE.FPEMode mode, byte[] key, AlphabetMapper mapper, byte[] tweak) {
|
public static FPE fpe(FPE.FPEMode mode, byte[] key, AlphabetMapper mapper, byte[] tweak) {
|
||||||
return new FPE(mode, key, mapper, tweak);
|
return new FPE(mode, key, mapper, tweak);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 祖冲之算法集(ZUC-128算法)实现,基于BouncyCastle实现。
|
||||||
|
*
|
||||||
|
* @param key 密钥
|
||||||
|
* @param iv 加盐,长度16bytes,{@code null}是随机加盐
|
||||||
|
* @return {@link ZUC}
|
||||||
|
* @since 5.7.12
|
||||||
|
*/
|
||||||
|
public static ZUC zuc128(byte[] key, byte[] iv) {
|
||||||
|
return new ZUC(ZUC.ZUCAlgorithm.ZUC_128, key, iv);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 祖冲之算法集(ZUC-256算法)实现,基于BouncyCastle实现。
|
||||||
|
*
|
||||||
|
* @param key 密钥
|
||||||
|
* @param iv 加盐,长度25bytes,{@code null}是随机加盐
|
||||||
|
* @return {@link ZUC}
|
||||||
|
* @since 5.7.12
|
||||||
|
*/
|
||||||
|
public static ZUC zuc256(byte[] key, byte[] iv) {
|
||||||
|
return new ZUC(ZUC.ZUCAlgorithm.ZUC_256, key, iv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ import java.io.Serializable;
|
|||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.security.Key;
|
import java.security.Key;
|
||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
|
import java.security.spec.AlgorithmParameterSpec;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* HMAC摘要算法<br>
|
* HMAC摘要算法<br>
|
||||||
@ -84,7 +85,19 @@ public class HMac implements Serializable {
|
|||||||
* @since 4.5.13
|
* @since 4.5.13
|
||||||
*/
|
*/
|
||||||
public HMac(String algorithm, Key key) {
|
public HMac(String algorithm, Key key) {
|
||||||
this(MacEngineFactory.createEngine(algorithm, key));
|
this(algorithm, key, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造
|
||||||
|
*
|
||||||
|
* @param algorithm 算法
|
||||||
|
* @param key 密钥
|
||||||
|
* @param spec {@link AlgorithmParameterSpec}
|
||||||
|
* @since 5.6.12
|
||||||
|
*/
|
||||||
|
public HMac(String algorithm, Key key, AlgorithmParameterSpec spec) {
|
||||||
|
this(MacEngineFactory.createEngine(algorithm, key, spec));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -5,6 +5,7 @@ import org.bouncycastle.crypto.Digest;
|
|||||||
import org.bouncycastle.crypto.Mac;
|
import org.bouncycastle.crypto.Mac;
|
||||||
import org.bouncycastle.crypto.macs.HMac;
|
import org.bouncycastle.crypto.macs.HMac;
|
||||||
import org.bouncycastle.crypto.params.KeyParameter;
|
import org.bouncycastle.crypto.params.KeyParameter;
|
||||||
|
import org.bouncycastle.crypto.params.ParametersWithIV;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BouncyCastle的HMAC算法实现引擎,使用{@link Mac} 实现摘要<br>
|
* BouncyCastle的HMAC算法实现引擎,使用{@link Mac} 实现摘要<br>
|
||||||
@ -18,11 +19,24 @@ public class BCHMacEngine implements MacEngine {
|
|||||||
private Mac mac;
|
private Mac mac;
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------- Constructor start
|
// ------------------------------------------------------------------------------------------- Constructor start
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构造
|
* 构造
|
||||||
*
|
*
|
||||||
* @param digest 摘要算法,为{@link Digest} 的接口实现
|
* @param digest 摘要算法,为{@link Digest} 的接口实现
|
||||||
* @param key 密钥
|
* @param key 密钥
|
||||||
|
* @param iv 加盐
|
||||||
|
* @since 5.7.12
|
||||||
|
*/
|
||||||
|
public BCHMacEngine(Digest digest, byte[] key, byte[] iv) {
|
||||||
|
this(digest, new ParametersWithIV(new KeyParameter(key), iv));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造
|
||||||
|
*
|
||||||
|
* @param digest 摘要算法,为{@link Digest} 的接口实现
|
||||||
|
* @param key 密钥
|
||||||
* @since 4.5.13
|
* @since 4.5.13
|
||||||
*/
|
*/
|
||||||
public BCHMacEngine(Digest digest, byte[] key) {
|
public BCHMacEngine(Digest digest, byte[] key) {
|
||||||
|
@ -7,64 +7,100 @@ import javax.crypto.Mac;
|
|||||||
import javax.crypto.SecretKey;
|
import javax.crypto.SecretKey;
|
||||||
import javax.crypto.spec.SecretKeySpec;
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
import java.security.Key;
|
import java.security.Key;
|
||||||
|
import java.security.spec.AlgorithmParameterSpec;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 默认的HMAC算法实现引擎,使用{@link Mac} 实现摘要<br>
|
* 默认的HMAC算法实现引擎,使用{@link Mac} 实现摘要<br>
|
||||||
* 当引入BouncyCastle库时自动使用其作为Provider
|
* 当引入BouncyCastle库时自动使用其作为Provider
|
||||||
*
|
*
|
||||||
* @author Looly
|
* @author Looly
|
||||||
*@since 4.5.13
|
* @since 4.5.13
|
||||||
*/
|
*/
|
||||||
public class DefaultHMacEngine implements MacEngine {
|
public class DefaultHMacEngine implements MacEngine {
|
||||||
|
|
||||||
private Mac mac;
|
private Mac mac;
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------- Constructor start
|
// ------------------------------------------------------------------------------------------- Constructor start
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构造
|
* 构造
|
||||||
|
*
|
||||||
* @param algorithm 算法
|
* @param algorithm 算法
|
||||||
* @param key 密钥
|
* @param key 密钥
|
||||||
* @since 4.5.13
|
* @since 4.5.13
|
||||||
*/
|
*/
|
||||||
public DefaultHMacEngine(String algorithm, byte[] key) {
|
public DefaultHMacEngine(String algorithm, byte[] key) {
|
||||||
init(algorithm, key);
|
this(algorithm, (null == key) ? null : new SecretKeySpec(key, algorithm));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构造
|
* 构造
|
||||||
|
*
|
||||||
* @param algorithm 算法
|
* @param algorithm 算法
|
||||||
* @param key 密钥
|
* @param key 密钥
|
||||||
* @since 4.5.13
|
* @since 4.5.13
|
||||||
*/
|
*/
|
||||||
public DefaultHMacEngine(String algorithm, Key key) {
|
public DefaultHMacEngine(String algorithm, Key key) {
|
||||||
init(algorithm, key);
|
this(algorithm, key, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造
|
||||||
|
*
|
||||||
|
* @param algorithm 算法
|
||||||
|
* @param key 密钥
|
||||||
|
* @param spec {@link AlgorithmParameterSpec}
|
||||||
|
* @since 5.7.12
|
||||||
|
*/
|
||||||
|
public DefaultHMacEngine(String algorithm, Key key, AlgorithmParameterSpec spec) {
|
||||||
|
init(algorithm, key, spec);
|
||||||
}
|
}
|
||||||
// ------------------------------------------------------------------------------------------- Constructor end
|
// ------------------------------------------------------------------------------------------- Constructor end
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 初始化
|
* 初始化
|
||||||
|
*
|
||||||
* @param algorithm 算法
|
* @param algorithm 算法
|
||||||
* @param key 密钥
|
* @param key 密钥
|
||||||
* @return this
|
* @return this
|
||||||
*/
|
*/
|
||||||
public DefaultHMacEngine init(String algorithm, byte[] key){
|
public DefaultHMacEngine init(String algorithm, byte[] key) {
|
||||||
return init(algorithm, (null == key) ? null : new SecretKeySpec(key, algorithm));
|
return init(algorithm, (null == key) ? null : new SecretKeySpec(key, algorithm));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 初始化
|
* 初始化
|
||||||
|
*
|
||||||
* @param algorithm 算法
|
* @param algorithm 算法
|
||||||
* @param key 密钥 {@link SecretKey}
|
* @param key 密钥 {@link SecretKey}
|
||||||
* @return this
|
* @return this
|
||||||
* @throws CryptoException Cause by IOException
|
* @throws CryptoException Cause by IOException
|
||||||
*/
|
*/
|
||||||
public DefaultHMacEngine init(String algorithm, Key key){
|
public DefaultHMacEngine init(String algorithm, Key key) {
|
||||||
|
return init(algorithm, key, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化
|
||||||
|
*
|
||||||
|
* @param algorithm 算法
|
||||||
|
* @param key 密钥 {@link SecretKey}
|
||||||
|
* @param spec {@link AlgorithmParameterSpec}
|
||||||
|
* @return this
|
||||||
|
* @throws CryptoException Cause by IOException
|
||||||
|
* @since 5.7.12
|
||||||
|
*/
|
||||||
|
public DefaultHMacEngine init(String algorithm, Key key, AlgorithmParameterSpec spec) {
|
||||||
try {
|
try {
|
||||||
mac = SecureUtil.createMac(algorithm);
|
mac = SecureUtil.createMac(algorithm);
|
||||||
if(null == key){
|
if (null == key) {
|
||||||
key = SecureUtil.generateKey(algorithm);
|
key = SecureUtil.generateKey(algorithm);
|
||||||
}
|
}
|
||||||
mac.init(key);
|
if (null != spec) {
|
||||||
|
mac.init(key, spec);
|
||||||
|
} else {
|
||||||
|
mac.init(key);
|
||||||
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new CryptoException(e);
|
throw new CryptoException(e);
|
||||||
}
|
}
|
||||||
|
@ -4,26 +4,41 @@ import cn.hutool.crypto.SmUtil;
|
|||||||
import cn.hutool.crypto.digest.HmacAlgorithm;
|
import cn.hutool.crypto.digest.HmacAlgorithm;
|
||||||
|
|
||||||
import java.security.Key;
|
import java.security.Key;
|
||||||
|
import java.security.spec.AlgorithmParameterSpec;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link MacEngine} 实现工厂类
|
* {@link MacEngine} 实现工厂类
|
||||||
*
|
*
|
||||||
* @author Looly
|
* @author Looly
|
||||||
*@since 4.5.13
|
* @since 4.5.13
|
||||||
*/
|
*/
|
||||||
public class MacEngineFactory {
|
public class MacEngineFactory {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据给定算法和密钥生成对应的{@link MacEngine}
|
* 根据给定算法和密钥生成对应的{@link MacEngine}
|
||||||
|
*
|
||||||
* @param algorithm 算法,见{@link HmacAlgorithm}
|
* @param algorithm 算法,见{@link HmacAlgorithm}
|
||||||
* @param key 密钥
|
* @param key 密钥
|
||||||
* @return {@link MacEngine}
|
* @return {@link MacEngine}
|
||||||
*/
|
*/
|
||||||
public static MacEngine createEngine(String algorithm, Key key) {
|
public static MacEngine createEngine(String algorithm, Key key) {
|
||||||
if(algorithm.equalsIgnoreCase(HmacAlgorithm.HmacSM3.getValue())) {
|
return createEngine(algorithm, key, null);
|
||||||
// HmacSM3算法是BC库实现的
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据给定算法和密钥生成对应的{@link MacEngine}
|
||||||
|
*
|
||||||
|
* @param algorithm 算法,见{@link HmacAlgorithm}
|
||||||
|
* @param key 密钥
|
||||||
|
* @param spec spec
|
||||||
|
* @return {@link MacEngine}
|
||||||
|
* @since 5.7.12
|
||||||
|
*/
|
||||||
|
public static MacEngine createEngine(String algorithm, Key key, AlgorithmParameterSpec spec) {
|
||||||
|
if (algorithm.equalsIgnoreCase(HmacAlgorithm.HmacSM3.getValue())) {
|
||||||
|
// HmacSM3算法是BC库实现的,忽略加盐
|
||||||
return SmUtil.createHmacSm3Engine(key.getEncoded());
|
return SmUtil.createHmacSm3Engine(key.getEncoded());
|
||||||
}
|
}
|
||||||
return new DefaultHMacEngine(algorithm, key);
|
return new DefaultHMacEngine(algorithm, key, spec);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,92 @@
|
|||||||
|
package cn.hutool.crypto.symmetric;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.RandomUtil;
|
||||||
|
import cn.hutool.crypto.KeyUtil;
|
||||||
|
|
||||||
|
import javax.crypto.spec.IvParameterSpec;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 祖冲之算法集(ZUC算法)实现,基于BouncyCastle实现。
|
||||||
|
*
|
||||||
|
* @author looly
|
||||||
|
* @since 5.7.12
|
||||||
|
*/
|
||||||
|
public class ZUC extends SymmetricCrypto {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成ZUC算法密钥
|
||||||
|
*
|
||||||
|
* @param algorithm ZUC算法
|
||||||
|
* @return 密钥
|
||||||
|
*
|
||||||
|
* @see KeyUtil#generateKey(String)
|
||||||
|
*/
|
||||||
|
public static byte[] generateKey(ZUCAlgorithm algorithm) {
|
||||||
|
return KeyUtil.generateKey(algorithm.value).getEncoded();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造
|
||||||
|
*
|
||||||
|
* @param algorithm ZUC算法枚举,包括128位和256位两种
|
||||||
|
* @param key 密钥
|
||||||
|
* @param iv 加盐,128位加盐是16bytes,256位是25bytes,{@code null}是随机加盐
|
||||||
|
*/
|
||||||
|
public ZUC(ZUCAlgorithm algorithm, byte[] key, byte[] iv) {
|
||||||
|
super(algorithm.value,
|
||||||
|
KeyUtil.generateKey(algorithm.value, key),
|
||||||
|
generateIvParam(algorithm, iv));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ZUC类型,包括128位和256位
|
||||||
|
*
|
||||||
|
* @author looly
|
||||||
|
*/
|
||||||
|
public enum ZUCAlgorithm {
|
||||||
|
ZUC_128("ZUC-128"),
|
||||||
|
ZUC_256("ZUC-256");
|
||||||
|
|
||||||
|
private final String value;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造
|
||||||
|
*
|
||||||
|
* @param value 算法的字符串表示,区分大小写
|
||||||
|
*/
|
||||||
|
ZUCAlgorithm(String value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得算法的字符串表示形式
|
||||||
|
*
|
||||||
|
* @return 算法字符串
|
||||||
|
*/
|
||||||
|
public String getValue() {
|
||||||
|
return this.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成加盐参数
|
||||||
|
*
|
||||||
|
* @param algorithm ZUC算法
|
||||||
|
* @param iv 加盐,128位加盐是16bytes,256位是25bytes,{@code null}是随机加盐
|
||||||
|
* @return {@link IvParameterSpec}
|
||||||
|
*/
|
||||||
|
private static IvParameterSpec generateIvParam(ZUCAlgorithm algorithm, byte[] iv){
|
||||||
|
if(null == iv){
|
||||||
|
switch (algorithm){
|
||||||
|
case ZUC_128:
|
||||||
|
iv = RandomUtil.randomBytes(16);
|
||||||
|
break;
|
||||||
|
case ZUC_256:
|
||||||
|
iv = RandomUtil.randomBytes(25);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new IvParameterSpec(iv);
|
||||||
|
}
|
||||||
|
}
|
@ -25,6 +25,8 @@ import java.io.Serializable;
|
|||||||
* <li>加密过程可逆,加密后的数据可以通过密钥解密还原原始数据</li>
|
* <li>加密过程可逆,加密后的数据可以通过密钥解密还原原始数据</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
|
* 此类基于BouncyCastle实现。
|
||||||
|
*
|
||||||
* @author looly
|
* @author looly
|
||||||
* @since 5.7.12
|
* @since 5.7.12
|
||||||
*/
|
*/
|
||||||
@ -52,15 +54,15 @@ public class FPE implements Serializable {
|
|||||||
* @param mode FPE模式枚举,可选FF1或FF3-1
|
* @param mode FPE模式枚举,可选FF1或FF3-1
|
||||||
* @param key 密钥,{@code null}表示随机密钥,长度必须是16bit、24bit或32bit
|
* @param key 密钥,{@code null}表示随机密钥,长度必须是16bit、24bit或32bit
|
||||||
* @param mapper Alphabet字典映射,被加密的字符范围和这个映射必须一致,例如手机号、银行卡号等字段可以采用数字字母字典表
|
* @param mapper Alphabet字典映射,被加密的字符范围和这个映射必须一致,例如手机号、银行卡号等字段可以采用数字字母字典表
|
||||||
* @param tweak Tweak是为了解决因局部加密而导致结果冲突问题,通常情况下将数据的不可变部分作为Tweak
|
* @param tweak Tweak是为了解决因局部加密而导致结果冲突问题,通常情况下将数据的不可变部分作为Tweak,{@code null}使用默认长度全是0的bytes
|
||||||
*/
|
*/
|
||||||
public FPE(FPEMode mode, byte[] key, AlphabetMapper mapper, byte[] tweak) {
|
public FPE(FPEMode mode, byte[] key, AlphabetMapper mapper, byte[] tweak) {
|
||||||
if (null == mode) {
|
if (null == mode) {
|
||||||
mode = FPEMode.FF1;
|
mode = FPEMode.FF1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(null == tweak){
|
if (null == tweak) {
|
||||||
switch (mode){
|
switch (mode) {
|
||||||
case FF1:
|
case FF1:
|
||||||
tweak = new byte[0];
|
tweak = new byte[0];
|
||||||
break;
|
break;
|
||||||
|
@ -1,13 +1,16 @@
|
|||||||
package cn.hutool.crypto.test.digest;
|
package cn.hutool.crypto.test.digest;
|
||||||
|
|
||||||
import org.junit.Assert;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import cn.hutool.core.io.IoUtil;
|
import cn.hutool.core.io.IoUtil;
|
||||||
import cn.hutool.core.util.CharsetUtil;
|
import cn.hutool.core.util.CharsetUtil;
|
||||||
|
import cn.hutool.crypto.KeyUtil;
|
||||||
import cn.hutool.crypto.SecureUtil;
|
import cn.hutool.crypto.SecureUtil;
|
||||||
import cn.hutool.crypto.digest.HMac;
|
import cn.hutool.crypto.digest.HMac;
|
||||||
import cn.hutool.crypto.digest.HmacAlgorithm;
|
import cn.hutool.crypto.digest.HmacAlgorithm;
|
||||||
|
import cn.hutool.crypto.symmetric.ZUC;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import javax.crypto.spec.IvParameterSpec;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hmac单元测试
|
* Hmac单元测试
|
||||||
@ -45,14 +48,39 @@ public class HmacTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void hmacSha1Test(){
|
public void hmacSha1Test(){
|
||||||
String testStr = "test中文";
|
|
||||||
|
|
||||||
HMac mac = SecureUtil.hmacSha1("password");
|
HMac mac = SecureUtil.hmacSha1("password");
|
||||||
|
|
||||||
|
String testStr = "test中文";
|
||||||
String macHex1 = mac.digestHex(testStr);
|
String macHex1 = mac.digestHex(testStr);
|
||||||
Assert.assertEquals("1dd68d2f119d5640f0d416e99d3f42408b88d511", macHex1);
|
Assert.assertEquals("1dd68d2f119d5640f0d416e99d3f42408b88d511", macHex1);
|
||||||
|
|
||||||
String macHex2 = mac.digestHex(IoUtil.toStream(testStr, CharsetUtil.CHARSET_UTF_8));
|
String macHex2 = mac.digestHex(IoUtil.toStream(testStr, CharsetUtil.CHARSET_UTF_8));
|
||||||
Assert.assertEquals("1dd68d2f119d5640f0d416e99d3f42408b88d511", macHex2);
|
Assert.assertEquals("1dd68d2f119d5640f0d416e99d3f42408b88d511", macHex2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void zuc128MacTest(){
|
||||||
|
byte[] iv = new byte[16];
|
||||||
|
final byte[] key = new byte[16];
|
||||||
|
HMac mac = new HMac("ZUC-128",
|
||||||
|
KeyUtil.generateKey(ZUC.ZUCAlgorithm.ZUC_128.getValue(), key),
|
||||||
|
new IvParameterSpec(iv));
|
||||||
|
|
||||||
|
String testStr = "test中文";
|
||||||
|
String macHex1 = mac.digestHex(testStr);
|
||||||
|
Assert.assertEquals("1e0b9455", macHex1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void zuc256MacTest(){
|
||||||
|
byte[] iv = new byte[25];
|
||||||
|
final byte[] key = new byte[32];
|
||||||
|
HMac mac = new HMac("ZUC-256",
|
||||||
|
KeyUtil.generateKey(ZUC.ZUCAlgorithm.ZUC_128.getValue(), key),
|
||||||
|
new IvParameterSpec(iv));
|
||||||
|
|
||||||
|
String testStr = "test中文";
|
||||||
|
String macHex1 = mac.digestHex(testStr);
|
||||||
|
Assert.assertEquals("d9ad618357c1bfb1d9d1200a763d5eaa", macHex1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,21 +2,17 @@ package cn.hutool.crypto.test.symmetric;
|
|||||||
|
|
||||||
import cn.hutool.core.util.CharsetUtil;
|
import cn.hutool.core.util.CharsetUtil;
|
||||||
import cn.hutool.core.util.RandomUtil;
|
import cn.hutool.core.util.RandomUtil;
|
||||||
import cn.hutool.crypto.KeyUtil;
|
import cn.hutool.crypto.symmetric.ZUC;
|
||||||
import cn.hutool.crypto.symmetric.SymmetricCrypto;
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import javax.crypto.SecretKey;
|
|
||||||
import javax.crypto.spec.IvParameterSpec;
|
|
||||||
|
|
||||||
public class ZucTest {
|
public class ZucTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void zuc128Test(){
|
public void zuc128Test(){
|
||||||
final SecretKey secretKey = KeyUtil.generateKey("zuc-128");
|
final byte[] secretKey = ZUC.generateKey(ZUC.ZUCAlgorithm.ZUC_128);
|
||||||
byte[] iv = RandomUtil.randomBytes(16);
|
byte[] iv = RandomUtil.randomBytes(16);
|
||||||
final SymmetricCrypto zuc = new SymmetricCrypto("zuc-128", secretKey, new IvParameterSpec(iv));
|
final ZUC zuc = new ZUC(ZUC.ZUCAlgorithm.ZUC_128, secretKey, iv);
|
||||||
|
|
||||||
String msg = RandomUtil.randomString(500);
|
String msg = RandomUtil.randomString(500);
|
||||||
byte[] crypt2 = zuc.encrypt(msg);
|
byte[] crypt2 = zuc.encrypt(msg);
|
||||||
@ -26,9 +22,9 @@ public class ZucTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void zuc256Test(){
|
public void zuc256Test(){
|
||||||
final SecretKey secretKey = KeyUtil.generateKey("zuc-256");
|
final byte[] secretKey = ZUC.generateKey(ZUC.ZUCAlgorithm.ZUC_256);
|
||||||
byte[] iv = RandomUtil.randomBytes(25);
|
byte[] iv = RandomUtil.randomBytes(25);
|
||||||
final SymmetricCrypto zuc = new SymmetricCrypto("zuc-256", secretKey, new IvParameterSpec(iv));
|
final ZUC zuc = new ZUC(ZUC.ZUCAlgorithm.ZUC_256, secretKey, iv);
|
||||||
|
|
||||||
String msg = RandomUtil.randomString(500);
|
String msg = RandomUtil.randomString(500);
|
||||||
byte[] crypt2 = zuc.encrypt(msg);
|
byte[] crypt2 = zuc.encrypt(msg);
|
||||||
|
@ -45,7 +45,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.ofdrw</groupId>
|
<groupId>org.ofdrw</groupId>
|
||||||
<artifactId>ofdrw-full</artifactId>
|
<artifactId>ofdrw-full</artifactId>
|
||||||
<version>1.15.0</version>
|
<version>1.15.1</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user