http加解密代码 - yiyixiaozhi/readingNotes GitHub Wiki


title: http加解密代码 date: 2019-10-18 description: http加解密代码 categories:

  • 工具 tags:

# 将传统格式的私钥转换成 PKCS#8 格式的
openssl pkcs8 -topk8 -in id_rsa -out pkcs8_rsa_private_key.pem -nocrypt
# 根据私钥生成公钥
openssl rsa -in pkcs8_rsa_private_key.pem -pubout -out rsa_public_key.pem

Windows证书管理

“此ca根目录证书不受信任”的解决办法

win+r 运行mmc;
文件>添加删除管理单元;
在可用的管理单元中选择”证书“,点击添加-->确定;
在控制节点中展开证书-->受信任的证书颁发机构-->证书,右击所有任务-->导入.

证书导入:

win+r 运行:certmgr.msc

其他参考:

RSA加解密代码示例

    public static void main(String[] args) throws Exception {
        JSONObject json = new JSONObject();
        json.put("首联", "一叶扁舟伴水流");
        //KeyPairGenerator类用于生成公钥和私钥对,基于RSA算法生成对象
        KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
        //初始化密钥对生成器,密钥大小为1024位
        keyPairGen.initialize(1024);
        //生成一个密钥对,保存在keyPair中
        KeyPair keyPair = keyPairGen.generateKeyPair();
        //得到私钥
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
        //得到公钥
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();

        //用公钥加密
        byte[] srcBytes = json.toJSONString().getBytes();
        byte[] resultBytes = encrypt(publicKey, srcBytes);

        //用私钥解密
        byte[] decBytes = decrypt(privateKey, resultBytes);

        System.out.println("明文是:" + json.toJSONString());
        System.out.println("加密后是:" + new String(resultBytes));
        System.out.println("解密后是:" + new String(decBytes));
    }
    /**
     * 加密
     *
     * @param publicKey
     * @param srcBytes
     * @return
     * @throws NoSuchAlgorithmException
     * @throws NoSuchPaddingException
     * @throws InvalidKeyException
     * @throws IllegalBlockSizeException
     * @throws BadPaddingException
     */
    public static byte[] encrypt(RSAPublicKey publicKey, byte[] srcBytes) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
        if (publicKey != null) {
            //Cipher负责完成加密或解密工作,基于RSA
            Cipher cipher = Cipher.getInstance("RSA");
            //根据公钥,对Cipher对象进行初始化
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            byte[] resultBytes = cipher.doFinal(srcBytes);
            return resultBytes;
        }
        return null;
    }
/**
     * 解密
     *
     * @param privateKey
     * @param srcBytes
     * @return
     * @throws NoSuchAlgorithmException
     * @throws NoSuchPaddingException
     * @throws InvalidKeyException
     * @throws IllegalBlockSizeException
     * @throws BadPaddingException
     */
    public static byte[] decrypt(RSAPrivateKey privateKey, byte[] srcBytes) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
        if (privateKey != null) {
            //Cipher负责完成加密或解密工作,基于RSA
            Cipher cipher = Cipher.getInstance("RSA");
            //根据公钥,对Cipher对象进行初始化
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            byte[] resultBytes = cipher.doFinal(srcBytes);
            return resultBytes;
        }
        return null;
    }

RSA工具类

package test;

import java.io.*;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.SecureRandom;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.Cipher;

import com.sun.org.apache.xml.internal.security.exceptions.Base64DecodingException;
import com.sun.org.apache.xml.internal.security.utils.Base64;

