add ASN1Util

This commit is contained in:
Looly 2021-08-18 01:00:32 +08:00
parent 7f8f016368
commit 6ac88ef1fe
11 changed files with 161 additions and 17 deletions

View File

@ -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修复
-------------------------------------------------------------------------------------------------------------

View 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描述了一种对数据进行表示编码传输和解码的数据格式它的编码格式包括DERBERDL等<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}可选DERBER或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}可选DERBER或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));
}
}

View File

@ -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);
}

View File

@ -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);
}
/**

View File

@ -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);
}
/**
* 解密
*

View File

@ -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"));
}
}

Binary file not shown.

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>