mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-04-19 03:01:48 +08:00
fix code
This commit is contained in:
parent
13d0ce8817
commit
c2d419ffdc
@ -13,6 +13,7 @@
|
|||||||
package org.dromara.hutool.crypto;
|
package org.dromara.hutool.crypto;
|
||||||
|
|
||||||
import org.dromara.hutool.core.exception.ExceptionUtil;
|
import org.dromara.hutool.core.exception.ExceptionUtil;
|
||||||
|
import org.dromara.hutool.core.exception.HutoolException;
|
||||||
import org.dromara.hutool.core.text.StrUtil;
|
import org.dromara.hutool.core.text.StrUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -20,30 +21,67 @@ import org.dromara.hutool.core.text.StrUtil;
|
|||||||
* @author Looly
|
* @author Looly
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class CryptoException extends RuntimeException {
|
public class CryptoException extends HutoolException {
|
||||||
private static final long serialVersionUID = 8068509879445395353L;
|
private static final long serialVersionUID = 8068509879445395353L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造
|
||||||
|
*
|
||||||
|
* @param e 异常
|
||||||
|
*/
|
||||||
public CryptoException(final Throwable e) {
|
public CryptoException(final Throwable e) {
|
||||||
super(ExceptionUtil.getMessage(e), e);
|
super(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造
|
||||||
|
*
|
||||||
|
* @param message 消息
|
||||||
|
*/
|
||||||
public CryptoException(final String message) {
|
public CryptoException(final String message) {
|
||||||
super(message);
|
super(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造
|
||||||
|
*
|
||||||
|
* @param messageTemplate 消息模板
|
||||||
|
* @param params 参数
|
||||||
|
*/
|
||||||
public CryptoException(final String messageTemplate, final Object... params) {
|
public CryptoException(final String messageTemplate, final Object... params) {
|
||||||
super(StrUtil.format(messageTemplate, params));
|
super(messageTemplate, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CryptoException(final String message, final Throwable throwable) {
|
/**
|
||||||
super(message, throwable);
|
* 构造
|
||||||
|
*
|
||||||
|
* @param message 消息
|
||||||
|
* @param cause 被包装的子异常
|
||||||
|
*/
|
||||||
|
public CryptoException(final String message, final Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CryptoException(final String message, final Throwable throwable, final boolean enableSuppression, final boolean writableStackTrace) {
|
/**
|
||||||
super(message, throwable, enableSuppression, writableStackTrace);
|
* 构造
|
||||||
|
*
|
||||||
|
* @param message 消息
|
||||||
|
* @param cause 被包装的子异常
|
||||||
|
* @param enableSuppression 是否启用抑制
|
||||||
|
* @param writableStackTrace 堆栈跟踪是否应该是可写的
|
||||||
|
*/
|
||||||
|
public CryptoException(final String message, final Throwable cause, final boolean enableSuppression, final boolean writableStackTrace) {
|
||||||
|
super(message, cause, enableSuppression, writableStackTrace);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CryptoException(final Throwable throwable, final String messageTemplate, final Object... params) {
|
/**
|
||||||
super(StrUtil.format(messageTemplate, params), throwable);
|
* 构造
|
||||||
|
*
|
||||||
|
* @param cause 被包装的子异常
|
||||||
|
* @param messageTemplate 消息模板
|
||||||
|
* @param params 参数
|
||||||
|
*/
|
||||||
|
public CryptoException(final Throwable cause, final String messageTemplate, final Object... params) {
|
||||||
|
super(cause, messageTemplate, params);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ import org.dromara.hutool.core.io.file.FileUtil;
|
|||||||
import org.dromara.hutool.core.io.IoUtil;
|
import org.dromara.hutool.core.io.IoUtil;
|
||||||
import org.dromara.hutool.core.lang.Assert;
|
import org.dromara.hutool.core.lang.Assert;
|
||||||
import org.dromara.hutool.core.array.ArrayUtil;
|
import org.dromara.hutool.core.array.ArrayUtil;
|
||||||
|
import org.dromara.hutool.core.lang.Console;
|
||||||
import org.dromara.hutool.core.text.CharUtil;
|
import org.dromara.hutool.core.text.CharUtil;
|
||||||
import org.dromara.hutool.core.util.RandomUtil;
|
import org.dromara.hutool.core.util.RandomUtil;
|
||||||
import org.dromara.hutool.core.text.StrUtil;
|
import org.dromara.hutool.core.text.StrUtil;
|
||||||
@ -620,7 +621,6 @@ public class KeyUtil {
|
|||||||
*/
|
*/
|
||||||
public static KeyGenerator getKeyGenerator(final String algorithm) {
|
public static KeyGenerator getKeyGenerator(final String algorithm) {
|
||||||
final Provider provider = GlobalProviderFactory.getProvider();
|
final Provider provider = GlobalProviderFactory.getProvider();
|
||||||
|
|
||||||
final KeyGenerator generator;
|
final KeyGenerator generator;
|
||||||
try {
|
try {
|
||||||
generator = (null == provider) //
|
generator = (null == provider) //
|
||||||
|
@ -25,14 +25,7 @@ import org.dromara.hutool.crypto.digest.HMac;
|
|||||||
import org.dromara.hutool.crypto.digest.HmacAlgorithm;
|
import org.dromara.hutool.crypto.digest.HmacAlgorithm;
|
||||||
import org.dromara.hutool.crypto.digest.MD5;
|
import org.dromara.hutool.crypto.digest.MD5;
|
||||||
import org.dromara.hutool.crypto.provider.GlobalProviderFactory;
|
import org.dromara.hutool.crypto.provider.GlobalProviderFactory;
|
||||||
import org.dromara.hutool.crypto.symmetric.AES;
|
import org.dromara.hutool.crypto.symmetric.*;
|
||||||
import org.dromara.hutool.crypto.symmetric.DES;
|
|
||||||
import org.dromara.hutool.crypto.symmetric.DESede;
|
|
||||||
import org.dromara.hutool.crypto.symmetric.PBKDF2;
|
|
||||||
import org.dromara.hutool.crypto.symmetric.RC4;
|
|
||||||
import org.dromara.hutool.crypto.symmetric.SymmetricCrypto;
|
|
||||||
import org.dromara.hutool.crypto.symmetric.ZUC;
|
|
||||||
import org.dromara.hutool.crypto.symmetric.FPE;
|
|
||||||
import org.bouncycastle.crypto.AlphabetMapper;
|
import org.bouncycastle.crypto.AlphabetMapper;
|
||||||
|
|
||||||
import javax.crypto.Cipher;
|
import javax.crypto.Cipher;
|
||||||
@ -593,10 +586,10 @@ public class SecureUtil {
|
|||||||
* RC4算法
|
* RC4算法
|
||||||
*
|
*
|
||||||
* @param key 密钥
|
* @param key 密钥
|
||||||
* @return {@link RC4}
|
* @return {@link SymmetricCrypto}
|
||||||
*/
|
*/
|
||||||
public static RC4 rc4(final String key) {
|
public static SymmetricCrypto rc4(final byte[] key) {
|
||||||
return new RC4(key);
|
return new SymmetricCrypto(SymmetricAlgorithm.RC4, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -30,9 +30,9 @@ public class GlobalProviderFactory {
|
|||||||
private static final Provider provider = _createProvider();
|
private static final Provider provider = _createProvider();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取{@link Provider}
|
* 获取{@link Provider},无提供方,返回{@code null}表示使用JDK默认
|
||||||
*
|
*
|
||||||
* @return {@link Provider}
|
* @return {@link Provider} or {@code null}
|
||||||
*/
|
*/
|
||||||
public static Provider getProvider() {
|
public static Provider getProvider() {
|
||||||
return useCustomProvider ? provider : null;
|
return useCustomProvider ? provider : null;
|
||||||
@ -56,6 +56,7 @@ public class GlobalProviderFactory {
|
|||||||
private static Provider _createProvider() {
|
private static Provider _createProvider() {
|
||||||
final ProviderFactory factory = SpiUtil.loadFirstAvailable(ProviderFactory.class);
|
final ProviderFactory factory = SpiUtil.loadFirstAvailable(ProviderFactory.class);
|
||||||
if (null == factory) {
|
if (null == factory) {
|
||||||
|
// 默认JCE
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,281 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2023 looly(loolly@aliyun.com)
|
|
||||||
* Hutool is licensed under Mulan PSL v2.
|
|
||||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
|
||||||
* You may obtain a copy of Mulan PSL v2 at:
|
|
||||||
* http://license.coscl.org.cn/MulanPSL2
|
|
||||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
|
||||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
|
||||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
|
||||||
* See the Mulan PSL v2 for more details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.dromara.hutool.crypto.symmetric;
|
|
||||||
|
|
||||||
import org.dromara.hutool.core.codec.HexUtil;
|
|
||||||
import org.dromara.hutool.core.codec.binary.Base64;
|
|
||||||
import org.dromara.hutool.core.text.StrUtil;
|
|
||||||
import org.dromara.hutool.core.util.ByteUtil;
|
|
||||||
import org.dromara.hutool.core.util.CharsetUtil;
|
|
||||||
import org.dromara.hutool.crypto.CryptoException;
|
|
||||||
import org.dromara.hutool.crypto.SecureUtil;
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.nio.charset.Charset;
|
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
|
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* RC4加密解密算法实现<br>
|
|
||||||
* 注意:由于安全问题,已经基本不在HTTPS中使用了<br>
|
|
||||||
* 来自:https://github.com/xSAVIKx/RC4-cipher/blob/master/src/main/java/com/github/xsavikx/rc4/RC4.java
|
|
||||||
*
|
|
||||||
* @author Iurii Sergiichuk,Looly
|
|
||||||
*/
|
|
||||||
public class RC4 implements Serializable {
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
|
|
||||||
private static final int SBOX_LENGTH = 256;
|
|
||||||
/** 密钥最小长度 */
|
|
||||||
private static final int KEY_MIN_LENGTH = 5;
|
|
||||||
|
|
||||||
/** Sbox */
|
|
||||||
private int[] sbox;
|
|
||||||
|
|
||||||
private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 构造
|
|
||||||
*
|
|
||||||
* @param key 密钥
|
|
||||||
* @throws CryptoException key长度小于5或者大于255抛出此异常
|
|
||||||
*/
|
|
||||||
public RC4(final String key) throws CryptoException {
|
|
||||||
setKey(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 加密
|
|
||||||
*
|
|
||||||
* @param message 消息
|
|
||||||
* @param charset 编码
|
|
||||||
* @return 密文
|
|
||||||
* @throws CryptoException key长度小于5或者大于255抛出此异常
|
|
||||||
*/
|
|
||||||
public byte[] encrypt(final String message, final Charset charset) throws CryptoException {
|
|
||||||
return crypt(ByteUtil.toBytes(message, charset));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 加密,使用默认编码:UTF-8
|
|
||||||
*
|
|
||||||
* @param message 消息
|
|
||||||
* @return 密文
|
|
||||||
* @throws CryptoException key长度小于5或者大于255抛出此异常
|
|
||||||
*/
|
|
||||||
public byte[] encrypt(final String message) throws CryptoException {
|
|
||||||
return encrypt(message, CharsetUtil.UTF_8);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 加密
|
|
||||||
*
|
|
||||||
* @param data 数据
|
|
||||||
* @return 加密后的Hex
|
|
||||||
* @since 4.5.12
|
|
||||||
*/
|
|
||||||
public String encryptHex(final byte[] data) {
|
|
||||||
return HexUtil.encodeHexStr(crypt(data));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 加密
|
|
||||||
*
|
|
||||||
* @param data 数据
|
|
||||||
* @return 加密后的Base64
|
|
||||||
* @since 4.5.12
|
|
||||||
*/
|
|
||||||
public String encryptBase64(final byte[] data) {
|
|
||||||
return Base64.encode(crypt(data));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 加密
|
|
||||||
*
|
|
||||||
* @param data 被加密的字符串
|
|
||||||
* @param charset 编码
|
|
||||||
* @return 加密后的Hex
|
|
||||||
* @since 4.5.12
|
|
||||||
*/
|
|
||||||
public String encryptHex(final String data, final Charset charset) {
|
|
||||||
return HexUtil.encodeHexStr(encrypt(data, charset));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 加密,使用UTF-8编码
|
|
||||||
*
|
|
||||||
* @param data 被加密的字符串
|
|
||||||
* @return 加密后的Hex
|
|
||||||
* @since 5.4.4
|
|
||||||
*/
|
|
||||||
public String encryptHex(final String data) {
|
|
||||||
return HexUtil.encodeHexStr(encrypt(data));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 加密
|
|
||||||
*
|
|
||||||
* @param data 被加密的字符串
|
|
||||||
* @param charset 编码
|
|
||||||
* @return 加密后的Base64
|
|
||||||
* @since 4.5.12
|
|
||||||
*/
|
|
||||||
public String encryptBase64(final String data, final Charset charset) {
|
|
||||||
return Base64.encode(encrypt(data, charset));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 加密,使用UTF-8编码
|
|
||||||
*
|
|
||||||
* @param data 被加密的字符串
|
|
||||||
* @return 加密后的Base64
|
|
||||||
* @since 5.4.4
|
|
||||||
*/
|
|
||||||
public String encryptBase64(final String data) {
|
|
||||||
return Base64.encode(encrypt(data));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 解密
|
|
||||||
*
|
|
||||||
* @param message 消息
|
|
||||||
* @param charset 编码
|
|
||||||
* @return 明文
|
|
||||||
* @throws CryptoException key长度小于5或者大于255抛出此异常
|
|
||||||
*/
|
|
||||||
public String decrypt(final byte[] message, final Charset charset) throws CryptoException {
|
|
||||||
return StrUtil.str(crypt(message), charset);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 解密,使用默认编码UTF-8
|
|
||||||
*
|
|
||||||
* @param message 消息
|
|
||||||
* @return 明文
|
|
||||||
* @throws CryptoException key长度小于5或者大于255抛出此异常
|
|
||||||
*/
|
|
||||||
public String decrypt(final byte[] message) throws CryptoException {
|
|
||||||
return decrypt(message, CharsetUtil.UTF_8);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 解密Hex(16进制)或Base64表示的字符串,使用默认编码UTF-8
|
|
||||||
*
|
|
||||||
* @param message 消息
|
|
||||||
* @return 明文
|
|
||||||
* @since 5.4.4
|
|
||||||
*/
|
|
||||||
public String decrypt(final String message) {
|
|
||||||
return decrypt(SecureUtil.decode(message));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 解密Hex(16进制)或Base64表示的字符串
|
|
||||||
*
|
|
||||||
* @param message 明文
|
|
||||||
* @param charset 解密后的charset
|
|
||||||
* @return 明文
|
|
||||||
* @since 5.4.4
|
|
||||||
*/
|
|
||||||
public String decrypt(final String message, final Charset charset) {
|
|
||||||
return StrUtil.str(decrypt(message), charset);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 加密或解密指定值,调用此方法前需初始化密钥
|
|
||||||
*
|
|
||||||
* @param msg 要加密或解密的消息
|
|
||||||
* @return 加密或解密后的值
|
|
||||||
*/
|
|
||||||
public byte[] crypt(final byte[] msg) {
|
|
||||||
final ReadLock readLock = this.lock.readLock();
|
|
||||||
byte[] code;
|
|
||||||
readLock.lock();
|
|
||||||
try {
|
|
||||||
final int[] sbox = this.sbox.clone();
|
|
||||||
code = new byte[msg.length];
|
|
||||||
int i = 0;
|
|
||||||
int j = 0;
|
|
||||||
for (int n = 0; n < msg.length; n++) {
|
|
||||||
i = (i + 1) % SBOX_LENGTH;
|
|
||||||
j = (j + sbox[i]) % SBOX_LENGTH;
|
|
||||||
swap(i, j, sbox);
|
|
||||||
final int rand = sbox[(sbox[i] + sbox[j]) % SBOX_LENGTH];
|
|
||||||
code[n] = (byte) (rand ^ msg[n]);
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
readLock.unlock();
|
|
||||||
}
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置密钥
|
|
||||||
*
|
|
||||||
* @param key 密钥
|
|
||||||
* @throws CryptoException key长度小于5或者大于255抛出此异常
|
|
||||||
*/
|
|
||||||
public void setKey(final String key) throws CryptoException {
|
|
||||||
final int length = key.length();
|
|
||||||
if (length < KEY_MIN_LENGTH || length >= SBOX_LENGTH) {
|
|
||||||
throw new CryptoException("Key length has to be between {} and {}", KEY_MIN_LENGTH, (SBOX_LENGTH - 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
final WriteLock writeLock = this.lock.writeLock();
|
|
||||||
writeLock.lock();
|
|
||||||
try {
|
|
||||||
this.sbox = initSBox(ByteUtil.toUtf8Bytes(key));
|
|
||||||
} finally {
|
|
||||||
writeLock.unlock();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------------------------------- Private method start
|
|
||||||
/**
|
|
||||||
* 初始化Sbox
|
|
||||||
*
|
|
||||||
* @param key 密钥
|
|
||||||
* @return sbox
|
|
||||||
*/
|
|
||||||
private int[] initSBox(final byte[] key) {
|
|
||||||
final int[] sbox = new int[SBOX_LENGTH];
|
|
||||||
int j = 0;
|
|
||||||
|
|
||||||
for (int i = 0; i < SBOX_LENGTH; i++) {
|
|
||||||
sbox[i] = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < SBOX_LENGTH; i++) {
|
|
||||||
j = (j + sbox[i] + (key[i % key.length]) & 0xFF) % SBOX_LENGTH;
|
|
||||||
swap(i, j, sbox);
|
|
||||||
}
|
|
||||||
return sbox;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 交换指定两个位置的值
|
|
||||||
*
|
|
||||||
* @param i 位置1
|
|
||||||
* @param j 位置2
|
|
||||||
* @param sbox 数组
|
|
||||||
*/
|
|
||||||
private void swap(final int i, final int j, final int[] sbox) {
|
|
||||||
final int temp = sbox[i];
|
|
||||||
sbox[i] = sbox[j];
|
|
||||||
sbox[j] = temp;
|
|
||||||
}
|
|
||||||
//----------------------------------------------------------------------------------------------------------------------- Private method end
|
|
||||||
}
|
|
@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023 looly(loolly@aliyun.com)
|
||||||
|
* Hutool is licensed under Mulan PSL v2.
|
||||||
|
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||||
|
* You may obtain a copy of Mulan PSL v2 at:
|
||||||
|
* http://license.coscl.org.cn/MulanPSL2
|
||||||
|
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||||
|
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||||
|
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the Mulan PSL v2 for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.dromara.hutool.crypto.symmetric;
|
||||||
|
|
||||||
|
import org.dromara.hutool.core.array.ArrayUtil;
|
||||||
|
import org.dromara.hutool.crypto.digest.DigestUtil;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OpenSSL风格前缀和加盐相关工具类<br>
|
||||||
|
* 参考:https://stackoverflow.com/questions/32508961/java-equivalent-of-an-openssl-aes-cbc-encryption
|
||||||
|
*
|
||||||
|
* @author looly
|
||||||
|
* @since 6.0.0
|
||||||
|
*/
|
||||||
|
public class SaltUtil {
|
||||||
|
|
||||||
|
private final static byte SALT_LEN = 8;
|
||||||
|
private final static byte IV_LEN = 16;
|
||||||
|
private final static byte KEY_LEN = 32;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OpenSSL's magic initial bytes.
|
||||||
|
*/
|
||||||
|
private static final byte[] SALTED_MAGIC = "Salted__".getBytes(StandardCharsets.US_ASCII);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取8位salt随机数<br>
|
||||||
|
*
|
||||||
|
* @param encryptedData 密文
|
||||||
|
* @return salt随机数
|
||||||
|
*/
|
||||||
|
public static byte[] getSalt(final byte[] encryptedData) {
|
||||||
|
if (ArrayUtil.startWith(encryptedData, SALTED_MAGIC)) {
|
||||||
|
return Arrays.copyOfRange(encryptedData, SALTED_MAGIC.length, SALTED_MAGIC.length + SALT_LEN);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过密钥和salt值,获取实际的密钥
|
||||||
|
*
|
||||||
|
* @param pass 密钥
|
||||||
|
* @param salt 加盐值
|
||||||
|
* @return 实际密钥
|
||||||
|
*/
|
||||||
|
public static byte[] getKey(final byte[] pass, final byte[] salt) {
|
||||||
|
if (null == salt) {
|
||||||
|
return pass;
|
||||||
|
}
|
||||||
|
final byte[] passAndSalt = arrayConcat(pass, salt);
|
||||||
|
|
||||||
|
byte[] hash = new byte[0];
|
||||||
|
byte[] keyAndIv = new byte[0];
|
||||||
|
for (int i = 0; i < 3 && keyAndIv.length < 48; i++) {
|
||||||
|
final byte[] hashData = arrayConcat(hash, passAndSalt);
|
||||||
|
hash = DigestUtil.md5(hashData);
|
||||||
|
keyAndIv = arrayConcat(keyAndIv, hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Arrays.copyOfRange(keyAndIv, 0, KEY_LEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] arrayConcat(final byte[] a, final byte[] b) {
|
||||||
|
if (ArrayUtil.isEmpty(a)) {
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
final byte[] c = new byte[a.length + b.length];
|
||||||
|
System.arraycopy(a, 0, c, 0, a.length);
|
||||||
|
System.arraycopy(b, 0, c, a.length, b.length);
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
}
|
@ -43,6 +43,10 @@ public enum SymmetricAlgorithm {
|
|||||||
* RC2
|
* RC2
|
||||||
*/
|
*/
|
||||||
RC2("RC2"),
|
RC2("RC2"),
|
||||||
|
/**
|
||||||
|
* RC4
|
||||||
|
*/
|
||||||
|
RC4("RC4"),
|
||||||
/**
|
/**
|
||||||
*PBEWithMD5AndDES
|
*PBEWithMD5AndDES
|
||||||
*/
|
*/
|
||||||
|
@ -219,7 +219,7 @@ public class SymmetricCrypto implements SymmetricEncryptor, SymmetricDecryptor,
|
|||||||
* @return this
|
* @return this
|
||||||
* @since 5.7.17
|
* @since 5.7.17
|
||||||
*/
|
*/
|
||||||
public SymmetricCrypto setRandom(final SecureRandom random){
|
public SymmetricCrypto setRandom(final SecureRandom random) {
|
||||||
this.cipherWrapper.setRandom(random);
|
this.cipherWrapper.setRandom(random);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -233,7 +233,7 @@ public class SymmetricCrypto implements SymmetricEncryptor, SymmetricDecryptor,
|
|||||||
* @return this
|
* @return this
|
||||||
* @since 5.7.12
|
* @since 5.7.12
|
||||||
*/
|
*/
|
||||||
public SymmetricCrypto setMode(final CipherMode mode){
|
public SymmetricCrypto setMode(final CipherMode mode) {
|
||||||
lock.lock();
|
lock.lock();
|
||||||
try {
|
try {
|
||||||
initMode(mode.getValue());
|
initMode(mode.getValue());
|
||||||
@ -335,6 +335,7 @@ public class SymmetricCrypto implements SymmetricEncryptor, SymmetricDecryptor,
|
|||||||
final byte[] decryptData;
|
final byte[] decryptData;
|
||||||
|
|
||||||
lock.lock();
|
lock.lock();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final Cipher cipher = initMode(Cipher.DECRYPT_MODE);
|
final Cipher cipher = initMode(Cipher.DECRYPT_MODE);
|
||||||
blockSize = cipher.getBlockSize();
|
blockSize = cipher.getBlockSize();
|
||||||
|
@ -2,6 +2,7 @@ package org.dromara.hutool.crypto.symmetric;
|
|||||||
|
|
||||||
import org.dromara.hutool.core.codec.binary.Base64;
|
import org.dromara.hutool.core.codec.binary.Base64;
|
||||||
import org.dromara.hutool.core.codec.HexUtil;
|
import org.dromara.hutool.core.codec.HexUtil;
|
||||||
|
import org.dromara.hutool.core.lang.Console;
|
||||||
import org.dromara.hutool.core.util.RandomUtil;
|
import org.dromara.hutool.core.util.RandomUtil;
|
||||||
import org.dromara.hutool.crypto.KeyUtil;
|
import org.dromara.hutool.crypto.KeyUtil;
|
||||||
import org.dromara.hutool.crypto.Mode;
|
import org.dromara.hutool.crypto.Mode;
|
||||||
|
@ -1,38 +1,41 @@
|
|||||||
package org.dromara.hutool.crypto.symmetric;
|
package org.dromara.hutool.crypto.symmetric;
|
||||||
|
|
||||||
import org.dromara.hutool.core.util.CharsetUtil;
|
import org.dromara.hutool.core.util.CharsetUtil;
|
||||||
|
import org.dromara.hutool.crypto.provider.GlobalProviderFactory;
|
||||||
import org.junit.jupiter.api.Assertions;
|
import org.junit.jupiter.api.Assertions;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
public class RC4Test {
|
public class RC4Test {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCryptMessage() {
|
public void testCryptMessage() {
|
||||||
final String key = "This is pretty long key";
|
final byte[] key = "This is pretty long key".getBytes();
|
||||||
final RC4 rc4 = new RC4(key);
|
final SymmetricCrypto SymmetricCrypto = new SymmetricCrypto("RC4", key);
|
||||||
final String message = "Hello, World!";
|
final String message = "Hello, World!";
|
||||||
final byte[] crypt = rc4.encrypt(message);
|
final byte[] crypt = SymmetricCrypto.encrypt(message);
|
||||||
final String msg = rc4.decrypt(crypt);
|
final String msg = SymmetricCrypto.decryptStr(crypt);
|
||||||
Assertions.assertEquals(message, msg);
|
Assertions.assertEquals(message, msg);
|
||||||
|
|
||||||
final String message2 = "Hello, World, this is megssage 2";
|
final String message2 = "Hello, World, this is megssage 2";
|
||||||
final byte[] crypt2 = rc4.encrypt(message2);
|
final byte[] crypt2 = SymmetricCrypto.encrypt(message2);
|
||||||
final String msg2 = rc4.decrypt(crypt2);
|
final String msg2 = SymmetricCrypto.decryptStr(crypt2);
|
||||||
Assertions.assertEquals(message2, msg2);
|
Assertions.assertEquals(message2, msg2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCryptWithChineseCharacters() {
|
public void testCryptWithChineseCharacters() {
|
||||||
final String message = "这是一个中文消息!";
|
final String message = "这是一个中文消息!";
|
||||||
final String key = "我是一个文件密钥";
|
final byte[] key = "我是一个文件密钥".getBytes(StandardCharsets.UTF_8);
|
||||||
final RC4 rc4 = new RC4(key);
|
final SymmetricCrypto SymmetricCrypto = new SymmetricCrypto("RC4", key);
|
||||||
final byte[] crypt = rc4.encrypt(message);
|
final byte[] crypt = SymmetricCrypto.encrypt(message);
|
||||||
final String msg = rc4.decrypt(crypt);
|
final String msg = SymmetricCrypto.decryptStr(crypt);
|
||||||
Assertions.assertEquals(message, msg);
|
Assertions.assertEquals(message, msg);
|
||||||
|
|
||||||
final String message2 = "这是第二个中文消息!";
|
final String message2 = "这是第二个中文消息!";
|
||||||
final byte[] crypt2 = rc4.encrypt(message2);
|
final byte[] crypt2 = SymmetricCrypto.encrypt(message2);
|
||||||
final String msg2 = rc4.decrypt(crypt2);
|
final String msg2 = SymmetricCrypto.decryptStr(crypt2);
|
||||||
Assertions.assertEquals(message2, msg2);
|
Assertions.assertEquals(message2, msg2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,14 +43,14 @@ public class RC4Test {
|
|||||||
public void testDecryptWithHexMessage() {
|
public void testDecryptWithHexMessage() {
|
||||||
final String message = "这是第一个用来测试密文为十六进制字符串的消息!";
|
final String message = "这是第一个用来测试密文为十六进制字符串的消息!";
|
||||||
final String key = "生成一个密钥";
|
final String key = "生成一个密钥";
|
||||||
final RC4 rc4 = new RC4(key);
|
final SymmetricCrypto SymmetricCrypto = new SymmetricCrypto("RC4", key.getBytes(StandardCharsets.UTF_8));
|
||||||
final String encryptHex = rc4.encryptHex(message, CharsetUtil.UTF_8);
|
final String encryptHex = SymmetricCrypto.encryptHex(message, CharsetUtil.UTF_8);
|
||||||
final String msg = rc4.decrypt(encryptHex);
|
final String msg = SymmetricCrypto.decryptStr(encryptHex);
|
||||||
Assertions.assertEquals(message, msg);
|
Assertions.assertEquals(message, msg);
|
||||||
|
|
||||||
final String message2 = "这是第二个用来测试密文为十六进制字符串的消息!";
|
final String message2 = "这是第二个用来测试密文为十六进制字符串的消息!";
|
||||||
final String encryptHex2 = rc4.encryptHex(message2);
|
final String encryptHex2 = SymmetricCrypto.encryptHex(message2);
|
||||||
final String msg2 = rc4.decrypt(encryptHex2);
|
final String msg2 = SymmetricCrypto.decryptStr(encryptHex2);
|
||||||
Assertions.assertEquals(message2, msg2);
|
Assertions.assertEquals(message2, msg2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,14 +59,21 @@ public class RC4Test {
|
|||||||
public void testDecryptWithBase64Message() {
|
public void testDecryptWithBase64Message() {
|
||||||
final String message = "这是第一个用来测试密文为Base64编码的消息!";
|
final String message = "这是第一个用来测试密文为Base64编码的消息!";
|
||||||
final String key = "生成一个密钥";
|
final String key = "生成一个密钥";
|
||||||
final RC4 rc4 = new RC4(key);
|
final SymmetricCrypto SymmetricCrypto = new SymmetricCrypto("RC4", key.getBytes(StandardCharsets.UTF_8));
|
||||||
final String encryptHex = rc4.encryptBase64(message, CharsetUtil.UTF_8);
|
final String encryptHex = SymmetricCrypto.encryptBase64(message, CharsetUtil.UTF_8);
|
||||||
final String msg = rc4.decrypt(encryptHex);
|
final String msg = SymmetricCrypto.decryptStr(encryptHex);
|
||||||
Assertions.assertEquals(message, msg);
|
Assertions.assertEquals(message, msg);
|
||||||
|
|
||||||
final String message2 = "这是第一个用来测试密文为Base64编码的消息!";
|
final String message2 = "这是第一个用来测试密文为Base64编码的消息!";
|
||||||
final String encryptHex2 = rc4.encryptBase64(message2);
|
final String encryptHex2 = SymmetricCrypto.encryptBase64(message2);
|
||||||
final String msg2 = rc4.decrypt(encryptHex2);
|
final String msg2 = SymmetricCrypto.decryptStr(encryptHex2);
|
||||||
Assertions.assertEquals(message2, msg2);
|
Assertions.assertEquals(message2, msg2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void decryptTest() {
|
||||||
|
GlobalProviderFactory.setUseCustomProvider(false);
|
||||||
|
final String key16 = "1234567890123456";
|
||||||
|
final SymmetricCrypto aes = new SymmetricCrypto("SymmetricCrypto", key16.getBytes());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user