/**
 * https://blog.csdn.net/xuejianbest/article/details/85050466
 * 此类是非对称加密算法RSA的工具类,方便对传输数据进行基于密钥的加密和解密。
 * <p>
 * 一般情况下,私钥是服务器端不公开的,公钥公开给每个客户端。
 * 客户端向服务器发送需要加密的消息时,可以用公钥加密后进行传送,服务器端受到密文后可以用私钥进行解密。
 * 服务器端可以对发送的消息进行数字签名,传给客户端,这样客户端受到签名后用公钥进行签名校验,若通过校验说明消息未被修改。
 * <p>
 * 由于RSA算法速度比对称加密算法AES慢很多,所以一般仅仅用来和服务器完成对接认证,和AES密钥传输。
 * 一旦AES密钥传输完成,客户服务器端就可以用AES加密进行通信。
 * 认证过程可以如下:
 * 1、客户端生成伪随机数D,用公钥加密后传给服务器。
 * 2、服务器收到密文用私钥进行解密得到D,然后用私钥对D进行数字签名,将签名发送给客户端。
 * 3、客户端收到签名,用公钥和D进行签名校验,通过校验说明认证通过。
 * 4、通过认证后,客户端可以将自己选择的AES加密算法和密钥用公钥加密后传给服务器。
 * 简单情况下可以只进行第4步,但最好跟一个随机数(加盐),防止其他拥有公钥的人进行穷举法破解。
 *
 * @author liuweitao
 */
public class RSAUtil {
    private RSAPrivateKey key_pri = null;
    private RSAPublicKey key_pub = null;
    private int KEYSIZE = 0;
    private static int D = 11; // java算法要求加密数据长度不能超过密钥长度减去11字节。

    private static final String SIGN_ALGORITHMS = "SHA256WithRSA";

    // 检查公钥私钥,若都为空则抛出异常。
    private void check() throws Exception {
        if ("none".equals(type())) {
            throw new Exception("密钥为空!");
        }
        if (key_pub != null) {
            KEYSIZE = key_pub.getModulus().bitLength();
        } else {
            KEYSIZE = key_pri.getModulus().bitLength();
        }
        KEYSIZE /= Byte.SIZE;
    }

    /**
     * @return pub:公钥填充完成; pri:私钥填充完成; all:公钥私钥都填充完成。
     */
    public String type() {
        String res = null;
        if (key_pub == null && key_pri == null) {
            res = "none";
        } else if (key_pub != null && key_pri == null) {
            res = "pub";
        } else if (key_pub == null && key_pri != null) {
            res = "pri";
        } else if (key_pub != null && key_pri != null) {
            res = "all";
        }
        return res;
    }

    /**
     * @param key_pub 公钥,若不指定则传入null
     * @param key_pri 私钥,若不指定则传入null
     * @throws Exception
     */
    public RSAUtil(RSAPublicKey key_pub, RSAPrivateKey key_pri) throws Exception {
        this.key_pub = key_pub;
        this.key_pri = key_pri;
        check();
    }

    /**
     * @param bytes_pub 公钥字节流,若不指定则传入null
     * @param bytes_pri 私钥字节流,若不指定则传入null
     * @throws Exception
     */
    public RSAUtil(byte[] bytes_pub, byte[] bytes_pri) throws Exception {
        KeyFactory keyFactory = KeyFactory.getInstance("rsa");
        if (bytes_pub != null && bytes_pub.length != 0) {
            X509EncodedKeySpec keySpec_pub = new X509EncodedKeySpec(bytes_pub);
            key_pub = (RSAPublicKey) keyFactory.generatePublic(keySpec_pub);
        }
        if (bytes_pri != null && bytes_pri.length != 0) {
            PKCS8EncodedKeySpec keySpec_pri = new PKCS8EncodedKeySpec(bytes_pri);
            key_pri = (RSAPrivateKey) keyFactory.generatePrivate(keySpec_pri);
        }
        check();
    }

    /**
     * @param str_pub 公钥字符串:Base64表示,若不指定则传入null
     * @param str_pri 私钥字符串:Base64表示,若不指定则传入null
     * @throws Exception
     */
    public RSAUtil(String str_pub, String str_pri) throws Exception {
        KeyFactory keyFactory = KeyFactory.getInstance("rsa");
        if (str_pub != null) {
            byte[] bytes_pub = Base64.decode(str_pub);
            X509EncodedKeySpec keySpec_pub = new X509EncodedKeySpec(bytes_pub);
            key_pub = (RSAPublicKey) keyFactory.generatePublic(keySpec_pub);
        }
        if (str_pri != null) {
            byte[] bytes_pri = Base64.decode(str_pri);
            PKCS8EncodedKeySpec keySpec_pri = new PKCS8EncodedKeySpec(bytes_pri);
            key_pri = (RSAPrivateKey) keyFactory.generatePrivate(keySpec_pri);
        }
        check();
    }

