Browse Source

add methods

Looly 4 years ago
parent
commit
ba8b4ad760

+ 37 - 0
hutool-crypto/src/main/java/cn/hutool/crypto/BCUtil.java

@@ -1,5 +1,8 @@
 package cn.hutool.crypto;
 
+import cn.hutool.core.io.IORuntimeException;
+import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
+import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
 import org.bouncycastle.asn1.x9.X9ECParameters;
 import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
 import org.bouncycastle.crypto.params.ECDomainParameters;
@@ -13,6 +16,7 @@ import org.bouncycastle.jce.spec.ECNamedCurveSpec;
 import org.bouncycastle.jce.spec.ECParameterSpec;
 import org.bouncycastle.math.ec.ECCurve;
 
+import java.io.IOException;
 import java.io.InputStream;
 import java.math.BigInteger;
 import java.security.Key;
@@ -313,4 +317,37 @@ public class BCUtil {
 	public static PublicKey readPemPublicKey(InputStream pemStream) {
 		return PemUtil.readPemPublicKey(pemStream);
 	}
+
+	/**
+	 * Java中的PKCS#8格式私钥转换为OpenSSL支持的PKCS#1格式
+	 *
+	 * @param privateKey PKCS#8格式私钥
+	 * @return PKCS#1格式私钥
+	 * @since 5.5.9
+	 */
+	public static byte[] toPkcs1(PrivateKey privateKey){
+		final PrivateKeyInfo pkInfo = PrivateKeyInfo.getInstance(privateKey.getEncoded());
+		try {
+			return pkInfo.parsePrivateKey().toASN1Primitive().getEncoded();
+		} catch (IOException e) {
+			throw new IORuntimeException(e);
+		}
+	}
+
+	/**
+	 * Java中的X.509格式公钥转换为OpenSSL支持的PKCS#1格式
+	 *
+	 * @param publicKey X.509格式公钥
+	 * @return PKCS#1格式公钥
+	 * @since 5.5.9
+	 */
+	public static byte[] toPkcs1(PublicKey publicKey){
+		final SubjectPublicKeyInfo spkInfo = SubjectPublicKeyInfo
+				.getInstance(publicKey.getEncoded());
+		try {
+			return spkInfo.parsePublicKey().getEncoded();
+		} catch (IOException e) {
+			throw new IORuntimeException(e);
+		}
+	}
 }

+ 55 - 17
hutool-crypto/src/main/java/cn/hutool/crypto/PemUtil.java

@@ -13,6 +13,8 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.Reader;
+import java.io.StringWriter;
+import java.io.Writer;
 import java.security.Key;
 import java.security.PrivateKey;
 import java.security.PublicKey;
