All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.dromara.hutool.crypto.bc.OpensslKeyUtil Maven / Gradle / Ivy

There is a newer version: 6.0.0.M3
Show newest version
/*
 * Copyright (c) 2013-2024 Hutool Team and hutool.cn
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.dromara.hutool.crypto.bc;

import org.dromara.hutool.core.io.IORuntimeException;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.openssl.PEMDecryptorProvider;
import org.bouncycastle.openssl.PEMEncryptedKeyPair;
import org.bouncycastle.openssl.PEMException;
import org.bouncycastle.openssl.PEMKeyPair;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.X509TrustedCertificateBlock;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
import org.bouncycastle.openssl.jcajce.JceOpenSSLPKCS8DecryptorProviderBuilder;
import org.bouncycastle.openssl.jcajce.JcePEMDecryptorProviderBuilder;
import org.bouncycastle.operator.InputDecryptorProvider;
import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.pkcs.PKCS10CertificationRequest;
import org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo;
import org.bouncycastle.pkcs.PKCSException;
import org.dromara.hutool.crypto.CryptoException;
import org.dromara.hutool.crypto.provider.GlobalProviderFactory;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.security.Key;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.PublicKey;

/**
 * 基于bcpkix封装的Openssl相关工具,包括密钥转换、Pem密钥文件读取等
* 注意此工具需要引入org.bouncycastle:bcpkix-jdk18on * * @author changhr2013, looly * @since 5.8.5 */ public class OpensslKeyUtil { private static final JcaPEMKeyConverter pemKeyConverter = new JcaPEMKeyConverter().setProvider(GlobalProviderFactory.getProvider()); /** * 转换{@link PrivateKeyInfo}为{@link PrivateKey} * * @param privateKeyInfo {@link PrivateKeyInfo} * @return {@link PrivateKey} * @throws CryptoException {@link PEMException}包装 */ public static PrivateKey getPrivateKey(final PrivateKeyInfo privateKeyInfo) throws CryptoException { try { return pemKeyConverter.getPrivateKey(privateKeyInfo); } catch (final PEMException e) { throw new CryptoException(e); } } /** * 转换{@link SubjectPublicKeyInfo}为{@link PublicKey} * * @param publicKeyInfo {@link SubjectPublicKeyInfo} * @return {@link PublicKey} * @throws CryptoException {@link PEMException}包装 */ public static PublicKey getPublicKey(final SubjectPublicKeyInfo publicKeyInfo) throws CryptoException { try { return pemKeyConverter.getPublicKey(publicKeyInfo); } catch (final PEMException e) { throw new CryptoException(e); } } /** * 转换{@link PEMKeyPair}为{@link KeyPair} * * @param keyPair {@link PEMKeyPair} * @return {@link KeyPair} * @throws CryptoException {@link PEMException}包装 */ public static KeyPair getKeyPair(final PEMKeyPair keyPair) throws CryptoException { try { return pemKeyConverter.getKeyPair(keyPair); } catch (final PEMException e) { throw new CryptoException(e); } } /** * 解密{@link PKCS8EncryptedPrivateKeyInfo}为{@link PrivateKeyInfo} * * @param pkcs8Info {@link PKCS8EncryptedPrivateKeyInfo} * @param password 密码 * @return {@link PrivateKeyInfo} * @throws CryptoException OperatorCreationException和PKCSException包装 */ public static PrivateKeyInfo decrypt(final PKCS8EncryptedPrivateKeyInfo pkcs8Info, final char[] password) throws CryptoException { final InputDecryptorProvider decryptProvider; try { decryptProvider = new JceOpenSSLPKCS8DecryptorProviderBuilder() .setProvider(GlobalProviderFactory.getProvider()).build(password); return pkcs8Info.decryptPrivateKeyInfo(decryptProvider); } catch (final OperatorCreationException | PKCSException e) { throw new CryptoException(e); } } /** * 解密{@link PEMEncryptedKeyPair}为{@link PEMKeyPair} * * @param pemEncryptedKeyPair {@link PKCS8EncryptedPrivateKeyInfo} * @param password 密码 * @return {@link PEMKeyPair} * @throws IORuntimeException IOException包装 */ public static PEMKeyPair decrypt(final PEMEncryptedKeyPair pemEncryptedKeyPair, final char[] password) throws IORuntimeException { final PEMDecryptorProvider decryptProvider; try { decryptProvider = new JcePEMDecryptorProviderBuilder() .setProvider(GlobalProviderFactory.getProvider()).build(password); return pemEncryptedKeyPair.decryptKeyPair(decryptProvider); } catch (final IOException e) { throw new IORuntimeException(e); } } /** * 从pem文件中读取公钥或私钥
* 根据类型返回 {@link PublicKey} 或者 {@link PrivateKey} * * @param keyStream pem 流 * @param password 私钥密码 * @return {@link Key},null 表示无法识别的密钥类型 * @since 5.8.5 */ public static Key readPemKey(final InputStream keyStream, final char[] password) { try (final PEMParser pemParser = new PEMParser(new InputStreamReader(keyStream))) { return readPemKeyFromKeyObject(pemParser.readObject(), password); } catch (final IOException e) { throw new CryptoException(e); } } /** * 从pem文件中读取公钥或私钥
* 根据类型返回 {@link PublicKey} 或者 {@link PrivateKey} * * @param keyStream pem 流 * @param password 私钥密码 * @return {@link Key},null 表示无法识别的密钥类型 * @since 5.8.5 */ public static KeyPair readPemKeyPair(final InputStream keyStream, final char[] password) { try (final PEMParser pemParser = new PEMParser(new InputStreamReader(keyStream))) { return readPemKeyPairFromKeyObject(pemParser.readObject(), password); } catch (final IOException e) { throw new CryptoException(e); } } /** * 读取Pem文件中的密钥,密钥支持包括:
*
    *
  • {@link PrivateKeyInfo}
  • *
  • {@link PEMKeyPair},默认读取私钥
  • *
  • {@link PKCS8EncryptedPrivateKeyInfo}
  • *
  • {@link PEMEncryptedKeyPair},默认读取私钥
  • *
  • {@link X509CertificateHolder}
  • *
  • {@link X509TrustedCertificateBlock}
  • *
  • {@link PKCS10CertificationRequest}
  • *
* * @param keyObject 密钥内容对象 * @param password 密码(部分加密的pem使用) * @return {@link Key} * @throws CryptoException 读取异常或不支持的类型 */ private static Key readPemKeyFromKeyObject(final Object keyObject, final char[] password) throws CryptoException { if (keyObject instanceof PrivateKeyInfo) { // PrivateKeyInfo return getPrivateKey((PrivateKeyInfo) keyObject); } else if (keyObject instanceof PEMKeyPair) { // PemKeyPair return getKeyPair((PEMKeyPair) keyObject).getPrivate(); } else if (keyObject instanceof PKCS8EncryptedPrivateKeyInfo) { // Encrypted PrivateKeyInfo return getPrivateKey(decrypt((PKCS8EncryptedPrivateKeyInfo) keyObject, password)); } else if (keyObject instanceof PEMEncryptedKeyPair) { // Encrypted PemKeyPair return getPrivateKey(decrypt((PEMEncryptedKeyPair) keyObject, password).getPrivateKeyInfo()); } else if (keyObject instanceof SubjectPublicKeyInfo) { // SubjectPublicKeyInfo return getPublicKey((SubjectPublicKeyInfo) keyObject); } else if (keyObject instanceof X509CertificateHolder) { // X509 Certificate return getPublicKey(((X509CertificateHolder) keyObject).getSubjectPublicKeyInfo()); } else if (keyObject instanceof X509TrustedCertificateBlock) { // X509 Trusted Certificate return getPublicKey(((X509TrustedCertificateBlock) keyObject).getCertificateHolder().getSubjectPublicKeyInfo()); } else if (keyObject instanceof PKCS10CertificationRequest) { // PKCS#10 CSR return getPublicKey(((PKCS10CertificationRequest) keyObject).getSubjectPublicKeyInfo()); } else { // 表示无法识别的密钥类型 throw new CryptoException("Unsupported key object type: {}", keyObject.getClass()); } } /** * 读取Pem文件中的密钥对,密钥支持包括:
*
    *
  • {@link PEMKeyPair},默认读取私钥
  • *
  • {@link PEMEncryptedKeyPair},默认读取私钥
  • *
* * @param keyObject 密钥内容对象 * @param password 密码(部分加密的pem使用) * @return {@link KeyPair} * @throws CryptoException 读取异常或不支持的类型 */ private static KeyPair readPemKeyPairFromKeyObject(final Object keyObject, final char[] password) throws CryptoException { if (keyObject instanceof PEMKeyPair) { // PemKeyPair return getKeyPair((PEMKeyPair) keyObject); } else if (keyObject instanceof PEMEncryptedKeyPair) { // Encrypted PemKeyPair final PEMKeyPair pemKeyPair = decrypt((PEMEncryptedKeyPair) keyObject, password); return new KeyPair(getPublicKey(pemKeyPair.getPublicKeyInfo()), getPrivateKey(pemKeyPair.getPrivateKeyInfo())); } else { // 表示无法识别的密钥类型 throw new CryptoException("Unsupported key object type: {}", keyObject.getClass()); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy