首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >java下使用openssl生成公私钥

java下使用openssl生成公私钥

原创
作者头像
sabergo
发布2019-02-21 19:27:45
2.5K0
发布2019-02-21 19:27:45
举报
文章被收录于专栏:itsoeasyitsoeasy

公私钥准备

  1. 使用openssl生成私钥 openssl genrsa -out rsa_private.key 1024 这里使用1024使用通用场景,需要加强的话使用2048
  2. 使用openssl生成公钥 openssl rsa -in rsa_private.key -out rsa_public.key -pubout

java的私钥格式要求

查看刚刚生成的私钥的页眉页脚都是带有“rsa”加密方式

-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQDMnP55TJgP2g6mHby+dXLmRL1MNSh+GKi4G1+gp9tQVFXGX3PV
...
LCgUw8xUu4Fozo7KGuinmKAlQz1NvzcqDYCKAlwOPeNa
-----END RSA PRIVATE KEY-----

这个文件格式是如下

-----页眉-----
DER格式
-----页脚-----

DER说明

-inform DER|NET|PEM This specifies the input format. The DER option uses an ASN1 DER encoded form

compatible with the PKCS#1 RSAPrivateKey or SubjectPublicKeyInfo format.

The PEM form is the default format: it consists of the DER format base64

encoded with additional header and footer lines. On input PKCS#8 format

private keys are also accepted. The NET form is a format is described

in the NOTES section.

Java具有私钥的编码密钥规范:PKCS8EncodedKeySpec - 但是,它实现了“PKCS#8”而不是我们使用的“PKCS#1”。幸运的是,OpenSSL还包含一个这种格式的转换器:

openssl pkcs8 -topk8 -in rsa_private.key -out pkcs8_rsa_private.key -nocrypt

转换后格式如下

-----BEGIN PRIVATE KEY-----
MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMyc/nlMmA/aDqYd
-----END PRIVATE KEY-----

这里就大概得出结论是: java要读取openssl文件需要去掉页眉页脚来der且全换成经过base64反编译得真实编码值

代码片段

详细代码查看后面源码文件

读取公钥,采用的是509格式

    public static PublicKey readPublicKeyFromFile (String path, String
            algorithm)
            throws IOException, NoSuchAlgorithmException,
    InvalidKeySpecException

    {
        String publicKeyPEM = FileUtils.readFileToString(
                new File(path), "UTF8");

        publicKeyPEM = publicKeyPEM
                .replace("-----BEGIN PUBLIC KEY-----", "")
                .replace("-----END PUBLIC KEY-----", "");

        byte[] publicKeyDER = new BASE64Decoder().decodeBuffer(publicKeyPEM);

        KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
        PublicKey publicKey = keyFactory.generatePublic(new X509EncodedKeySpec(publicKeyDER));

        return publicKey;
    }
  1. 这里FileUtils是来自依赖apache的commons-io的,读取文件到一个String。
  2. 去掉页眉页脚
  3. 转码得到真实编码Base64Decoder
  4. 通过api获取对应的密钥

读取私钥,采用的是PCK#8

    public static PrivateKey readPrivateKeyFromFile (String path, String
            algorithm)
            throws IOException, NoSuchAlgorithmException,
            InvalidKeySpecException

    {
        String privateKeyPEM = FileUtils.readFileToString(
                new File(path), "UTF8");

        privateKeyPEM = privateKeyPEM
                .replace("-----BEGIN PRIVATE KEY-----", "")
                .replace("-----END PRIVATE KEY-----", "");

        byte[] privateKeyDER = new BASE64Decoder().decodeBuffer(privateKeyPEM);

        KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
        PrivateKey privateKey = keyFactory.generatePrivate(new PKCS8EncodedKeySpec(privateKeyDER));

        return privateKey;
    }

源码文件

CyperUtil.java

package com.roger;

import org.apache.commons.io.FileUtils;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;


public class CyperUtil {
    /**
     * <p>
     * 用私钥对信息生成数字签名
     * </p>
     *
     * @param data 数据
     * @param privateKey 私钥
     *
     * @return
     * @throws Exception
     */
    public static String sign(byte[] data, PrivateKey privateKey) throws
            Exception {
//        byte[] data = plainText.getBytes("UTF8");

        Signature sig = Signature.getInstance("SHA1WithRSA");
        sig.initSign(privateKey);
        sig.update(data);
        byte[] signatureBytes = sig.sign();
        return new BASE64Encoder().encode(signatureBytes);
    }

