C语言 c++ php mysql nginx linux lnmp lamp lanmp memcache redis 面试 笔记 ppt 设计模式 问题 远程连接

openssl 加解密相关

 

常用命令 

#查看私钥信息
openssl rsa -in private.key -text -noout

#查看公钥信息
openssl rsa -in public.key -pubin -text -noout

#生成私钥,PKCS1格式
openssl genrsa -out rsa_private_key.pem 1024

#私钥转为PKCS8格式,java 默认只支持该格式私钥
openssl pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt -out rsa_private_key_pcks8.pem

#生成公钥
openssl rsa -in rsa_private_key.pem  -pubout -out rsa_public_key.pem 

#pem(base64)转换为der格式(二进制)
openssl rsa -in rsa_private_key.pem -out rsa_private_key.der -outform DER

 帮助命令

#查看帮助
man openssl

#查看子命令帮助
man gendsa

#其他
asn1parse(1), ca(1), config(5), crl(1), crl2pkcs7(1), dgst(1), dhparam(1), dsa(1), dsaparam(1),
enc(1), gendsa(1), genpkey(1), genrsa(1), nseq(1), openssl(1), sslpasswd(1), pkcs12(1), pkcs7(1),
pkcs8(1), sslrand(1), req(1), rsa(1), rsautl(1), s_client(1), s_server(1), s_time(1), smime(1),
spkac(1), verify(1), version(1), x509(1), crypto(3), ssl(3), x509v3_config(5)

 

pem 密钥格式

pkcs1 头:-----BEGIN RSA PRIVATE KEY-----
pkcs8头:-----BEGIN PRIVATE KEY-----

 

数字证书格式

  • *.DER或*.CER文件: 这样的证书文件是二进制格式,只含有证书信息,不包含私钥。
  • *.CRT文件: 这样的证书文件可以是二进制格式,也可以是文本格式,一般均为文本格式,功能与 *.DER及*.CER证书文件相同。
  • *.PEM文件: 这样的证书文件一般是文本格式,可以存放证书或私钥,或者两者都包含。 *.PEM 文件如果只包含私钥,一般用*.KEY文件代替。
  • *.PFX或*.P12文件: 这样的证书文件是二进制格式,同时包含证书和私钥,且一般有密码保护。

  

  • 如果存在——BEGIN CERTIFICATE——,则说明这是一个证书文件。
  • 如果存在—–BEGIN RSA PRIVATE KEY—–,则说明这是一个私钥文件。

java加解密【rsa】

  读取公钥:X509EncodedKeySpec
  读取私钥:PKCS8EncodedKeySpec ,java 只支持PKCS8格式

  der 格式为二进制存储
  pem 格式为 base64存储和一些格式化

 

 

明文长度:密钥长度(Bytes)-11
    理论上为密钥长度,但是有时候明文小于密钥长度,这时候需要 padding
    只要用到padding,那么就要占用实际的明文长度,于是才有117字节的说法。我们一般使用的padding标准有NoPPadding、OAEPPadding、PKCS1Padding等,其中PKCS#1建议的padding就占用了11个字节。

    如果加密字段过长,需要切分后在分块加密

密文长度:密文位长跟密钥的位长度是相同的

 

 

java 原生代码读取 der 格式

class Signer {
    private KeyFactory keyFactory;

    public Signer() {
        this.keyFactory = KeyFactory.getInstance("RSA");
    }

    public PublicKey getPublicKey() {
        byte[] publicKey = readFileAsBytes("public-key.der");

        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey);

        return keyFactory.generatePublic(keySpec);
    }

    public PrivateKey getPrivateKey() {
        byte[] privateKey = readFileAsBytes("private-key.der");

        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKey);
    
        return keyFactory.generatePrivate(keySpec);
    }

    private URI readFileAsBytes(String name) {
        URI fileUri = getClass().getClassLoader().getResource(name).toURI();

        return Files.readAllBytes(Paths.get(fileUri));
    }
}

 

node 加密 ,java 解密【rsa】

  node 加密

/**
 * 参考
 *  https://tomoya92.github.io/2018/10/12/node-rsa/
 *  https://github.com/rzcoder/node-rsa/wiki/Advanced-options
 *
 */
var NodeRSA = require('node-rsa')
var fs = require('fs')
const constants = require("constants");

