mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-04-19 03:01:48 +08:00
add openssl
This commit is contained in:
parent
ba2813becb
commit
73ddd17f7a
@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* 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.openssl;
|
||||||
|
|
||||||
|
import org.dromara.hutool.crypto.KeyUtil;
|
||||||
|
import org.dromara.hutool.crypto.SecureUtil;
|
||||||
|
|
||||||
|
import javax.crypto.Cipher;
|
||||||
|
import javax.crypto.SecretKey;
|
||||||
|
import javax.crypto.spec.PBEKeySpec;
|
||||||
|
import javax.crypto.spec.PBEParameterSpec;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
public class OpenSSLPBECommon {
|
||||||
|
protected static final int SALT_SIZE_BYTES = 8;
|
||||||
|
/**
|
||||||
|
* OpenSSL's magic initial bytes.
|
||||||
|
*/
|
||||||
|
protected static final byte[] SALTED_MAGIC = "Salted__".getBytes(StandardCharsets.US_ASCII);
|
||||||
|
protected static final String OPENSSL_HEADER_ENCODE = "ASCII";
|
||||||
|
|
||||||
|
protected static Cipher initializeCipher(char[] password, byte[] salt, int cipherMode,
|
||||||
|
final String algorithm, int iterationCount)
|
||||||
|
throws Exception {
|
||||||
|
|
||||||
|
final SecretKey key = KeyUtil.generateKey(algorithm, new PBEKeySpec(password));
|
||||||
|
|
||||||
|
final Cipher cipher = SecureUtil.createCipher(algorithm);
|
||||||
|
cipher.init(cipherMode, key, new PBEParameterSpec(salt, iterationCount));
|
||||||
|
|
||||||
|
return cipher;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,108 @@
|
|||||||
|
/*
|
||||||
|
* 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.openssl;
|
||||||
|
|
||||||
|
import org.dromara.hutool.core.array.ArrayUtil;
|
||||||
|
import org.dromara.hutool.core.text.StrUtil;
|
||||||
|
|
||||||
|
import javax.crypto.BadPaddingException;
|
||||||
|
import javax.crypto.Cipher;
|
||||||
|
import javax.crypto.IllegalBlockSizeException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
/*
|
||||||
|
source: http://stackoverflow.com/questions/11783062/how-to-decrypt-an-encrypted-file-in-java-with-openssl-with-aes
|
||||||
|
*/
|
||||||
|
public class OpenSSLPBEInputStream extends InputStream {
|
||||||
|
|
||||||
|
protected final static int READ_BLOCK_SIZE = 64 * 1024;
|
||||||
|
|
||||||
|
private final Cipher cipher;
|
||||||
|
private final InputStream inStream;
|
||||||
|
|
||||||
|
private final byte[] bufferCipher = new byte[READ_BLOCK_SIZE];
|
||||||
|
private byte[] bufferClear = null;
|
||||||
|
|
||||||
|
private int index = Integer.MAX_VALUE;
|
||||||
|
private int maxIndex = 0;
|
||||||
|
|
||||||
|
public OpenSSLPBEInputStream(final InputStream streamIn,
|
||||||
|
final String algorithm,
|
||||||
|
final int iterationCount,
|
||||||
|
final char[] password) throws IOException {
|
||||||
|
|
||||||
|
this.inStream = streamIn;
|
||||||
|
|
||||||
|
readHeader();
|
||||||
|
final byte[] salt = readSalt();
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.cipher = OpenSSLPBECommon.initializeCipher(password, salt, Cipher.DECRYPT_MODE, algorithm, iterationCount);
|
||||||
|
} catch (final Exception e) {
|
||||||
|
throw new IOException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int available() throws IOException {
|
||||||
|
return inStream.available();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int read() throws IOException {
|
||||||
|
if (maxIndex < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (index > maxIndex) {
|
||||||
|
index = 0;
|
||||||
|
final int read = inStream.read(bufferCipher);
|
||||||
|
|
||||||
|
if (read != -1) {
|
||||||
|
bufferClear = cipher.update(bufferCipher, 0, read);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (read == -1 || bufferClear == null || bufferClear.length == 0) {
|
||||||
|
try {
|
||||||
|
bufferClear = cipher.doFinal();
|
||||||
|
} catch (IllegalBlockSizeException | BadPaddingException e) {
|
||||||
|
bufferClear = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
maxIndex = bufferClear == null ? -1 : bufferClear.length - 1;
|
||||||
|
|
||||||
|
if (maxIndex < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return bufferClear[index++] & 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void readHeader() throws IOException {
|
||||||
|
final byte[] headerBytes = new byte[OpenSSLPBECommon.SALTED_MAGIC.length];
|
||||||
|
inStream.read(headerBytes);
|
||||||
|
|
||||||
|
if (!Arrays.equals(OpenSSLPBECommon.SALTED_MAGIC, headerBytes)) {
|
||||||
|
throw new IOException("unexpected file header " + StrUtil.utf8Str(headerBytes));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] readSalt() throws IOException {
|
||||||
|
final byte[] salt = new byte[OpenSSLPBECommon.SALT_SIZE_BYTES];
|
||||||
|
inStream.read(salt);
|
||||||
|
return salt;
|
||||||
|
}
|
||||||
|
}
|
@ -12,12 +12,18 @@
|
|||||||
|
|
||||||
package org.dromara.hutool.crypto.symmetric;
|
package org.dromara.hutool.crypto.symmetric;
|
||||||
|
|
||||||
|
import org.dromara.hutool.core.codec.binary.Base64;
|
||||||
|
import org.dromara.hutool.core.io.IoUtil;
|
||||||
|
import org.dromara.hutool.core.lang.Console;
|
||||||
import org.dromara.hutool.crypto.KeyUtil;
|
import org.dromara.hutool.crypto.KeyUtil;
|
||||||
import org.dromara.hutool.crypto.SecureUtil;
|
import org.dromara.hutool.crypto.SecureUtil;
|
||||||
|
import org.dromara.hutool.crypto.openssl.OpenSSLPBEInputStream;
|
||||||
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 javax.crypto.SecretKey;
|
import javax.crypto.SecretKey;
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
public class SaltUtilTest {
|
public class SaltUtilTest {
|
||||||
|
|
||||||
@ -70,4 +76,26 @@ public class SaltUtilTest {
|
|||||||
final String decrypt = des.decryptStr(encrypted);
|
final String decrypt = des.decryptStr(encrypted);
|
||||||
Assertions.assertEquals("hutool", decrypt);
|
Assertions.assertEquals("hutool", decrypt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 测试:
|
||||||
|
* https://www.bejson.com/enc/aesdes/<br>
|
||||||
|
* https://stackoverflow.com/questions/11783062/how-to-decrypt-file-in-java-encrypted-with-openssl-command-using-aes
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
void aesTest2() throws IOException {
|
||||||
|
final String encrypted = "U2FsdGVkX1+lqsuKAR+OdOeNduvx5wgXf6yEUdDIh3g=";
|
||||||
|
final String pass = "1234567890123456";
|
||||||
|
final String algorithm = "PBEWITHMD5AND256BITAES-CBC-OPENSSL";
|
||||||
|
final String result = "hutool";
|
||||||
|
|
||||||
|
final OpenSSLPBEInputStream stream = new OpenSSLPBEInputStream(
|
||||||
|
new ByteArrayInputStream(Base64.decode(encrypted)),
|
||||||
|
algorithm,
|
||||||
|
1,
|
||||||
|
pass.toCharArray());
|
||||||
|
|
||||||
|
final String s = IoUtil.readUtf8(stream);
|
||||||
|
Assertions.assertEquals(result, s);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user