Dedicated line crypto

This commit is contained in:
hongqiaowei
2021-11-20 16:41:10 +08:00
parent afd31a1a4a
commit 26d8808e03
18 changed files with 645 additions and 222 deletions

View File

@@ -36,6 +36,7 @@ import we.util.NettyDataBufferUtils;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -60,7 +61,9 @@ public class FizzServerHttpRequestDecorator extends ServerHttpRequestDecorator {
@Nullable
private MultiValueMap<String, HttpCookie> cookies;
private Flux<DataBuffer> body = Flux.empty();
private Flux<DataBuffer> body = Flux.empty();
private byte[] bodyBytes;
public FizzServerHttpRequestDecorator(ServerHttpRequest delegate) {
super(delegate);
@@ -128,16 +131,20 @@ public class FizzServerHttpRequestDecorator extends ServerHttpRequestDecorator {
}
public void setEmptyBody() {
this.body = Flux.empty();
body = Flux.empty();
bodyBytes = null;
}
public void setBody(DataBuffer body) {
if (body instanceof PooledDataBuffer) {
byte[] bytes = new byte[body.readableByteCount()];
body.read(bytes);
byte[] bytes = NettyDataBufferUtils.copyBytes(body);
setBody(bytes);
} else {
this.body = Flux.just(body);
ByteBuffer byteBuffer = body.asByteBuffer();
if (byteBuffer.hasArray()) {
bodyBytes = byteBuffer.array();
}
}
}
@@ -147,7 +154,8 @@ public class FizzServerHttpRequestDecorator extends ServerHttpRequestDecorator {
}
public void setBody(byte[] body) {
NettyDataBuffer from = NettyDataBufferUtils.from(body);
bodyBytes = body;
NettyDataBuffer from = NettyDataBufferUtils.from(bodyBytes);
this.body = Flux.just(from);
}
@@ -156,13 +164,7 @@ public class FizzServerHttpRequestDecorator extends ServerHttpRequestDecorator {
return body;
}
// public DataBuffer getRawBody() {
// final DataBuffer[] raw = {null};
// body.subscribe(
// dataBuffer -> {
// raw[0] = dataBuffer;
// }
// );
// return raw[0];
// }
public byte[] getBodyBytes() {
return bodyBytes;
}
}

View File

@@ -46,7 +46,7 @@ public abstract class FizzServerHttpResponseDecorator extends ServerHttpResponse
if (body != NettyDataBufferUtils.EMPTY_DATA_BUFFER) {
if (body instanceof PooledDataBuffer) {
try {
b = NettyDataBufferUtils.from(body.asByteBuffer());
b = NettyDataBufferUtils.copy2heap(body);
} finally {
NettyDataBufferUtils.release(body);
}

View File

@@ -54,15 +54,25 @@ public abstract class NettyDataBufferUtils extends org.springframework.core.io.b
return (NettyDataBuffer) dataBufferFactory.wrap(bytes);
}
public static NettyDataBuffer from(ByteBuffer byteBuffer) {
/*public static NettyDataBuffer from(ByteBuffer byteBuffer) {
return dataBufferFactory.wrap(byteBuffer);
}
public static NettyDataBuffer from(ByteBuf byteBuf) {
return dataBufferFactory.wrap(byteBuf);
}*/
public static byte[] copyBytes(DataBuffer dataBuffer) {
byte[] bytes = new byte[dataBuffer.readableByteCount()];
dataBuffer.read(bytes);
return bytes;
}
public static boolean release(@Nullable String traceId, @Nullable DataBuffer dataBuffer) {
public static DataBuffer copy2heap(DataBuffer dataBuffer) {
return from(copyBytes(dataBuffer));
}
/*public static boolean release(@Nullable String traceId, @Nullable DataBuffer dataBuffer) {
if (dataBuffer instanceof PooledDataBuffer) {
PooledDataBuffer pooledDataBuffer = (PooledDataBuffer) dataBuffer;
if (pooledDataBuffer.isAllocated()) {
@@ -81,5 +91,5 @@ public abstract class NettyDataBufferUtils extends org.springframework.core.io.b
}
}
return false;
}
}*/
}

View File

@@ -0,0 +1,107 @@
/*
* Copyright (C) 2020 the original author or authors.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package we.util;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.KeyUtil;
import cn.hutool.crypto.Padding;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.symmetric.SymmetricAlgorithm;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEParameterSpec;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.spec.AlgorithmParameterSpec;
/**
* @author hongqiaowei
*/
public abstract class SymmetricCryptoUtils {
private SymmetricCryptoUtils() {
}
public static Cipher createCipher(SymmetricAlgorithm algorithm, String key, int mode) {
byte[] keyBytes = SecureUtil.decode(key);
String algorithmName = algorithm.getValue();
SecretKey secretKey = KeyUtil.generateKey(algorithmName, keyBytes);
Cipher cipher = SecureUtil.createCipher(algorithmName);
byte[] iv = cipher.getIV();
AlgorithmParameterSpec parameterSpec = null;
if (StrUtil.startWithIgnoreCase(algorithmName, "AES")) {
if (iv != null) {
parameterSpec = new IvParameterSpec(iv);
}
} else if (StrUtil.startWithIgnoreCase(algorithmName, "PBE")) {
if (null == iv) {
iv = RandomUtil.randomBytes(8);
}
parameterSpec = new PBEParameterSpec(iv, 100);
}
try {
if (null == parameterSpec) {
cipher.init(mode, secretKey);
} else {
cipher.init(mode, secretKey, parameterSpec);
}
} catch (InvalidAlgorithmParameterException | InvalidKeyException e) {
throw new RuntimeException(e);
}
return cipher;
}
public static boolean isZeroPadding(SymmetricAlgorithm algorithm) {
String algorithmName = algorithm.getValue();
return algorithmName.contains(Padding.ZeroPadding.name());
}
public static byte[] paddingWith0(byte[] data, int blockSize) {
int length = data.length;
int remainLength = length % blockSize;
if (remainLength > 0) {
return ArrayUtil.resize(data, length + blockSize - remainLength);
} else {
return data;
}
}
public static byte[] removePadding(byte[] data, int blockSize) {
if (blockSize > 0) {
int length = data.length;
int remainLength = length % blockSize;
if (remainLength == 0) {
int i = length - 1;
while (i >= 0 && 0 == data[i]) {
i--;
}
return ArrayUtil.resize(data, i + 1);
}
}
return data;
}
}

View File

@@ -0,0 +1,72 @@
/*
* Copyright (C) 2020 the original author or authors.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package we.util;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.symmetric.SymmetricAlgorithm;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
/**
* @author hongqiaowei
*/
public class SymmetricDecryptor {
public final SymmetricAlgorithm algorithm;
public final String secretKey;
private final Cipher cipher;
private final boolean isZeroPadding;
public SymmetricDecryptor(SymmetricAlgorithm algorithm, String key) {
this.algorithm = algorithm;
secretKey = key;
cipher = SymmetricCryptoUtils.createCipher(algorithm, key, Cipher.DECRYPT_MODE);
isZeroPadding = SymmetricCryptoUtils.isZeroPadding(algorithm);
}
/**
* @param data can be hex or base64 string
*/
public String decrypt(String data) {
byte[] decode = SecureUtil.decode(data);
return StrUtil.str(decrypt(decode), CharsetUtil.CHARSET_UTF_8);
}
public byte[] decrypt(byte[] data) {
int blockSize = cipher.getBlockSize();
byte[] decryptData;
try {
decryptData = cipher.doFinal(data);
} catch (IllegalBlockSizeException | BadPaddingException e) {
throw new RuntimeException(e);
}
if (isZeroPadding) {
return SymmetricCryptoUtils.removePadding(decryptData, blockSize);
} else {
return decryptData;
}
}
}

View File

@@ -0,0 +1,73 @@
/*
* Copyright (C) 2020 the original author or authors.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package we.util;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.HexUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.symmetric.SymmetricAlgorithm;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
/**
* @author hongqiaowei
*/
public class SymmetricEncryptor {
public final SymmetricAlgorithm algorithm;
public final String secretKey;
private final Cipher cipher;
private final boolean isZeroPadding;
public SymmetricEncryptor(SymmetricAlgorithm algorithm, String key) {
this.algorithm = algorithm;
secretKey = key;
cipher = SymmetricCryptoUtils.createCipher(algorithm, key, Cipher.ENCRYPT_MODE);
isZeroPadding = SymmetricCryptoUtils.isZeroPadding(algorithm);
}
public byte[] encrypt(byte[] data) {
if (isZeroPadding) {
data = SymmetricCryptoUtils.paddingWith0(data, cipher.getBlockSize());
}
try {
return cipher.doFinal(data);
} catch (IllegalBlockSizeException | BadPaddingException e) {
throw new RuntimeException(e);
}
}
public byte[] encrypt(String data) {
return encrypt(StrUtil.bytes(data, CharsetUtil.CHARSET_UTF_8));
}
public String base64encrypt(String data) {
return Base64.encode(encrypt(data));
}
public String hexEncrypt(String data) {
return HexUtil.encodeHexStr(encrypt(data));
}
}

View File

@@ -132,4 +132,15 @@ public abstract class Utils {
return new Throwable(msg, null, false, false) {
};
}
public static String getMessage(Throwable t) {
String message = t.getMessage();
if (message == null) {
StringBuilder b = new StringBuilder();
b.append(t.toString()).append(Consts.S.LF);
b.append("at ").append(t.getStackTrace()[0].toString());
message = b.toString();
}
return message;
}
}

View File

@@ -0,0 +1,24 @@
package we.util;
import cn.hutool.crypto.symmetric.SymmetricAlgorithm;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
public class SymmetricCryptoTests {
@Test
public void encryptTest() {
String secretKey = "1gG1dVcEaQz8JyifTHeEnQ==";
SymmetricEncryptor symmetricEncryptor = new SymmetricEncryptor(SymmetricAlgorithm.AES, secretKey);
String encrypt = symmetricEncryptor.base64encrypt("abc");
SymmetricDecryptor symmetricDecryptor = new SymmetricDecryptor(SymmetricAlgorithm.AES, secretKey);
String decrypt = symmetricDecryptor.decrypt(encrypt);
Assertions.assertEquals("abc", decrypt);
byte[] encryptBytes = symmetricEncryptor.encrypt("123".getBytes());
byte[] decryptBytes = symmetricDecryptor.decrypt(encryptBytes);
Assertions.assertEquals("123", new String(decryptBytes));
}
}