function encrypt() {
    fs.readFile('./pem/rsa_public_key.pem', function (err, data) {
        var key = new NodeRSA(data);

        options = {
            encryptionScheme: {
                scheme: 'pkcs1', //默认 pkcs1_oaep
                padding: constants.RSA_PKCS1_PADDING
            }
        }

        key.setOptions(options)

        let cipherText = key.encrypt('hello world', 'base64');
        console.log(cipherText);
    });
}

//generator();
encrypt();

  java 解密

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.Security;
import java.util.Objects;

import javax.crypto.Cipher;

import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openssl.PEMKeyPair;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
import org.junit.Test;

public class RsaTest2 {

    static {
        Security.addProvider(new BouncyCastleProvider());
    }

    /**
     * 公钥
     */
    private static final File PUBLIC_KEY_FILE = new File(
        Objects.requireNonNull(RsaTest2.class.getClassLoader().getResource("rsa_public_key.pem"))
            .getFile());

    /**
     * 私钥 PKCS1
     */
    private static final File PRIVATE_KEY_FILE = new File(
        Objects.requireNonNull(RsaTest2.class.getClassLoader().getResource("rsa_private_key.pem"))
            .getFile());
    /**
     * 私钥 PKCS8 java 支持此格式
     */
    private static final File PRIVATE_PKCS8_KEY_FILE = new File(
        Objects.requireNonNull(RsaTest2.class.getClassLoader().getResource("rsa_private_key_8.pem"))
            .getFile());

    /**
     * 测试解密
     */
    @Test
    public void testUnencrypt() throws Exception {
        PrivateKey rsaPrivateKey1 = this.readPrivateKeySecondApproach(PRIVATE_PKCS8_KEY_FILE);
        PrivateKey rsaPrivateKey2 = this.readPrivateKeySecondApproach(PRIVATE_KEY_FILE);

        String encrypt = "gE0OmGUdTp5z+6HwmMUc5JPGOAY4nU84/OFvk0sWV+Zk392m91isaYoE64A2k"
            + "+REv7zZMDu1w1ucmk1jQzFj4N9CoqBGN9QisMDo7WyDB1NAg5enXd9Rz9gvZ4j"
            + "+z6cuk0SVrpPpUTlPCLIUz8CGAkvVGOCqUNQedwQkl4GwBO0=";
        String unencrypt = this.decrypt(rsaPrivateKey2, encrypt);
        System.out.println(unencrypt);

        unencrypt = this.decrypt(rsaPrivateKey2, encrypt);
        System.out.println(unencrypt);

        System.out.println(rsaPrivateKey2.equals(rsaPrivateKey1));
    }

    public PrivateKey readPrivateKeySecondApproach(File file) throws IOException {
        try (FileReader keyReader = new FileReader(file)) {

            PEMParser pemParser = new PEMParser(keyReader);
            JcaPEMKeyConverter converter = new JcaPEMKeyConverter();

            Object obj = pemParser.readObject();
            if (obj instanceof PrivateKeyInfo) {//
                //pkcs#8 case
                return converter.getPrivateKey((PrivateKeyInfo)obj);
            } else {
                //pkcs#1 case
                KeyPair kp = converter.getKeyPair((PEMKeyPair)obj);
                return kp.getPrivate();
            }
        }
    }

    public static String decrypt(PrivateKey privateKey, String enStr) throws Exception {

        //Cipher.getInstance("RSA"); 等价于 Cipher.getInstance("RSA/ECB/PKCS1Padding");
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        byte[] deBytes = cipher.doFinal(Base64.decodeBase64(enStr));
        return new String(deBytes);
    }
}

 

 

node 加密 ,java 解密【aes】

  node 加密

/**
 * 对标 java 中 AES/CBC/PKCS7Padding
 * PKCS5 是 PKCS7 的特殊情况,固定 8bit 分组
 * 在线测试: http://tools.jb51.net/password/rsa_encode
 *
 * @type {{}}
 */

const CryptoJS = require("crypto-js");

// 加密
// let str = '思齐';

// 密钥 16 位
let key = '491c15367010fbe1';

// 初始向量 initial vector 16 位
let iv = '13bf32d4419b54b8';
// key 和 iv 可以一致

key = CryptoJS.enc.Utf8.parse(key);
iv = CryptoJS.enc.Utf8.parse(iv);
{

    var encrypted = CryptoJS.AES.encrypt(str, key, {
        iv: iv,
        mode: CryptoJS.mode.CBC,
        padding: CryptoJS.pad.Pkcs7
    });


// 转换为字符串 16 进制
//     encrypted = encrypted.toString(CryptoJS.format.Hex);
//     console.log(encrypted)

// 转换为字符串 base64
    encrypted = encrypted.toString(CryptoJS.format.Base64);
    console.log(encrypted)
}

