侧边栏壁纸
  • 累计撰写 61 篇文章
  • 累计创建 35 个标签
  • 累计收到 4 条评论

目 录CONTENT

文章目录

openssl生成证书与java使用证书签名验签

李洪
2022-10-22 / 0 评论 / 2 点赞 / 396 阅读 / 829 字

证书生成以及签名验签流程

私钥证书

私钥证书生成

//生成4096位的RSA私钥
openssl genrsa -out pkcs1_private.pem 4096

java读取私钥

public PrivateKey generatePrivateKeyWithPKCS8PEM() throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
    byte[] bytes = Files.readAllBytes(Paths.get("D:\\test\\RSA_pkcs8.der"));
    PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(bytes);
    KeyFactory keyFactory = KeyFactory.getInstance("RSA");
    PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
    System.out.println(privateKey.getFormat());
    return privateKey;
}
  • 此时会出现异常
java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: invalid key format

问题原因:Java自带的security包不支持直接读取PEM格式文件。
解决方法:需要将PEM格式转为DER格式再进行读取。

// 把pem格式转化成der格式,使用outform指定der格式
openssl rsa -in RSA.pem -outform der -out RSA.der
  • 修改读取私钥路径,执行代码,也会出现异常
java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException : algid parse error, not a sequence

问题原因:OpenSSL生成的私钥是PKCS#1格式的,而Java自带的security包使用PKCS8EncodedKeySpec来实现私钥,私钥信息是以PKCS#8标准定义的。

解决方法:OpenSSL生成密钥之后在Java环境中使用要先转为PKCS#8格式。

关于PKCS#1与PKCS#8,简单理解两者都是非对称加密私钥信息的标准定义,区别是PKCS#1是针对RSA算法的,而PKCS#8是通用的,两者在格式定义上有些许区别。

提取PCKS8格式的私钥
openssl pkcs8 -topk8 -inform DER -in RSA.der -outform DER -nocrypt -out RSA_pkcs8.der

公钥证书

根据生成的私钥生成公钥证书

// 提取公钥
openssl rsa -in RSA.pem -pubout -out pub.pem 
// 把pem格式转化成der格式,使用outform指定der格式
openssl rsa -pubin -in pub.pem -outform der -out pub.der

Java读取公钥

public PublicKey generatePublicKey() throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
    byte[] bytes = Files.readAllBytes(Paths.get("D:\\test\\pub.der"));
    X509EncodedKeySpec keySpec = new X509EncodedKeySpec(bytes);
    KeyFactory keyFactory = KeyFactory.getInstance("RSA");
    PublicKey publicKey = keyFactory.generatePublic(keySpec);
    System.out.println(publicKey.getFormat());
    return publicKey;
}

java私钥签名,公钥验签

私钥签名

public String signByPrivateKey(String signData) throws NoSuchAlgorithmException, IOException, InvalidKeySpecException, InvalidKeyException, SignatureException {
    byte[] bytes = Base64.decodeBase64(signData);
    PrivateKey privateKey = generatePrivateKeyWithPKCS8PEM();
    Signature signature = Signature.getInstance("SHA1WithRSA");
    signature.initSign(privateKey);
    signature.update(bytes);
    byte[] sign = signature.sign();
    String resultSign = Base64.encodeBase64String(sign);
    System.out.println(resultSign);
    return resultSign;
}

公钥验签

public void verifyByPublicKey() throws NoSuchAlgorithmException, IOException, InvalidKeySpecException, SignatureException, InvalidKeyException {
    String signData="testSign";
    PublicKey publicKey = generatePublicKey();
    String resultSignData = signByPrivateKey(signData);
    Signature signature = Signature.getInstance("SHA1WithRSA");
    signature.initVerify(publicKey);
    signature.update(Base64.decodeBase64(signData));
    boolean verify = signature.verify(Base64.decodeBase64(resultSignData));
    System.out.println(verify);
}

完整代码

import org.apache.commons.codec.binary.Base64;
import org.junit.Test;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

public class TestSecurity {

    public PrivateKey generatePrivateKeyWithPKCS8PEM() throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
        byte[] bytes = Files.readAllBytes(Paths.get("D:\\test\\RSA_pkcs8.der"));
        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(bytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
        System.out.println(privateKey.getFormat());
        return privateKey;
    }


    public PublicKey generatePublicKey() throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
        byte[] bytes = Files.readAllBytes(Paths.get("D:\\test\\pub.der"));
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(bytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PublicKey publicKey = keyFactory.generatePublic(keySpec);
        System.out.println(publicKey.getFormat());
        return publicKey;
    }

    public String signByPrivateKey(String signData) throws NoSuchAlgorithmException, IOException, InvalidKeySpecException, InvalidKeyException, SignatureException {
        byte[] bytes = Base64.decodeBase64(signData);
        PrivateKey privateKey = generatePrivateKeyWithPKCS8PEM();
        Signature signature = Signature.getInstance("SHA1WithRSA");
        signature.initSign(privateKey);
        signature.update(bytes);
        byte[] sign = signature.sign();
        String resultSign = Base64.encodeBase64String(sign);
        System.out.println(resultSign);
        return resultSign;
    }

    @Test
    public void verifyByPublicKey() throws NoSuchAlgorithmException, IOException, InvalidKeySpecException, SignatureException, InvalidKeyException {
        String signData="testSign";
        PublicKey publicKey = generatePublicKey();
        String resultSignData = signByPrivateKey(signData);
        Signature signature = Signature.getInstance("SHA1WithRSA");
        signature.initVerify(publicKey);
        signature.update(Base64.decodeBase64(signData));
        boolean verify = signature.verify(Base64.decodeBase64(resultSignData));
        System.out.println(verify);
    }
}
2

评论区