@@ -67,7 +69,8 @@ public class PemUtil {
 			//private
 			if (type.endsWith("EC PRIVATE KEY")) {
 				return KeyUtil.generatePrivateKey("EC", object.getContent());
-			}if (type.endsWith("PRIVATE KEY")) {
+			}
+			if (type.endsWith("PRIVATE KEY")) {
 				return KeyUtil.generateRSAPrivateKey(object.getContent());
 			}
 
@@ -131,10 +134,34 @@ public class PemUtil {
 	}
 
 	/**
+	 * 读取OpenSSL生成的ANS1格式的Pem私钥文件
+	 *
+	 * @param keyStream 私钥pem流
+	 * @return {@link PrivateKey}
+	 */
+	public static PrivateKey readSm2PemPrivateKey(InputStream keyStream) {
+		final ECPrivateKey ecPrivateKey = ECPrivateKey.getInstance(readPem(keyStream));
+		return ECKeyUtil.toSm2PrivateKey(ecPrivateKey);
+	}
+
+	/**
+	 * 将私钥或公钥转换为PEM格式的字符串
+	 * @param type 密钥类型(私钥、公钥、证书)
+	 * @param content 密钥内容
+	 * @return PEM内容
+	 * @since 5.5.9
+	 */
+	public static String toPem(String type, byte[] content) {
+		final StringWriter stringWriter = new StringWriter();
+		writePemObject(type, content, stringWriter);
+		return stringWriter.toString();
+	}
+
+	/**
 	 * 写出pem密钥(私钥、公钥、证书)
 	 *
 	 * @param type      密钥类型(私钥、公钥、证书)
-	 * @param content   密钥内容
+	 * @param content   密钥内容,需为PKCS#1格式
 	 * @param keyStream pem流
 	 * @since 5.1.6
 	 */
@@ -145,30 +172,41 @@ public class PemUtil {
 	/**
 	 * 写出pem密钥(私钥、公钥、证书)
 	 *
+	 * @param type    密钥类型(私钥、公钥、证书)
+	 * @param content 密钥内容,需为PKCS#1格式
+	 * @param writer  pemWriter
+	 * @since 5.5.9
+	 */
+	public static void writePemObject(String type, byte[] content, Writer writer) {
+		writePemObject(new PemObject(type, content), writer);
+	}
+
+	/**
+	 * 写出pem密钥(私钥、公钥、证书)
+	 *
 	 * @param pemObject pem对象,包括密钥和密钥类型等信息
 	 * @param keyStream pem流
 	 * @since 5.1.6
 	 */
 	public static void writePemObject(PemObjectGenerator pemObject, OutputStream keyStream) {
-		PemWriter writer = null;
-		try {
-			writer = new PemWriter(IoUtil.getUtf8Writer(keyStream));
-			writer.writeObject(pemObject);
-		} catch (IOException e) {
-			throw new IORuntimeException(e);
-		} finally {
-			IoUtil.close(writer);
-		}
+		writePemObject(pemObject, IoUtil.getUtf8Writer(keyStream));
 	}
 
 	/**
-	 * 读取OpenSSL生成的ANS1格式的Pem私钥文件
+	 * 写出pem密钥(私钥、公钥、证书)
 	 *
-	 * @param keyStream 私钥pem流
-	 * @return {@link PrivateKey}
+	 * @param pemObject pem对象,包括密钥和密钥类型等信息
+	 * @param writer    pemWriter
+	 * @since 5.5.9
 	 */
-	public static PrivateKey readSm2PemPrivateKey(InputStream keyStream){
-		final ECPrivateKey ecPrivateKey = ECPrivateKey.getInstance(readPem(keyStream));
-		return ECKeyUtil.toSm2PrivateKey(ecPrivateKey);
+	public static void writePemObject(PemObjectGenerator pemObject, Writer writer) {
+		final PemWriter pemWriter = new PemWriter(writer);
+		try {
+			pemWriter.writeObject(pemObject);
+		} catch (IOException e) {
+			throw new IORuntimeException(e);
+		} finally {
+			IoUtil.close(pemWriter);
+		}
 	}
 }

+ 4 - 2
hutool-crypto/src/main/java/cn/hutool/crypto/asymmetric/SM2.java

@@ -274,7 +274,8 @@ public class SM2 extends AbstractAsymmetricCrypto<SM2> {
 	}
 
 	/**
-	 * 用私钥对信息生成数字签名
+	 * 用私钥对信息生成数字签名,签名格式为ASN1<br>
+	 * 	 * 在硬件签名中,返回结果为R+S,可以通过调用{@link cn.hutool.crypto.SmUtil#rsAsn1ToPlain(byte[])}方法转换之。
 	 *
 	 * @param data 加密数据
 	 * @return 签名
@@ -295,7 +296,8 @@ public class SM2 extends AbstractAsymmetricCrypto<SM2> {
 	}
 
 	/**
-	 * 用私钥对信息生成数字签名
+	 * 用私钥对信息生成数字签名,签名格式为ASN1<br>
+	 * 在硬件签名中,返回结果为R+S,可以通过调用{@link cn.hutool.crypto.SmUtil#rsAsn1ToPlain(byte[])}方法转换之。
 	 *
 	 * @param data 被签名的数据数据
 	 * @param id   可以为null,若为null,则默认withId为字节数组:"1234567812345678".getBytes()