    /**
     * <p>
     * 校验数字签名
     * </p>
     *
     * @param data 数据
     * @param publicKey 公钥
     * @param sign 数字签名
     *
     * @return
     * @throws Exception
     *
     */
    public static boolean verify(byte[] data, PublicKey publicKey, String sign)
            throws Exception {
        byte[] s = new BASE64Decoder().decodeBuffer(sign);
        Signature sig = Signature.getInstance("SHA1WithRSA");
        sig.initVerify(publicKey);
        sig.update(data);
        return sig.verify(s);
    }

    /**
     * <p>
     * 从文件加载公钥
     * </p>
     *
     * @param path 文件路劲
     * @param algorithm 算法名称
     *
     * @return PublicKey 公钥
     * @throws IOException, NoSuchAlgorithmException,
     *             InvalidKeySpecException
     *
     */
    public static PublicKey readPublicKeyFromFile (String path, String
            algorithm)
            throws IOException, NoSuchAlgorithmException,
    InvalidKeySpecException

    {
        String publicKeyPEM = FileUtils.readFileToString(
                new File(path), "UTF8");

        publicKeyPEM = publicKeyPEM
                .replace("-----BEGIN PUBLIC KEY-----", "")
                .replace("-----END PUBLIC KEY-----", "");

        byte[] publicKeyDER = new BASE64Decoder().decodeBuffer(publicKeyPEM);

        KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
        PublicKey publicKey = keyFactory.generatePublic(new X509EncodedKeySpec(publicKeyDER));

        return publicKey;
    }


    /**
     * <p>
     * 从文件加载私钥
     * </p>
     *
     * @param path 文件路劲
     * @param algorithm 算法名称
     *
     * @return PrivateKey 私钥
     * @throws IOException, NoSuchAlgorithmException,
     *             InvalidKeySpecException
     *
     */
    public static PrivateKey readPrivateKeyFromFile (String path, String
            algorithm)
            throws IOException, NoSuchAlgorithmException,
            InvalidKeySpecException

    {
        String privateKeyPEM = FileUtils.readFileToString(
                new File(path), "UTF8");

        privateKeyPEM = privateKeyPEM
                .replace("-----BEGIN PRIVATE KEY-----", "")
                .replace("-----END PRIVATE KEY-----", "");

        byte[] privateKeyDER = new BASE64Decoder().decodeBuffer(privateKeyPEM);

        KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
        PrivateKey privateKey = keyFactory.generatePrivate(new PKCS8EncodedKeySpec(privateKeyDER));

        return privateKey;
    }
}

TestRSA.java

package com.roger;

import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;

public class TestRSA {
    public static void main(String[] args) throws Exception {
        KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
        kpg.initialize(1024);
        KeyPair keyPair = kpg.genKeyPair();

        String plainText = "test";
        String sign = CyperUtil.sign(plainText.getBytes("UTF8"), keyPair
                .getPrivate());
        System.out.println("sign:" + sign);
        System.out.println("sign length:" + sign.length());

        Boolean pass = CyperUtil.verify(plainText.getBytes("UTF8"), keyPair
                .getPublic(), sign);
        System.out.println("verify:" + pass);

        System.out.println("========");

        PublicKey publickey = CyperUtil.readPublicKeyFromFile
                ("/D:/temp/rsa_public.key", "RSA");

        PrivateKey privateKey = CyperUtil.readPrivateKeyFromFile
                ("/D:/temp/pkcs8_rsa_private.key", "RSA");

        sign = CyperUtil.sign(plainText.getBytes("UTF8"), privateKey);
        System.out.println("sign:" + sign);
        System.out.println("sign length:" + sign.length());
        pass = CyperUtil.verify(plainText.getBytes
                ("UTF8"), publickey, sign);
        System.out.println("verify:" + pass);
    }
}

POM文件依赖片段

    <dependencies>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.6</version>
        </dependency>
    </dependencies>

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 公私钥准备
  • java的私钥格式要求
  • 代码片段
  • 源码文件
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档