{

// mode 支持 CBC、CFB、CTR、ECB、OFB, 默认 CBC
// padding 支持 Pkcs7、AnsiX923、Iso10126
// NoPadding、ZeroPadding, 默认 Pkcs7, 即 Pkcs5

// 解密
    var decrypted = CryptoJS.AES.decrypt(encrypted, key, {
        iv: iv,
        mode: CryptoJS.mode.CBC,
        padding: CryptoJS.pad.Pkcs7
    });

// 转换为 utf8 字符串
    decrypted = CryptoJS.enc.Utf8.stringify(decrypted);
}

  java 解密

/**
 * AES加解密
 *
 *
 * java 中默认要求支持以下实现 https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#Cipher
 *
 * AES/CBC/NoPadding (128)
 * AES/CBC/PKCS5Padding (128)
 * AES/ECB/NoPadding (128)
 * AES/ECB/PKCS5Padding (128)
 * DES/CBC/NoPadding (56)
 * DES/CBC/PKCS5Padding (56)
 * DES/ECB/NoPadding (56)
 * DES/ECB/PKCS5Padding (56)
 * DESede/CBC/NoPadding (168)
 * DESede/CBC/PKCS5Padding (168)
 * DESede/ECB/NoPadding (168)
 * DESede/ECB/PKCS5Padding (168)
 * RSA/ECB/PKCS1Padding (1024, 2048)
 * RSA/ECB/OAEPWithSHA-1AndMGF1Padding (1024, 2048)
 * RSA/ECB/OAEPWithSHA-256AndMGF1Padding (1024, 2048)
 *
 *
 * @date
 * @author
 */
@Slf4j
public class AesCrypt2 {
    /**
     * 使用固定长度密钥
     */
    private static final int KEY_LENGTH = 16;
    /**
     * 算法/模式/填充方式
     */
    private static final String TRANSFORMATION = "AES/CBC/PKCS7Padding";
    private static final String AES_ALGORITHM = "AES";
    private static final IvParameterSpec IV = new IvParameterSpec("13bf32d4419b54b8".getBytes());

    static {
        //support PKCS7Padding
        if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) {
            Security.addProvider(new BouncyCastleProvider());
        }
    }

    /**
     * aes解密
     * @param data 加密数据
     * @param key 解密密钥
     * @return null 参数不符合要求或解密失败
     */
    public static byte[] decrypt(byte[] data, byte[] key) {
        if (data == null || key == null) {
            return null;
        }

        if (key.length != KEY_LENGTH) {
            throw new RuntimeException("Invalid AES key length (must be 16 bytes)");
        }

        try {
            SecretKeySpec secretKey = new SecretKeySpec(key, AES_ALGORITHM);
            byte[] enCodeFormat = secretKey.getEncoded();
            SecretKeySpec seckey = new SecretKeySpec(enCodeFormat, AES_ALGORITHM);

            Cipher cipher = Cipher.getInstance(TRANSFORMATION);
            cipher.init(Cipher.DECRYPT_MODE, seckey, IV);

            return cipher.doFinal(data);
        } catch (Exception e) {
            log.error(" decrypt fail:{}", e.getMessage(), e);
        }

        return null;
    }

    /**
     * aes加密
     * @param data 需要加密的内容
     * @param key  加密密钥
     * @return 参数不符合要求或加密失败
     */
    public static byte[] encrypt(byte[] data, byte[] key) {
        if (data == null || key == null) {
            return null;
        }

        if (key.length != KEY_LENGTH) {
            throw new RuntimeException("Invalid AES key length (must be 16 bytes)");
        }

        try {
            SecretKeySpec secretKey = new SecretKeySpec(key, AES_ALGORITHM);
            byte[] enCodeFormat = secretKey.getEncoded();
            SecretKeySpec seckey = new SecretKeySpec(enCodeFormat, AES_ALGORITHM);

            Cipher cipher = Cipher.getInstance(TRANSFORMATION);

            cipher.init(Cipher.ENCRYPT_MODE, seckey, IV);
            return cipher.doFinal(data);
        } catch (Exception e) {
            log.error(" encrypt fail:{}", e.getMessage(), e);
        }

        return null;
    }
}
        String raw = "eFsqUJGjPd6FO16dgZ6xlg==";

        byte[] decode = Base64.getDecoder().decode(raw);
        byte[] last = OgnvAesCrypt.decrypt(decode, "491c15367010fbe1".getBytes());
        //System.out.println(Hex.encodeHex(last));
        System.out.println(new String(last));

 

 

