mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-05-09 23:51:34 +08:00
add ASN1Util
This commit is contained in:
parent
7f8f016368
commit
6ac88ef1fe
@ -3,12 +3,13 @@
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
|
||||
# 5.7.10 (2021-08-17)
|
||||
# 5.7.10 (2021-08-18)
|
||||
|
||||
### 🐣新特性
|
||||
* 【core 】 增加NamingCase类
|
||||
* 【core 】 ListUtil增加page方法重载(pr#1761@Github)
|
||||
*
|
||||
* 【crypto 】 增加ASN1Util
|
||||
|
||||
### 🐞Bug修复
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
|
105
hutool-crypto/src/main/java/cn/hutool/crypto/ASN1Util.java
Normal file
105
hutool-crypto/src/main/java/cn/hutool/crypto/ASN1Util.java
Normal file
@ -0,0 +1,105 @@
|
||||
package cn.hutool.crypto;
|
||||
|
||||
import cn.hutool.core.io.FastByteArrayOutputStream;
|
||||
import cn.hutool.core.io.IORuntimeException;
|
||||
import org.bouncycastle.asn1.ASN1Encodable;
|
||||
import org.bouncycastle.asn1.ASN1Encoding;
|
||||
import org.bouncycastle.asn1.ASN1InputStream;
|
||||
import org.bouncycastle.asn1.ASN1Object;
|
||||
import org.bouncycastle.asn1.ASN1Sequence;
|
||||
import org.bouncycastle.asn1.BERSequence;
|
||||
import org.bouncycastle.asn1.DERSequence;
|
||||
import org.bouncycastle.asn1.DLSequence;
|
||||
import org.bouncycastle.asn1.util.ASN1Dump;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
* ASN.1 – Abstract Syntax Notation dot one,抽象记法1 工具类。<br>
|
||||
* ASN.1描述了一种对数据进行表示、编码、传输和解码的数据格式。它的编码格式包括DER、BER、DL等<br>
|
||||
*
|
||||
* @author looly
|
||||
* @since 5.7.10
|
||||
*/
|
||||
public class ASN1Util {
|
||||
|
||||
/**
|
||||
* 编码为DER格式
|
||||
*
|
||||
* @param elements ASN.1元素
|
||||
* @return 编码后的bytes
|
||||
*/
|
||||
public static byte[] encodeDer(ASN1Encodable... elements) {
|
||||
return encode(ASN1Encoding.DER, elements);
|
||||
}
|
||||
|
||||
/**
|
||||
* 编码为指定ASN1格式
|
||||
*
|
||||
* @param asn1Encoding 编码格式,见{@link ASN1Encoding},可选DER、BER或DL
|
||||
* @param elements ASN.1元素
|
||||
* @return 编码后的bytes
|
||||
*/
|
||||
public static byte[] encode(String asn1Encoding, ASN1Encodable... elements) {
|
||||
final FastByteArrayOutputStream out = new FastByteArrayOutputStream();
|
||||
encodeTo(asn1Encoding, out, elements);
|
||||
return out.toByteArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* 编码为指定ASN1格式
|
||||
*
|
||||
* @param asn1Encoding 编码格式,见{@link ASN1Encoding},可选DER、BER或DL
|
||||
* @param out 输出流
|
||||
* @param elements ASN.1元素
|
||||
*/
|
||||
public static void encodeTo(String asn1Encoding, OutputStream out, ASN1Encodable... elements) {
|
||||
ASN1Sequence sequence;
|
||||
switch (asn1Encoding) {
|
||||
case ASN1Encoding.DER:
|
||||
sequence = new DERSequence(elements);
|
||||
break;
|
||||
case ASN1Encoding.BER:
|
||||
sequence = new BERSequence(elements);
|
||||
break;
|
||||
case ASN1Encoding.DL:
|
||||
sequence = new DLSequence(elements);
|
||||
break;
|
||||
default:
|
||||
throw new CryptoException("Unsupported ASN1 encoding: {}", asn1Encoding);
|
||||
}
|
||||
try {
|
||||
sequence.encodeTo(out);
|
||||
} catch (IOException e) {
|
||||
throw new IORuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取ASN.1数据流为{@link ASN1Object}
|
||||
*
|
||||
* @param in ASN.1数据
|
||||
* @return {@link ASN1Object}
|
||||
*/
|
||||
public static ASN1Object decode(InputStream in) {
|
||||
final ASN1InputStream asn1In = new ASN1InputStream(in);
|
||||
try {
|
||||
return asn1In.readObject();
|
||||
} catch (IOException e) {
|
||||
throw new IORuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取ASN1格式的导出格式,一般用于调试
|
||||
*
|
||||
* @param in ASN.1数据
|
||||
* @return {@link ASN1Object}的字符串表示形式
|
||||
* @see ASN1Dump#dumpAsString(Object)
|
||||
*/
|
||||
public static String getDumpStr(InputStream in) {
|
||||
return ASN1Dump.dumpAsString(decode(in));
|
||||
}
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
package cn.hutool.crypto;
|
||||
|
||||
import cn.hutool.core.io.IORuntimeException;
|
||||
import org.bouncycastle.asn1.ASN1Encoding;
|
||||
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
|
||||
import org.bouncycastle.asn1.sec.ECPrivateKey;
|
||||
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
|
||||
@ -300,7 +299,7 @@ public class ECKeyUtil {
|
||||
try {
|
||||
final PrivateKeyInfo info = new PrivateKeyInfo(
|
||||
new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey, SmUtil.ID_SM2_PUBLIC_KEY_PARAM), privateKey);
|
||||
return KeyUtil.generatePrivateKey("SM2", info.getEncoded(ASN1Encoding.DER));
|
||||
return KeyUtil.generatePrivateKey("SM2", info.getEncoded());
|
||||
} catch (IOException e) {
|
||||
throw new IORuntimeException(e);
|
||||
}
|
||||
|
@ -106,7 +106,7 @@ public abstract class AbstractAsymmetricCrypto<T extends AbstractAsymmetricCrypt
|
||||
* @return 加密后的bytes
|
||||
*/
|
||||
public byte[] encrypt(String data, KeyType keyType) {
|
||||
return encrypt(StrUtil.bytes(data, CharsetUtil.CHARSET_UTF_8), keyType);
|
||||
return encrypt(StrUtil.utf8Bytes(data), keyType);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -181,12 +181,30 @@ public class SM2 extends AbstractAsymmetricCrypto<SM2> {
|
||||
// --------------------------------------------------------------------------------- Encrypt
|
||||
|
||||
/**
|
||||
* 加密,SM2非对称加密的结果由C1,C2,C3三部分组成,其中:
|
||||
* 使用公钥加密,SM2非对称加密的结果由C1,C3,C2三部分组成,其中:
|
||||
*
|
||||
* <pre>
|
||||
* C1 生成随机数的计算出的椭圆曲线点
|
||||
* C2 密文数据
|
||||
* C3 SM3的摘要值
|
||||
* C2 密文数据
|
||||
* </pre>
|
||||
*
|
||||
* @param data 被加密的bytes
|
||||
* @return 加密后的bytes
|
||||
* @throws CryptoException 包括InvalidKeyException和InvalidCipherTextException的包装异常
|
||||
* @since 5.7.10
|
||||
*/
|
||||
public byte[] encrypt(byte[] data) throws CryptoException {
|
||||
return encrypt(data, KeyType.PublicKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* 加密,SM2非对称加密的结果由C1,C3,C2三部分组成,其中:
|
||||
*
|
||||
* <pre>
|
||||
* C1 生成随机数的计算出的椭圆曲线点
|
||||
* C3 SM3的摘要值
|
||||
* C2 密文数据
|
||||
* </pre>
|
||||
*
|
||||
* @param data 被加密的bytes
|
||||
@ -232,6 +250,18 @@ public class SM2 extends AbstractAsymmetricCrypto<SM2> {
|
||||
|
||||
// --------------------------------------------------------------------------------- Decrypt
|
||||
|
||||
/**
|
||||
* 使用私钥解密
|
||||
*
|
||||
* @param data SM2密文,实际包含三部分:ECC公钥、真正的密文、公钥和原文的SM3-HASH值
|
||||
* @return 加密后的bytes
|
||||
* @throws CryptoException 包括InvalidKeyException和InvalidCipherTextException的包装异常
|
||||
* @since 5.7.10
|
||||
*/
|
||||
public byte[] decrypt(byte[] data) throws CryptoException {
|
||||
return decrypt(data, KeyType.PrivateKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* 解密
|
||||
*
|
||||
|
@ -1,15 +1,18 @@
|
||||
package cn.hutool.crypto.test.asymmetric;
|
||||
|
||||
import cn.hutool.core.codec.Base64;
|
||||
import cn.hutool.core.io.resource.ResourceUtil;
|
||||
import cn.hutool.core.util.CharsetUtil;
|
||||
import cn.hutool.core.util.HexUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.crypto.ASN1Util;
|
||||
import cn.hutool.crypto.ECKeyUtil;
|
||||
import cn.hutool.crypto.KeyUtil;
|
||||
import cn.hutool.crypto.SecureUtil;
|
||||
import cn.hutool.crypto.SmUtil;
|
||||
import cn.hutool.crypto.asymmetric.KeyType;
|
||||
import cn.hutool.crypto.asymmetric.SM2;
|
||||
import org.bouncycastle.asn1.ASN1Sequence;
|
||||
import org.bouncycastle.crypto.engines.SM2Engine;
|
||||
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
|
||||
import org.bouncycastle.jcajce.spec.OpenSSHPrivateKeySpec;
|
||||
@ -311,4 +314,10 @@ public class SM2Test {
|
||||
byte[] dec = sm2.decrypt(data, KeyType.PrivateKey);
|
||||
Assert.assertArrayEquals(dec, src.getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void asn1DecryptTest(){
|
||||
final SM2 sm2 = SmUtil.sm2("00dc7651c8473110a83215bfd26f37e306b2b99b02da9a4af9b9bd12e6360849bd", null);
|
||||
final ASN1Sequence decode = (ASN1Sequence) ASN1Util.decode(ResourceUtil.getStream("asn1.key"));
|
||||
}
|
||||
}
|
||||
|
BIN
hutool-crypto/src/test/resources/asn1.key
Normal file
BIN
hutool-crypto/src/test/resources/asn1.key
Normal file
Binary file not shown.
@ -81,7 +81,7 @@
|
||||
<dependency>
|
||||
<groupId>com.github.chris2018998</groupId>
|
||||
<artifactId>beecp</artifactId>
|
||||
<version>3.2.5</version>
|
||||
<version>3.2.6</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
@ -161,7 +161,7 @@
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-simple</artifactId>
|
||||
<version>1.7.30</version>
|
||||
<version>1.7.32</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
@ -19,10 +19,10 @@
|
||||
<properties>
|
||||
<!-- versions -->
|
||||
<velocity.version>2.3</velocity.version>
|
||||
<beetl.version>3.5.0.RELEASE</beetl.version>
|
||||
<beetl.version>3.5.1.RELEASE</beetl.version>
|
||||
<rythm.version>1.4.1</rythm.version>
|
||||
<freemarker.version>2.3.31</freemarker.version>
|
||||
<enjoy.version>4.9.15</enjoy.version>
|
||||
<enjoy.version>4.9.16</enjoy.version>
|
||||
<thymeleaf.version>3.0.12.RELEASE</thymeleaf.version>
|
||||
<mail.version>1.6.2</mail.version>
|
||||
<jsch.version>0.1.55</jsch.version>
|
||||
@ -235,7 +235,7 @@
|
||||
<dependency>
|
||||
<groupId>com.hankcs</groupId>
|
||||
<artifactId>hanlp</artifactId>
|
||||
<version>portable-1.7.8</version>
|
||||
<version>portable-1.8.2</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@ -384,7 +384,7 @@
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
<version>1.2.3</version>
|
||||
<version>1.2.5</version>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
|
@ -18,7 +18,7 @@
|
||||
|
||||
<properties>
|
||||
<!-- versions -->
|
||||
<slf4j.version>1.7.30</slf4j.version>
|
||||
<slf4j.version>1.7.32</slf4j.version>
|
||||
<logback.version>1.3.0-alpha5</logback.version>
|
||||
<log4j.version>1.2.17</log4j.version>
|
||||
<log4j2.version>2.14.1</log4j2.version>
|
||||
@ -75,7 +75,7 @@
|
||||
<dependency>
|
||||
<groupId>org.tinylog</groupId>
|
||||
<artifactId>tinylog-api</artifactId>
|
||||
<version>2.2.0</version>
|
||||
<version>2.3.2</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@ -99,7 +99,7 @@
|
||||
<dependency>
|
||||
<groupId>org.tinylog</groupId>
|
||||
<artifactId>tinylog-impl</artifactId>
|
||||
<version>2.2.0</version>
|
||||
<version>2.3.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
@ -45,7 +45,7 @@
|
||||
<dependency>
|
||||
<groupId>org.ofdrw</groupId>
|
||||
<artifactId>ofdrw-full</artifactId>
|
||||
<version>1.13.2</version>
|
||||
<version>1.13.5</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
Loading…
x
Reference in New Issue
Block a user