美文网首页
Java代码整理的关于加密算法Utils

Java代码整理的关于加密算法Utils

作者: 蓝Renly | 来源:发表于2018-10-14 23:13 被阅读0次

Encrypt/Decrypt Util整理:

package pers.lansir.util;

/*-----------------Go,My Program----------------*/
/*
 *   @Project:    Cryptography
 *   @Package:    pers.lansir.util
 *   @Author :     LanSir
 *   @Email:       helloworldlgr@gmail.com
 *   @Time :       2018/10/8 16:08
 *   @Description : 加密解密工具类
 */


import com.sun.org.apache.xml.internal.security.utils.Base64;
import org.apache.commons.io.FileUtils;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

public class MyEncryptionUtil {

    /*----------------------------凯撒加密&解密-----------------------------------*/
    /**
     * @params  [input:原文内容, offset:偏移值(也就是秘钥)]
     * @return  java.lang.String 返回加密后的数据
     * @description  :  使用凯撒加密方式加密后的数据
     */
    public static String kaiserEncrypt(String input, int offset){
        char[] chars = input.toCharArray();
        StringBuilder sb = new StringBuilder();
        for (char c : chars) {
            int i = c+offset;
            char ch = (char) i;
            sb.append(ch);
        }
        return sb.toString();
    }


    /**
     * @params  [encryptData:密文, offset:偏移值(也就是秘钥)]
     * @return  java.lang.String 返回解密后的数据
     * @description  :  使用凯撒方式解密后的数据
     */
    public static String kaiserDecrypt(String encryptData, int offset){
        char[] chars = encryptData.toCharArray();
        StringBuilder sb = new StringBuilder();
        for (char c : chars) {
            int i = c - offset;
            char ch  = (char) i;
            sb.append(ch);
        }
        return sb.toString();
    }

    /*----------------------------AES和DES加密&解密----------------------------------*/
    /**
     * @params  [input:原文, key:密钥, transformation:变形算法, algorithm:算法]
     * @return  java.lang.String 返回密文
     * @description  :  AES和DES的加密
     */
    public static String AesAndDesEncrypt(String input, String key, String transformation, String algorithm) throws Exception{
        //获取Cipher
        Cipher cipher = Cipher.getInstance(transformation);
        //参数1:秘钥字符串对应的数组;参数2:指定算法
        SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(),algorithm);
        //参数一:指定模式;参数二:传入秘钥规范;
        cipher.init(Cipher.ENCRYPT_MODE,secretKeySpec);
        //执行加密操作
        byte[] bytes = cipher.doFinal(input.getBytes());
        //注意这里的Base64是Apach.xml下的
        return Base64.encode(bytes);
//        System.out.println(encode);
    }


    /**
     * @params  [transformation, encode:密文, key, algorithm]
     * @return  java.lang.String 返回原文
     * @description  :  AES和DES的解密
     */
    public static String AesAndDesDecrypt(String transformation,String encode,String key,String algorithm) throws Exception{
        //1.获取cipher
        Cipher cipher = Cipher.getInstance(transformation);
        //2.init()
        SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(),algorithm);
        cipher.init(Cipher.DECRYPT_MODE,secretKeySpec);
        //3.doFinal()
        byte[] bytes = cipher.doFinal(Base64.decode(encode));
        return new String(bytes);
    }


    /**
     * @params  [input:原文, key:密钥, transformation:变形算法(完整写法), algorithm:算法]
     * @return  java.lang.String 返回密文
     * @description  :  AES和DES的加密
     * 此方法只适用于CBC模式下,且algorithm写法完整
     */
    public static String AesAndDesEncryptWithAlgorithm(String input, String key, String transformation, String algorithm) throws Exception{
        //获取Cipher
        Cipher cipher = Cipher.getInstance(transformation);
        //参数1:秘钥字符串对应的数组;参数2:指定算法
        SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(),algorithm);
        //参数一:指定模式;参数二:传入秘钥规范;参数3:初始向量,在CBC模式下,用于和第一个块进行异或处理
        IvParameterSpec iv = new IvParameterSpec(key.getBytes());//注意:这里传入的参数:des需要时8位,aes需要时16位
        cipher.init(Cipher.ENCRYPT_MODE,secretKeySpec,iv);
        //执行加密操作
        byte[] bytes = cipher.doFinal(input.getBytes());
        //注意这里的Base64是Apach.xml下的
        return Base64.encode(bytes);
