java 根据 KeyPairGenerator对象生成RSA密钥对,并进行测试

4 篇文章 0 订阅

java 根据 KeyPairGenerator对象生成RSA密钥对,并进行测试

说明:rsa 算法根据密钥长度, 每轮 加/解密 填充 允许的最大长度,也不相同,这个地方暂时还不知道是怎么计算出来的
限制:由于上面的原因,这里暂时只支持 密钥长度为 1024 / 2048 位长度
实现:根据 KeyPairGenerator 对象传入密钥长度,随机种子,生成rsa 密钥

编码实现

	package com.example.demo.util.encrypt;

import org.apache.commons.codec.binary.Base64;
import sun.security.rsa.RSACore;
import sun.security.rsa.RSAKeyFactory;

import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.security.*;
import java.security.interfaces.RSAKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

/**
 *  生成 rsa 密钥,通过 KeyPairGenerator 对象
 *
 *  尝试根据 密钥长度获取  每轮 加/解密 填充 允许的最大长度, 但是失败,先不尝试了
 */
public class RsaGenerate {


    /**
     * 解密 每轮的基准, 128 ,以 密钥 1024 位来算(与 私钥/公钥 解密无关)
     */
    private static int decodePaddingBase = 128;

    /**
     * 加密 每轮的基准, 117 ,以 密钥1024 来算(与 私钥/公钥 加密无关)
     */
    private static int encodePaddingBase = 117;


    /**
     * 密钥位数以 1024 位为基准
     */
    private static int baseSize = 1024;





    /**
     * KeyFactory 不行
     * KeyGenerator 不支持rsa
     * @param args
     * @throws NoSuchAlgorithmException
     */
    public static void main(String[] args) throws Exception {
        //  传入随机种子,生成 对称算法密钥对
        int keySize = 1024;
        String seedStr = "测试seed ajibahuihu";
        String testStr = "这是一条测试数据,请注意 https://blog.csdn.net/kzcming";

        process(keySize, seedStr, testStr);
    }


    /**
     * 根据密钥的长度, 每轮 加/解密 填充 允许的最大长度,也不相同
     * @param key
     * @throws InvalidKeyException
     */
    private static void makeSize(Key key) throws InvalidKeyException {
        RSAKey var6 = RSAKeyFactory.toRSAKey(key);
        int byteLength = RSACore.getByteLength(var6.getModulus());
        if(key instanceof PrivateKey) encodePaddingBase = byteLength;
        if(key instanceof PublicKey) decodePaddingBase = byteLength;

//        if(key instanceof PrivateKey)
//            init("1", key, JceSecurity.RANDOM,null);
    }






    private static void process(int keySize, String seedStr, String testStr) throws Exception {
        KeyPair keyPair = getKeyPair(seedStr,keySize);
        // 获得私钥,公钥
        PrivateKey aPrivate = keyPair.getPrivate();
        PublicKey aPublic = keyPair.getPublic();
        byte[] privateEncoded = aPrivate.getEncoded();
        byte[] publicEncoded = aPublic.getEncoded();
        // Base64 编码
        String privateKeyStr = Base64.encodeBase64String(privateEncoded);
        String publicKeyStr = Base64.encodeBase64String(publicEncoded);
        System.out.println("private:" + privateKeyStr);
        System.out.println();
        System.out.println("public:" + publicKeyStr);


        // 执行测试
//        int divide = keySize/baseSize;
//        if( divide != 1 ) {
        if(keySize == 2048) {
//            makeSize(aPrivate);
//            makeSize(aPublic);
            encodePaddingBase = encodePaddingBase * 2;
            decodePaddingBase = decodePaddingBase * 2;
        }

        // 公钥加密,私钥解密, 当然也可以反着,但是大家一般都这么弄
        byte[] bytes = encryptByPublicKey(testStr.getBytes(), publicKeyStr);
        byte[] bytes1 = decryptByPrivateKey(bytes, privateKeyStr);
        System.out.println(new String(bytes1));
    }

    /**
     * 获取对称加密密钥
     *
     * KeyPairGenerator 是生成对称加密密钥的 封装对象
     * @param seedStr   随机种子字符串
     * @param keySize   密钥长度, 必须是128 的倍数
     * @return
     * @throws NoSuchAlgorithmException
     */
    private static KeyPair getKeyPair(String seedStr,int keySize) throws NoSuchAlgorithmException {
        KeyPairGenerator gen = KeyPairGenerator.getInstance("RSA");
        gen.initialize(keySize,new SecureRandom(seedStr.getBytes()));
        return gen.generateKeyPair();
    }


    /**
     * 私钥解密
     * @param data
     * @param privateKey
     * @return
     * @throws Exception
     */
    public static byte[] decryptByPrivateKey(byte[] data, String privateKey) throws Exception {
        byte[] keyBytes = Base64.decodeBase64(privateKey);
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(2, privateK);
        int inputLen = data.length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offSet = 0;

        int i = 0;
        while (inputLen - offSet > 0) {
            byte[] cache;

            if (inputLen - offSet > decodePaddingBase) {
                cache = cipher.doFinal(data, offSet, decodePaddingBase);
            } else {
                cache = cipher.doFinal(data, offSet, inputLen - offSet);
            }
            out.write(cache, 0, cache.length);
            i++;
            offSet = i * decodePaddingBase;
        }
        byte[] decryptedData = out.toByteArray();
        out.close();
        return decryptedData;
    }


    /**
     * 公钥加密
     * @param data
     * @param publicKey
     * @return
     * @throws Exception
     */
    public static byte[] encryptByPublicKey(byte[] data, String publicKey) throws Exception {
        byte[] keyBytes = Base64.decodeBase64(publicKey);
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        Key publicK = keyFactory.generatePublic(x509KeySpec);

        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(1, publicK);
        int inputLen = data.length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offSet = 0;

        int i = 0;
        while (inputLen - offSet > 0) {
            byte[] cache;
            if (inputLen - offSet > encodePaddingBase) {
                cache = cipher.doFinal(data, offSet, encodePaddingBase);
            } else {
                cache = cipher.doFinal(data, offSet, inputLen - offSet);
            }
            out.write(cache, 0, cache.length);
            i++;
            offSet = i * encodePaddingBase;
        }
        byte[] encryptedData = out.toByteArray();
        out.close();
        return encryptedData;
    }


}

  • 3
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值