java 读写公钥、私钥

/**
 * RSA 加解密
 *
 * BouncyCastle 三方开发的加解密和消息摘要组件, 需要添加 provider
 *
 * https://www.baeldung.com/java-read-pem-file-keys
 * https://github.com/rzcoder/node-rsa
 */
public class RsaTest {

    static {
        Security.addProvider(new BouncyCastleProvider());
    }

    /**
     * 公钥
     */
    private static final File PUBLIC_KEY_FILE = new File(
        Objects.requireNonNull(RsaTest.class.getClassLoader().getResource("rsa_public_key.pem"))
            .getFile());

    /**
     * 私钥 PKCS1
     */
    private static final File PRIVATE_KEY_FILE = new File(
        Objects.requireNonNull(RsaTest.class.getClassLoader().getResource("rsa_private_key.pem"))
            .getFile());
    /**
     * 私钥 PKCS8 java 支持此格式
     */
    private static final File PRIVATE_PKCS8_KEY_FILE = new File(
        Objects.requireNonNull(RsaTest.class.getClassLoader().getResource("rsa_private_key_8.pem"))
            .getFile());

    @Test
    public void testReadKey() throws Exception {

        //PublicKey rsaPublicKey = this.readPublicKey(PUBLIC_KEY_FILE);
        //PublicKey rsaPrivateKey = this.readPrivateKey(PRIVATE_PKCS8_KEY_FILE);

        //BouncyCastle library supports the PKCS1 format,需要加载 provider
        PublicKey rsaPublicKey = this.readPublicKeySecondApproach(PUBLIC_KEY_FILE);

        PrivateKey rsaPrivateKey1 = this.readPrivateKeySecondApproach(PRIVATE_PKCS8_KEY_FILE);
        PrivateKey rsaPrivateKey2 = this.readPrivateKeySecondApproach(PRIVATE_KEY_FILE);

    }

    /**
     * 测试加密
     */
    @Test
    public void testEncrypt() throws Exception {
        //BouncyCastle library supports the PKCS1 format,需要加载 provider
        PublicKey rsaPublicKey = this.readPublicKeySecondApproach(PUBLIC_KEY_FILE);

        // fFAajnaTQOJUDllbS1qkr/w7yx4vgkMyro8xDIpUEYMYbi43PpdMEF9TnO5hMnL1HmgA4PhD1Uws/EpQtDFBE+0ls+iQa1F6
        // +QwakVrUTMttnJF5kS2WQ0+0yLstXclR1JMFmSZnJGL2dlg1tTIJjREmrKljC2c1VJfoZK5kPps=
        String data = "jksong";
        String encrypt = this.encrypt(rsaPublicKey, data);
        System.out.println(encrypt);
    }

    /**
     * 测试解密
     */
    @Test
    public void testUnencrypt() throws Exception {
        PrivateKey rsaPrivateKey1 = this.readPrivateKeySecondApproach(PRIVATE_PKCS8_KEY_FILE);
        PrivateKey rsaPrivateKey2 = this.readPrivateKeySecondApproach(PRIVATE_KEY_FILE);

        String encrypt = "gE0OmGUdTp5z+6HwmMUc5JPGOAY4nU84/OFvk0sWV+Zk392m91isaYoE64A2k"
            + "+REv7zZMDu1w1ucmk1jQzFj4N9CoqBGN9QisMDo7WyDB1NAg5enXd9Rz9gvZ4j"
            + "+z6cuk0SVrpPpUTlPCLIUz8CGAkvVGOCqUNQedwQkl4GwBO0=";
        String unencrypt = this.decrypt(rsaPrivateKey2, encrypt);
        System.out.println(unencrypt);

        //unencrypt = this.decrypt(rsaPrivateKey2, encrypt);
        //System.out.println(unencrypt);
        //
        //System.out.println(rsaPrivateKey2.equals(rsaPrivateKey1));
    }

    //public static void main(String[] args) throws IOException {
    //    RsaTest rsaTest = new RsaTest();
    //    PrivateKey rsaPrivateKey = rsaTest.readPrivateKeySecondApproach(PRIVATE_PKCS8_KEY_FILE);
    //    rsaTest.readPrivateKeySecondApproach(PRIVATE_KEY_FILE);
    //
    //}