//        System.out.println(encode);
    }

    /**
     * @params  [transformation, encode:密文, key, algorithm]
     * @return  java.lang.String 返回原文
     * @description  :  AES和DES的解密
     * 此方法只适用于CBC模式下,且algorithm写法完整
     */
    public static String AesAndDesDecryptWithAlgorithm(String transformation,String encode,String key,String algorithm) throws Exception{
        //1.获取cipher
        Cipher cipher = Cipher.getInstance(transformation);
        //2.init()
        SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(),algorithm);
        IvParameterSpec iv = new IvParameterSpec(key.getBytes());//注意:这里传入的参数:des需要时8位,aes需要时16位
        cipher.init(Cipher.DECRYPT_MODE,secretKeySpec,iv);
        //3.doFinal()
        byte[] bytes = cipher.doFinal(Base64.decode(encode));
        return new String(bytes);
    }

    /*--------------------信息摘要获取(通过字符串和文件)-------------------------*/
    /**
     * @params  [input:原文, algorithm:hash算法(MD-5,SHA-1,SHA-256,SHA-512)]
     * @return  java.lang.String
     * @description  :  获取字符串信息摘要
     */
    public static String messageDigestOfString(String input, String algorithm) throws Exception {
        //1.获取信息摘要对象
        MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
        byte[] bytes = messageDigest.digest(input.getBytes());
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            int asciiCode = b;
            int a = asciiCode & 0xff;
            String string = Integer.toHexString(a);
            if (string.length()==1){
                string = "0"+string;
            }
            sb.append(string);
        }
        return sb.toString();
    }

    /**
     * @params  [filePath:文件路径, algorithm:hash算法((MD-5,SHA-1,SHA-256,SHA-512))]
     * @return  java.lang.String
     * @description  :  获取文件信息摘要
     */
    public static String messageDigestOfFile(String filePath, String algorithm) throws Exception {
        //1.获取信息摘要对象
        MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
        FileInputStream fis = new FileInputStream(filePath);
        int len ;
        byte[] buffer = new  byte[1024];
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        while ((len = fis.read(buffer))!= -1){
            bos.write(buffer,0,len);
        }
        byte[] bytes = messageDigest.digest(bos.toByteArray());
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            int asciiCode = b;
            int a = asciiCode & 0xff;
            String string = Integer.toHexString(a);
            if (string.length()==1){
                string = "0"+string;
            }
            sb.append(string);
        }
        return sb.toString();
    }


    /*--------------------------------RSA加密&解密--------------------------------------*/

    //RSA加密解密demo查看
    public static void demo() throws Exception{
        String input = "定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。Template Method使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。\n" +
                "\n" +
                "Template Method模式一般是需要继承的。这里想要探讨另一种对Template Method的理解。Spring中的JdbcTemplate,在用这个类时并不想去继承这个类,因为这个类的方法太多,但是我们还是想用到JdbcTemplate已有的稳定的、公用的数据库连接,那么我们怎么办呢?我们可以把变化的东西抽出来作为一个参数传入JdbcTemplate的方法中。但是变化的东西是一段代码,而且这段代码会用到JdbcTemplate中的变量。怎么办?那我们就用回调对象吧。在这个回调对象中定义一个操纵JdbcTemplate中变量的方法,我们去实现这个方法,就把变化的东西集中到这里了。然后我们再传入这个回调对象到JdbcTemplate,从而完成了调用。这可能是Template Method不需要继承的另一种实现方式吧。\n" +
                "\n" +
                "作者:Java填坑之路\n" +
                "链接:https://www.jianshu.com/p/2ae05fe6f318\n" +
                "來源:简书\n" +
                "简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。";
        //Exception in thread "main" javax.crypto.IllegalBlockSizeException: Data must not be longer than 245 bytes
        PrivateKey privateKey = MyEncryptionUtil.getPriKeyFromFile("a.pri");
        PublicKey publicKey = MyEncryptionUtil.getPubKeyFromFile("a.pub");

        String encrypt = rsaEncrypt(input, publicKey, 245);
        System.out.println(encrypt);

        String rsaDecrypt = rsaDecrypt(encrypt, privateKey, 256);
        System.out.println(rsaDecrypt);
    }



    /**
     * @params  [input:原文, key:私钥与秘钥key的父类, inputLen:一次读取的最多的字节的数量]
     * @return  java.lang.String
     * @description  :  RSA的加密操作操作 注意:这里的inputLen通常使用245
     */
    public static String rsaEncrypt(String input, Key key,int inputLen) throws Exception {
        //指定算法
        String transformation = "RSA";
        Cipher cipher = Cipher.getInstance(transformation);
        cipher.init(Cipher.ENCRYPT_MODE, key);
        //获取原文的字符数组
        byte[] data = input.getBytes();
        org.apache.commons.io.output.ByteArrayOutputStream bos = new org.apache.commons.io.output.ByteArrayOutputStream();
        decodeRSAData(cipher, inputLen, data, bos);
        return Base64.encode(bos.toByteArray());
    }

    /**
     * @params  [input : RSA加密后的密文, key : 公钥/秘钥, inputLen : 一次读取的字符最大数量]
     * @return  java.lang.String
     * @description  :  RSA的解密操作  注意:这里的inputLen通常使用256(用其它数字可能会报错)
     */
    public static String rsaDecrypt(String input, Key key,int inputLen) throws Exception {
        String transformation = "RSA";
        Cipher cipher = Cipher.getInstance(transformation);
        cipher.init(Cipher.DECRYPT_MODE, key);
        //获取原文的字符数组
        byte[] data = Base64.decode(input);
        org.apache.commons.io.output.ByteArrayOutputStream bos = new org.apache.commons.io.output.ByteArrayOutputStream();
        decodeRSAData(cipher, inputLen, data, bos);
        return bos.toString();
    }

    /**
     * @params  [cipher, inputLen : 一次读取的最大字节数, data : 原文的字节数组名, bos : 读取到流中的变量名]
     * @return  void
     * @description  :  读取超过245字节的原文
     */
    public static void decodeRSAData(Cipher cipher, int inputLen, byte[] data, org.apache.commons.io.output.ByteArrayOutputStream bos) throws Exception {
        //定义初始偏移量
        int inputOffset = 0;
        //用来接收加密后的字符
        byte[] bytes;
        //获取原文的长度
        int total = data.length;
        while (total - inputOffset > 0) {
            if (total - inputOffset >= inputLen) {
                bytes = cipher.doFinal(data, inputOffset, inputLen);
                inputOffset += inputLen;
            } else {
                //读取最后剩余的可能不完整的数据
                bytes = cipher.doFinal(data, inputOffset, total - inputOffset);
                inputOffset = total;
            }
            //把加密后的数据存储到流中
            bos.write(bytes);
        }
    }

    /**
     * @return java.security.PrivateKey 返回私钥
     * @params [filePath : 私钥的文件路径]
     * @description :  从文件中读取私钥
     */
    public static PrivateKey getPriKeyFromFile(String filePath) throws Exception {
        //读取文件夹中的私钥
        String stringPrivate = FileUtils.readFileToString(new File(filePath), "UTF-8");
        /*String algorithm = "RSA";
        KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(Base64.decode(stringPrivate));
        //获取私钥
        return keyFactory.generatePrivate(x509EncodedKeySpec);*/
        return getPriKeyFromString(stringPrivate);
    }

    /**
     * @return java.security.PrivateKey 返回私钥
     * @params [stringPrivate : 私钥的字符串]
     * @description :  从字符串中获取私钥
     */
    public static PrivateKey getPriKeyFromString(String stringPrivate) throws Exception {
        String algorithm = "RSA";
        KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
        PKCS8EncodedKeySpec pKCS8EncodedKeySpec = new PKCS8EncodedKeySpec(Base64.decode(stringPrivate));
        //获取私钥
        return keyFactory.generatePrivate(pKCS8EncodedKeySpec);
    }

    /**
     * @return java.security.PrivateKey 返回私钥
     * @params [filePath : 私钥的文件路径]
     * @description :  从文件中读取私钥
     */
    public static PublicKey getPubKeyFromFile(String filePath) throws Exception {
        //读取文件夹中的私钥
        String stringPublic = FileUtils.readFileToString(new File(filePath), "UTF-8");
        /*String algorithm = "RSA";
        KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
        PKCS8EncodedKeySpec pKCS8EncodedKeySpec = new pKCS8EncodedKeySpec(Base64.decode(stringPrivate));
        //获取私钥
        return keyFactory.generatePrivate(pKCS8EncodedKeySpec);*/
        return getPubKeyFromString(stringPublic);
    }

    /**
     * @return java.security.PrivateKey 返回私钥
     * @params [stringPrivate : 私钥的字符串]
     * @description :  从字符串中获取私钥
     */
    public static PublicKey getPubKeyFromString(String stringPublic) throws Exception {
        String algorithm = "RSA";
        KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
        X509EncodedKeySpec pKCS8EncodedKeySpec = new X509EncodedKeySpec(Base64.decode(stringPublic));
        //获取私钥
        return keyFactory.generatePublic(pKCS8EncodedKeySpec);
    }

    /**
     * @return void
     * @params [fileName:文件名]
     * @description : 获取公钥/私钥,将公钥/私钥写到文件中
     */
    public static void GenerateRSAKeyPairs(String fileName) throws Exception {
        //指定RSA算法
        String algorithm = "RSA";
        //获取钥匙对生成器
        KeyPairGenerator key = KeyPairGenerator.getInstance(algorithm);
        //获取钥匙对
        KeyPair keyPair = key.generateKeyPair();
        //获取私钥
        PrivateKey privateKey = keyPair.getPrivate();
        //把密钥转换为字节数组
        byte[] privateKeyEncoded = privateKey.getEncoded();
        //通过Base64将数组转换为字符串
        String stringPrivate = Base64.encode(privateKeyEncoded);
        //通过三方库common io将私钥写到文件中
        FileUtils.writeStringToFile(new File(fileName + ".pri"), stringPrivate, "UTF-8");
        //获取公钥
        PublicKey publicKey = keyPair.getPublic();
        byte[] publicKeyEncoded = publicKey.getEncoded();
        String stringPublic = Base64.encode(publicKeyEncoded);
        FileUtils.writeStringToFile(new File(fileName + ".pub"), stringPublic, "UTF-8");
    }

    /*-----------------------------数字签名-----------------------------------------*/

    /**
     * @params  [input : 原文, publicKey : 公钥, encryptSign : 对应的密文]
     * @return  void
     * @description  :  验证签名
     */
    private static void toDecrptySign(String input, PublicKey publicKey, String encryptSign) throws Exception {
        //1.获取signature对象
        Signature signature = Signature.getInstance("SHA256withRSA");
        //2.初始化签名
        signature.initVerify(publicKey);
        //3.传入原文
        signature.update(input.getBytes());
        //4.验证签名
        boolean res = signature.verify(Base64.decode(encryptSign));
    }

    /**
     * @params  [input : 原文, privateKey : 私钥]
     * @return  String 加密签名
     * @description  :  使用SHA256withRSA生成加密签名
     */
    private static String toEncryptSign(String input, PrivateKey privateKey) throws Exception {
        String algorithm = "SHA256withRSA";
        //获取signature对象和
        Signature signature = Signature.getInstance(algorithm);
        //初始化签名
        signature.initSign(privateKey);
        //传入原文
        signature.update(input.getBytes());
        //生成签名
        byte[] sign = signature.sign();
        return Base64.encode(sign);
    }
}

相关文章

网友评论

      本文标题:Java代码整理的关于加密算法Utils

      本文链接:https://www.haomeiwen.com/subject/udcxzftx.html