    /**
     * @param file_pub 公钥文件,内容给为Base64表示的字符串,若不指定则传入null
     * @param file_pri 私钥文件,内容给为Base64表示的字符串,若不指定则传入null
     * @throws Exception
     */
    public RSAUtil(File file_pub, File file_pri) throws Exception {
        KeyFactory keyFactory = KeyFactory.getInstance("rsa");
        if (file_pub != null) {
            String str_pub = readStringFile(file_pub);
            byte[] bytes_pub = Base64.decode(str_pub);
            X509EncodedKeySpec keySpec_pub = new X509EncodedKeySpec(bytes_pub);
            key_pub = (RSAPublicKey) keyFactory.generatePublic(keySpec_pub);
        }
        if (file_pri != null) {
            String str_pri = readStringFile(file_pri);
            byte[] bytes_pri = Base64.decode(str_pri);
            PKCS8EncodedKeySpec keySpec_pri = new PKCS8EncodedKeySpec(bytes_pri);
            key_pri = (RSAPrivateKey) keyFactory.generatePrivate(keySpec_pri);
        }
        check();
    }

    /**
     * @param dir_path 密钥文件保存目录路径,字符串
     * @param keysize  密钥文件大小,最小为512,推荐1024和2048
     * @throws Exception
     */
    public static void genKeyFile(String dir_path, int keysize) throws Exception {
        File file = new File(dir_path);
        genKeyFile(file, keysize);
    }

    /**
     * @param dir     密钥文件保存目录路径,文件
     * @param keysize 密钥文件大小,最小为512,推荐1024和2048
     * @throws Exception
     */
    public static void genKeyFile(File dir, int keysize) throws Exception {
        if (!dir.isDirectory()) {
            throw new Exception("接收参数不为目录!");
        }
        String path = dir.getAbsolutePath() + File.separatorChar;

        KeyPairGenerator keyGenerator = KeyPairGenerator.getInstance("rsa");
        keyGenerator.initialize(keysize, new SecureRandom());
        KeyPair keyPair = keyGenerator.generateKeyPair();
        RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
        RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();

        String rsaPrivateKeyString = Base64.encode(rsaPrivateKey.getEncoded());
        String rsaPublicKeyString = Base64.encode(rsaPublicKey.getEncoded());
        PrintWriter out1;
        PrintWriter out2;
        out1 = new PrintWriter(path + "id_rsa.pub");
        out2 = new PrintWriter(path + "id_rsa.pri");
        out1.write(rsaPublicKeyString);
        out2.write(rsaPrivateKeyString);
        out1.close();
        out2.close();
    }

    // 加密内容
    private byte[] encrypt(Cipher cipher, byte[] content) throws Exception {
        final int groupsize = KEYSIZE - D;
        int group_num = content.length % groupsize == 0 ? content.length / groupsize : content.length / groupsize + 1;
        byte[] outBuffer = new byte[KEYSIZE * group_num];

        for (int i = 0; i * groupsize < content.length; i++) {
            if (content.length - i * groupsize > groupsize) {
                cipher.doFinal(content, i * groupsize, groupsize, outBuffer, KEYSIZE * i);
            } else {
                cipher.doFinal(content, i * groupsize, content.length - i * groupsize, outBuffer, KEYSIZE * i);
            }
        }
        return outBuffer;
    }

    // 解密内容
    private byte[] decrypt(Cipher cipher, byte[] secret) throws Exception {
        int count = secret.length / KEYSIZE;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        for (int i = 0; i < count; i++) {
            out.write(cipher.doFinal(secret, KEYSIZE * i, KEYSIZE));
        }
        byte[] res = out.toByteArray();
        out.reset();
        out.close();
        return res;
    }

    /**
     * 公钥加密
     *
     * @param content 要加密的数据
     * @return 加密后的数据
     * @throws Exception
     */
    public byte[] encrypt_pub(byte[] content) throws Exception {
        if (key_pub == null) {
            throw new Exception("公钥为null!");
        }
        Cipher cipher = Cipher.getInstance("rsa");
        cipher.init(Cipher.ENCRYPT_MODE, key_pub);
        return encrypt(cipher, content);
    }