    public PublicKey readPublicKey(File file) throws Exception {
        String key = new String(Files.readAllBytes(file.toPath()), Charset.defaultCharset());

        String publicKeyPEM = key
            .replace("-----BEGIN PUBLIC KEY-----", "")
            .replaceAll(System.lineSeparator(), "")
            .replace("-----END PUBLIC KEY-----", "");

        byte[] encoded = Base64.decodeBase64(publicKeyPEM);

        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(encoded);
        return keyFactory.generatePublic(keySpec);
    }

    public RSAPrivateKey readPrivateKey(File file) throws Exception {
        String key = new String(Files.readAllBytes(file.toPath()), Charset.defaultCharset());

        String privateKeyPEM = key
            .replace("-----BEGIN PRIVATE KEY-----", "")
            .replaceAll(System.lineSeparator(), "")
            .replace("-----END PRIVATE KEY-----", "");

        byte[] encoded = Base64.decodeBase64(privateKeyPEM);

        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encoded);
        return (RSAPrivateKey)keyFactory.generatePrivate(keySpec);
    }

    /**
     * 使用 BouncyCastle,可以支持读取 pem 文件
     * @param file
     * @return
     * @throws IOException
     */
    public RSAPublicKey readPublicKeySecondApproach(File file) throws IOException {
        try (FileReader keyReader = new FileReader(file)) {
            PEMParser pemParser = new PEMParser(keyReader);
            JcaPEMKeyConverter converter = new JcaPEMKeyConverter();
            SubjectPublicKeyInfo publicKeyInfo = SubjectPublicKeyInfo.getInstance(pemParser.readObject());
            return (RSAPublicKey)converter.getPublicKey(publicKeyInfo);
        }
    }

    public PrivateKey readPrivateKeySecondApproach(File file) throws IOException {
        try (FileReader keyReader = new FileReader(file)) {

            PEMParser pemParser = new PEMParser(keyReader);
            JcaPEMKeyConverter converter = new JcaPEMKeyConverter();

            Object obj = pemParser.readObject();
            if (obj instanceof PrivateKeyInfo) {//
                //pkcs#8 case
                return converter.getPrivateKey((PrivateKeyInfo)obj);
            } else {
                //pkcs#1 case
                KeyPair kp = converter.getKeyPair((PEMKeyPair)obj);
                return kp.getPrivate();
            }
        }
    }

    public String encrypt(PublicKey publicKey, String plainText) throws Exception {

        //等价于 RSA/ECB/PKCS1Padding (1024, 2048) => RSA/None/PKCS1Padding
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        byte[] enBytes = cipher.doFinal(plainText.getBytes());
        return Base64.encodeBase64String(enBytes);
    }

    public static String decrypt(PrivateKey privateKey, String enStr) throws Exception {
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        byte[] deBytes = cipher.doFinal(Base64.decodeBase64(enStr));
        return new String(deBytes);
    }
}

 

数字签名【防篡改】

/**
 * RSA 加解密
 *
 * BouncyCastle 三方开发的加解密和消息摘要组件, 需要添加 provider
 *
 * https://www.baeldung.com/java-read-pem-file-keys
 * https://github.com/rzcoder/node-rsa
 */
public class RsaTest {

    static {
        Security.addProvider(new BouncyCastleProvider());
    }

    /**
     * 公钥
     */
    private static final File PUBLIC_KEY_FILE = new File(
        Objects.requireNonNull(RsaTest.class.getClassLoader().getResource("rsa_public_key.pem"))
            .getFile());

    /**
     * 私钥 PKCS1
     */
    private static final File PRIVATE_KEY_FILE = new File(
        Objects.requireNonNull(RsaTest.class.getClassLoader().getResource("rsa_private_key.pem"))
            .getFile());
    /**
     * 私钥 PKCS8 java 支持此格式
     */
    private static final File PRIVATE_PKCS8_KEY_FILE = new File(
        Objects.requireNonNull(RsaTest.class.getClassLoader().getResource("rsa_private_key_8.pem"))
            .getFile());

