WilliamUUUU / LearningNote

0 stars 0 forks source link

RSA工具类 #5

Open WilliamUUUU opened 1 year ago

WilliamUUUU commented 1 year ago

init

WilliamUUUU commented 1 year ago
public class RSAUtil
{
    private static final String BASE_SEED = "grt112461016***@@@";
    private static final String CIPHER_TRANSFORMS = "RSA/ECB/PKCS1Padding";
    private static final int KEY_PAIR_LENGTH = 1024;
    private final static int ENCRYPTKEY = 0xFF;

    public static KeyPair generateRsaKeyPair(String secureRandomSeed) {
        //KeyPair 是密钥对(公钥和私钥)的简单持有者。加密、解密都需要使用.
        KeyPair keyPair = null;
        try {
            //获取生成 RSA 加密算法的公钥/私钥对 KeyPairGenerator 对象
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
            //获取实现指定算法(SHA1PRNG)的随机数生成器(RNG)对象.
            SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
            //重新设定此随机对象的种子.
            secureRandom.setSeed(secureRandomSeed.getBytes());
            /**
             * initialize(int keySize, SecureRandom random):使用给定的随机源(random)初始化特定密钥大小的密钥对生成器。
             * keySize: 健的大小值,这是一个特定于算法的度量。值越大,能加密的内容就越多,否则会抛异常:javax.crypto.IllegalBlockSizeException: Data must not be longer than xxx bytes
             * 如 keySize 为 2048 时加密数据的长度不能超过 245 字节。
             */
            keyPairGenerator.initialize(KEY_PAIR_LENGTH, secureRandom);
            //genKeyPair(): 生成密钥对
            keyPair = keyPairGenerator.genKeyPair();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return keyPair;
    }

    /**
     * 使用私钥(PrivateKey)对数据进行加密 或 解密
     *
     * @param content          :待加/解密的数据。如果待解密的数据,则是 Base64 编码后的可视字符串.
     * @param model            :1 表示加密模式(Cipher.ENCRYPT_MODE),2 表示解密模式(Cipher.DECRYPT_MODE)
     * @param secureRandomSeed :SecureRandom 随机数生成器的种子,只要种子相同,则生成的公钥、私钥就是同一对.
     *                         加解密必须是同一个.
     * @return :返回加/解密后的数据,如果是加密,则将字节数组使用 Base64 转为可视字符串.
     */
    public static String cipherByPrivateKey(String content, int model, String secureRandomSeed) {
        String result = "";
        try {
            //获取 RSA 密钥对
            KeyPair keyPair = generateRsaKeyPair(secureRandomSeed);
            /**getPrivate():获取密钥对的私钥。
             * getEncoded(): 返回已编码的密钥,如果密钥不支持编码,则返回 null*/
            byte[] privateEncoded = keyPair.getPrivate().getEncoded();
            /**PKCS8EncodedKeySpec(byte[] encodedKey): 使用给定的编码密钥创建新的 PKCS8EncodedKeySpec
             * PKCS8EncodedKeySpec 表示 ASN.1 号私钥的编码*/
            EncodedKeySpec encodedKeySpec = new PKCS8EncodedKeySpec(privateEncoded);
            //创建 KeyFactory 对象,用于转换指定算法(RSA)的公钥/私钥。
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            //从提供的密钥规范生成私钥对象
            PrivateKey keyPrivate = keyFactory.generatePrivate(encodedKeySpec);
            //实例化 Cipher 对象。
            result = encryptionDecryption(content, model, keyPrivate);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 使用公钥(PublicKey)对数据进行加密 或 解解
     *
     * @param content          :待加解密的数据
     * @param model            :1 表示加密模式(Cipher.ENCRYPT_MODE),2 表示解密模式(Cipher.DECRYPT_MODE)
     * @param secureRandomSeed :SecureRandom 随机数生成器的种子,只要种子相同,则生成的公钥、私钥就是同一对.
     *                         加解密必须是同一个.
     * @return :返回加密 或者 解密后的数据
     */
    public static String cipherByPublicKey(String content, int model, String secureRandomSeed)
    {
        String result = "";
        try
        {
            // 得到公钥
            KeyPair keyPair = generateRsaKeyPair(secureRandomSeed);
            EncodedKeySpec keySpec = new X509EncodedKeySpec(keyPair.getPublic().getEncoded());
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            PublicKey keyPublic = keyFactory.generatePublic(keySpec);
            // 数据加/解密
            result = encryptionDecryption(content, model, keyPublic);
        } catch (Exception e)
        {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 加密或解密
     *
     * @param content :待加解密的数据
     * @param model   :1 表示加密模式(Cipher.ENCRYPT_MODE),2 表示解密模式(Cipher.DECRYPT_MODE)
     * @param key     :公钥(PUBLIC_KEY)或 私钥(PRIVATE_KEY)的 key
     * @return
     */
    private static String encryptionDecryption(String content, int model, Key key) {
        String result = "";
        try {
            Cipher cipher = Cipher.getInstance(CIPHER_TRANSFORMS);
            //init(int opMode, Key key):初始化 Cipher.
            cipher.init(model, key);
            //如果是解密模式,则需要使用 Base64 进行解码.
            byte[] contentBytes = content.getBytes();
            if (model == Cipher.DECRYPT_MODE) {
                contentBytes = Base64.getDecoder().decode(content);
//                contentBytes = new BASE64Decoder().decodeBuffer(content);
            }
            /**执行加密 或 解密操作。如果 contentBytes 内容过长,则 doFinal 可能会抛出异常.
             *javax.crypto.IllegalBlockSizeException: Data must not be longer than 245 bytes :数据不能超过xxx字节
             * 此时需要调大 KEY_PAIR_LENGTH 的值*/
            byte[] finalBytes = cipher.doFinal(contentBytes);
            //如果是加密,则将加密后的字节数组使用 Base64 转成可视化的字符串。否则是解密时,直接 new String 字符串.
            if (model == Cipher.ENCRYPT_MODE) {
//                result = new BASE64Encoder().encode(finalBytes);
                result = Base64.getEncoder().encodeToString(finalBytes);
            } else if (model == Cipher.DECRYPT_MODE) {
                result = new String(finalBytes);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 编码返回字符串
     * @param key
     * @return
     * @throws Exception
     */
    public static String encryptBASE64(byte[] key) throws Exception {
        return Base64.getEncoder().encodeToString(key);
//        return (new BASE64Encoder()).encodeBuffer(key);
    }

    /**
     * 获取公钥串
     * @return
     * @throws Exception
     */
    public static String getPubliKey() throws Exception
    {
        KeyPair keyPair = generateRsaKeyPair(genSeed());
        return encryptBASE64(keyPair.getPublic().getEncoded()).replace("\r\n", "");
    }

    /**
     * 产生种子
     * @return
     */
    public static String genSeed()
    {
        String today = DateUtil.today();
        return today + BASE_SEED;
    }

    public static void main(String[] args)
    {
        String pwd123456 = cipherByPublicKey("pwd123456", 1, genSeed());
//        String pwd123456 = cipherByPublicKey("ADD_DEVICE", 1, genSeed());
        System.out.println("pwd123456 = " + pwd123456);
    }
}