    /**
     * 公钥解密
     *
     * @param secret 要解密的数据
     * @return 解密后的数据
     * @throws Exception
     */
    public byte[] decrypt_pub(byte[] secret) throws Exception {
        if (key_pub == null) {
            throw new Exception("公钥为null!");
        }
        Cipher cipher = Cipher.getInstance("rsa");
        cipher.init(Cipher.DECRYPT_MODE, key_pub);
        return decrypt(cipher, secret);
    }

    /**
     * 私钥加密
     *
     * @param content 要加密的数据
     * @return 加密后的数据
     * @throws Exception
     */
    public byte[] encrypt_pri(byte[] content) throws Exception {
        if (key_pri == null) {
            throw new Exception("私钥为null!");
        }
        Cipher cipher = Cipher.getInstance("rsa");
        cipher.init(Cipher.ENCRYPT_MODE, key_pri);
        return encrypt(cipher, content);
    }

    /**
     * 私钥解密
     *
     * @param secret 要解密的数据
     * @return 解密后的数据
     * @throws Exception
     */
    public byte[] decrypt_pri(byte[] secret) throws Exception {
        if (key_pri == null) {
            throw new Exception("私钥为null!");
        }
        Cipher cipher = Cipher.getInstance("rsa");
        cipher.init(Cipher.DECRYPT_MODE, key_pri);
        return decrypt(cipher, secret);
    }

    /**
     * 生成数字签名,签名算法SHA256WithRSA
     *
     * @param content 数据内容
     * @return 签名
     * @throws Exception
     */
    public byte[] sign(byte[] content) throws Exception {
        if (key_pri == null) {
            throw new Exception("私钥为null!");
        }
        java.security.Signature signature = java.security.Signature.getInstance(SIGN_ALGORITHMS);
        signature.initSign(key_pri);
        signature.update(content);
        return signature.sign();
    }

    /**
     * 校验签名,签名算法SHA256WithRSA
     *
     * @param content 数据内容
     * @param sign    签名
     * @return 是否通过校验
     * @throws Exception
     */
    public boolean check_sign(byte[] content, byte[] sign) throws Exception {
        if (key_pub == null) {
            throw new Exception("公钥为null!");
        }
        java.security.Signature signature = java.security.Signature.getInstance(SIGN_ALGORITHMS);
        signature.initVerify(key_pub);
        signature.update(content);
        return signature.verify(sign);
    }

    /**
     * 对二进制数据进行Base64编码
     *
     * @param binaryData 要编码的原始二进制数据
     * @return com.sun.org.apache.xml.internal.security.utils.Base64.encode(binaryData);
     */
    public static String base64Encode(byte[] binaryData) {
        return Base64.encode(binaryData);
    }

    /**
     * 对Base64编码字符串解码为二进制数,此方法能自动忽略原始字符串中的换行符。
     *
     * @param encoded 表示Base64编码的字符串
     * @return com.sun.org.apache.xml.internal.security.utils.Base64.decode(encoded);
     * @throws Base64DecodingException
     */
    public static byte[] base64Decode(String encoded) throws Base64DecodingException {
        return Base64.decode(encoded);
    }

    /**
     * 从文件中输入流中加载公钥
     *
     * @param in 公钥输入流
     * @throws Exception 加载公钥时产生的异常
     */
    public static String readStringFile(File file) throws Exception {
        try {
            BufferedReader br = new BufferedReader(new FileReader(file));
            String readLine = null;
            StringBuilder sb = new StringBuilder();
            while ((readLine = br.readLine()) != null) {
                sb.append(readLine);
            }
            br.close();
            return sb.toString();
        } catch (IOException e) {
            throw new Exception("秘钥数据流读取错误");
        } catch (NullPointerException e) {
            throw new Exception("秘钥输入流为空");
        }
    }
}

拓展阅读

更多阅读

⚠️ **GitHub.com Fallback** ⚠️