    @Test
    public void testReadKey() throws Exception {

        //PublicKey rsaPublicKey = this.readPublicKey(PUBLIC_KEY_FILE);
        //PublicKey rsaPrivateKey = this.readPrivateKey(PRIVATE_PKCS8_KEY_FILE);

        //BouncyCastle library supports the PKCS1 format,需要加载 provider
        PublicKey rsaPublicKey = this.readPublicKeySecondApproach(PUBLIC_KEY_FILE);

        PrivateKey rsaPrivateKey1 = this.readPrivateKeySecondApproach(PRIVATE_PKCS8_KEY_FILE);
        PrivateKey rsaPrivateKey2 = this.readPrivateKeySecondApproach(PRIVATE_KEY_FILE);

    }

    /**
     * 测试加密
     */
    @Test
    public void testEncrypt() throws Exception {
        //BouncyCastle library supports the PKCS1 format,需要加载 provider
        PublicKey rsaPublicKey = this.readPublicKeySecondApproach(PUBLIC_KEY_FILE);

        // fFAajnaTQOJUDllbS1qkr/w7yx4vgkMyro8xDIpUEYMYbi43PpdMEF9TnO5hMnL1HmgA4PhD1Uws/EpQtDFBE+0ls+iQa1F6
        // +QwakVrUTMttnJF5kS2WQ0+0yLstXclR1JMFmSZnJGL2dlg1tTIJjREmrKljC2c1VJfoZK5kPps=
        String data = "jksong";
        String encrypt = this.encrypt(rsaPublicKey, data);
        System.out.println(encrypt);
    }

    /**
     * 测试解密
     */
    @Test
    public void testUnencrypt() throws Exception {
        PrivateKey rsaPrivateKey1 = this.readPrivateKeySecondApproach(PRIVATE_PKCS8_KEY_FILE);
        PrivateKey rsaPrivateKey2 = this.readPrivateKeySecondApproach(PRIVATE_KEY_FILE);

        String encrypt = "gE0OmGUdTp5z+6HwmMUc5JPGOAY4nU84/OFvk0sWV+Zk392m91isaYoE64A2k"
            + "+REv7zZMDu1w1ucmk1jQzFj4N9CoqBGN9QisMDo7WyDB1NAg5enXd9Rz9gvZ4j"
            + "+z6cuk0SVrpPpUTlPCLIUz8CGAkvVGOCqUNQedwQkl4GwBO0=";
        String unencrypt = this.decrypt(rsaPrivateKey2, encrypt);
        System.out.println(unencrypt);

        //unencrypt = this.decrypt(rsaPrivateKey2, encrypt);
        //System.out.println(unencrypt);
        //
        //System.out.println(rsaPrivateKey2.equals(rsaPrivateKey1));
    }

    /**
     * 数字签名
     * @throws Exception
     */
    @Test
    public void testSign() throws Exception {

        /**
         * 签名算法
         * MD2withRSA
         * MD5withRSA
         * RSASSA-PSS
         * SHA1withRSA
         * SHA224withRSA
         * SHA256withRSA
         * SHA384withRSA
         * SHA512withRSA
         * SHA512/224withRSA
         * SHA512/256withRSA
         * 等
         *
         * https://docs.oracle.com/javase/8/docs/technotes/guides/security/SunProviders.html#Introduction
         *
         */
        String signType = "SHA1withRSA";

        //待签名数据
        byte[] data = "思齐".getBytes(StandardCharsets.UTF_8);

        //生成签名
        PrivateKey rsaPrivateKey1 = this.readPrivateKeySecondApproach(PRIVATE_PKCS8_KEY_FILE);
        String sign = this.sign("SHA1withRSA", data, rsaPrivateKey1);
        System.out.println("签名:" + sign);

        //验证签名
        PublicKey rsaPublicKey = this.readPublicKeySecondApproach(PUBLIC_KEY_FILE);

        boolean verifySign = this.verifySign("SHA1withRSA", data, rsaPublicKey, sign);
        System.out.println("签名验证结果:" + verifySign);
    }

    public PublicKey readPublicKey(File file) throws Exception {
        String key = new String(Files.readAllBytes(file.toPath()), Charset.defaultCharset());

        String publicKeyPEM = key
            .replace("-----BEGIN PUBLIC KEY-----", "")
            .replaceAll(System.lineSeparator(), "")
            .replace("-----END PUBLIC KEY-----", "");

        byte[] encoded = Base64.decodeBase64(publicKeyPEM);

        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(encoded);
        return keyFactory.generatePublic(keySpec);
    }

    public RSAPrivateKey readPrivateKey(File file) throws Exception {
        String key = new String(Files.readAllBytes(file.toPath()), Charset.defaultCharset());

        String privateKeyPEM = key
            .replace("-----BEGIN PRIVATE KEY-----", "")
            .replaceAll(System.lineSeparator(), "")
            .replace("-----END PRIVATE KEY-----", "");

        byte[] encoded = Base64.decodeBase64(privateKeyPEM);

        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encoded);
        return (RSAPrivateKey)keyFactory.generatePrivate(keySpec);
    }

    /**
     * 使用 BouncyCastle,可以支持读取 pem 文件
     * @param file
     * @return
     * @throws IOException
     */
    public RSAPublicKey readPublicKeySecondApproach(File file) throws IOException {
        try (FileReader keyReader = new FileReader(file)) {
            PEMParser pemParser = new PEMParser(keyReader);
            JcaPEMKeyConverter converter = new JcaPEMKeyConverter();
            SubjectPublicKeyInfo publicKeyInfo = SubjectPublicKeyInfo.getInstance(pemParser.readObject());
            return (RSAPublicKey)converter.getPublicKey(publicKeyInfo);
        }
    }

    public PrivateKey readPrivateKeySecondApproach(File file) throws IOException {
        try (FileReader keyReader = new FileReader(file)) {

            PEMParser pemParser = new PEMParser(keyReader);
            JcaPEMKeyConverter converter = new JcaPEMKeyConverter();

            Object obj = pemParser.readObject();
            if (obj instanceof PrivateKeyInfo) {//
                //pkcs#8 case
                return converter.getPrivateKey((PrivateKeyInfo)obj);
            } else {
                //pkcs#1 case
                KeyPair kp = converter.getKeyPair((PEMKeyPair)obj);
                return kp.getPrivate();
            }
        }
    }

    public String encrypt(PublicKey publicKey, String plainText) throws Exception {

        //等价于 RSA/ECB/PKCS1Padding (1024, 2048) => RSA/None/PKCS1Padding
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        byte[] enBytes = cipher.doFinal(plainText.getBytes());
        return Base64.encodeBase64String(enBytes);
    }

    public static String decrypt(PrivateKey privateKey, String enStr) throws Exception {
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        byte[] deBytes = cipher.doFinal(Base64.decodeBase64(enStr));
        return new String(deBytes);
    }

    public String sign(String signType, byte[] data, PrivateKey privateKey) throws Exception {
        Signature signature = Signature.getInstance(signType);
        signature.initSign(privateKey);
        signature.update(data);

        return Base64.encodeBase64String(signature.sign());
    }

    public boolean verifySign(String signType, byte[] data, PublicKey publicKey, String sign) throws Exception {
        Signature signature = Signature.getInstance(signType);
        signature.initVerify(publicKey);
        signature.update(data);
        return signature.verify(Base64.decodeBase64(sign));
    }

}

 

 读取证书

/**
     * 读取证书信息
     * @throws CertificateException
     */
    @Test
    public void test497() throws CertificateException {
        InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream("pub_server.crt");

        CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
        X509Certificate x509Cert = (X509Certificate)certificateFactory.generateCertificate(resourceAsStream);

        PublicKey publicKey = x509Cert.getPublicKey();
        BASE64Encoder encoder = new BASE64Encoder();
        String encoded = encoder.encode(publicKey.getEncoded());
        System.out.println("公钥:" + encoded);

        System.out.println("输出证书信息:" + x509Cert.toString());
        System.out.println("版本号:" + x509Cert.getVersion());
        System.out.println("序列号:" + x509Cert.getSerialNumber().toString(16));
        System.out.println("主体名:" + x509Cert.getSubjectDN());
        System.out.println("签发者:" + x509Cert.getIssuerDN());
        System.out.println("有效期:" + x509Cert.getNotBefore());
        System.out.println("签名算法:" + x509Cert.getSigAlgName());
        byte[] sig = x509Cert.getSignature();
        System.out.println("签名值:" + Arrays.toString(sig));
    }

 

 

测试密钥

 

rsa_private_key.pem

-----BEGIN PRIVATE KEY-----
MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMpWEnTXc7jl7fJg
hMJp5lv3c/Lwv5q7qamRcQIBx6qDNcrMvKfQRqcGS8WqsmWx3qZCWzi40Brexlo/
V0RN0ktfDXrKl9qO5++yqPk/0mVhN/raF32SSrCP6WNEvSwc5ln3LUV/NPZ6rRTI
wFLeilruVjvtT1yw/f6cbf5ac+n5AgMBAAECgYAkZy305ZqFZqDT3bek/saaP0AW
MmhWn3Lb9jXdxZI1xFuWPBWpH5jGjiRt0NM95q2HPiMJZn7ShsgrDoBV4qZ15LdT
8iHGvDVhmcqv1GPkKoyI1HoCvcff0bhblMb70m14ZnOHgf4MlNeOVvrkd8LdaoST
7y61akphJdTIKLZVAQJBAPv4rNjA0yjZvwLeR/mZdQyYexI/yJCEJhPj591BeeMI
ZzPlEcyZS+vMYtMpGaxHqtUJG8zoCcXluj/lZmPlsCECQQDNkj0vLk/ZpRE+paOj
SKrjQJF/OJ9SWu0FGpQ9PfqrFgLUvVYTzFpFfW0k345r4CK6I9eX/4ey7oGgbUfh
Zd7ZAkEAnRVt5H9p5SjCnS4oXuIdh6mz6C+dgQLxnirSDSzZqQE/HaosS4oyO6Gi
5pPT7oSLat6P11G9bgOG9ni0OYkjIQJAHCFOzg4AT0APRAtWgRmIiOBlCIuvAY3/
sRsZ/edlTdQNPx9JkBv+nlOzg8AztP9OwTn2Xo5Q+2M3ycQqeeV+wQJBAJRyBEh1
2RuDjCMjz7K8KCWJcZ1wZT+7Xb51ICyQPwnIiz1fSRpwmzO8dS7gZQ9qaqa1uAEl
O+aDMRvr202Wm2s=
-----END PRIVATE KEY-----

 

rsa_private_key_8.pem

-----BEGIN PRIVATE KEY-----
MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMpWEnTXc7jl7fJg
hMJp5lv3c/Lwv5q7qamRcQIBx6qDNcrMvKfQRqcGS8WqsmWx3qZCWzi40Brexlo/
V0RN0ktfDXrKl9qO5++yqPk/0mVhN/raF32SSrCP6WNEvSwc5ln3LUV/NPZ6rRTI
wFLeilruVjvtT1yw/f6cbf5ac+n5AgMBAAECgYAkZy305ZqFZqDT3bek/saaP0AW
MmhWn3Lb9jXdxZI1xFuWPBWpH5jGjiRt0NM95q2HPiMJZn7ShsgrDoBV4qZ15LdT
8iHGvDVhmcqv1GPkKoyI1HoCvcff0bhblMb70m14ZnOHgf4MlNeOVvrkd8LdaoST
7y61akphJdTIKLZVAQJBAPv4rNjA0yjZvwLeR/mZdQyYexI/yJCEJhPj591BeeMI
ZzPlEcyZS+vMYtMpGaxHqtUJG8zoCcXluj/lZmPlsCECQQDNkj0vLk/ZpRE+paOj
SKrjQJF/OJ9SWu0FGpQ9PfqrFgLUvVYTzFpFfW0k345r4CK6I9eX/4ey7oGgbUfh
Zd7ZAkEAnRVt5H9p5SjCnS4oXuIdh6mz6C+dgQLxnirSDSzZqQE/HaosS4oyO6Gi
5pPT7oSLat6P11G9bgOG9ni0OYkjIQJAHCFOzg4AT0APRAtWgRmIiOBlCIuvAY3/
sRsZ/edlTdQNPx9JkBv+nlOzg8AztP9OwTn2Xo5Q+2M3ycQqeeV+wQJBAJRyBEh1
2RuDjCMjz7K8KCWJcZ1wZT+7Xb51ICyQPwnIiz1fSRpwmzO8dS7gZQ9qaqa1uAEl
O+aDMRvr202Wm2s=
-----END PRIVATE KEY-----

 

rsa_public_key.pem

-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDKVhJ013O45e3yYITCaeZb93Py
8L+au6mpkXECAceqgzXKzLyn0EanBkvFqrJlsd6mQls4uNAa3sZaP1dETdJLXw16
ypfajufvsqj5P9JlYTf62hd9kkqwj+ljRL0sHOZZ9y1FfzT2eq0UyMBS3opa7lY7
7U9csP3+nG3+WnPp+QIDAQAB
-----END PUBLIC KEY-----

 

 

 参考

  Java Cryptography Architecture Standard Algorithm Name

  Java Cryptography Architecture Oracle Providers Documentation for JDK 8

  数字签名是什么

  rsa 在线加解密工具

  数字证书格式

 

posted on 2021-08-20 15:32  思齐_  阅读(716)  评论(0编辑  收藏  举报