常见加密算法实现——DES、AES、RSA、MD5

一、对称加密

1、介绍

对称加密:加密和解密使用同一个密钥。
对称加密算法:DES、3DES、AES等。
     DES:数据加密标准,是一种使用密钥加密的块算法;
     3DES:DES向AES过渡的加密算法;
     AES:高级加密标准,替代DES;

对称加密的特点:

  • 加密速度快,可加密大文件;
  • 密文可逆,数据容易暴露;
  • 加密后编码找不到对应字符,出现乱码;
  • 一般结合base64使用

2、加密模式

有两种加密模式:ECB、CBC
ECB:电子密码本. 需要加密的消息按照块密码的块大小被分为数个块,并对每个块进行独立加密。

  • 优点:可以并行处理数据;
  • 缺点:同样的原文生成同样的密文, 不能很好的保护数据;

CBC:密码块链接. 每个明文块先与前一个密文块进行异或后,再进行加密。

  • 优点:同样的原文生成的密文不一样;
  • 缺点:串行处理数据.;

3、填充模式

当需要按块处理的数据, 数据长度不符合块处理需求时, 按照一定的方法填充满块长的规则。

NoPadding:不填充;

  • 在DES加密算法下, 要求原文长度必须是8byte的整数倍
  • 在AES加密算法下, 要求原文长度必须是16byte的整数倍

PKCS5Padding:数据块的大小为8位, 不够就补足;

4、Base64算法

  • Base64算法是可读性编码算法,不是为了保护数据安全性。是为了数据可读;
  • 可读性编码不改变信息内容,只改变信息的表现形式;
  • Base64在编码过程中用到了64种字符,A-Z,a-z,0-9,“+”,“/”;

Base64算法原理:

  • base64是3个字节为1组,1个字节8位,一共24位;然后把3个字节转成4组,每组6位;缺少的2为,高位补0;这样base64的取值就控制在0-63之间了;
  • base64是3个字节为1组,位数不够时,用 = 来补齐;

说明:

  • 默认情况下, 加密模式和填充模式为 : ECB/PKCS5Padding;
  • 如果使用CBC模式, 在初始化Cipher对象时, 需要增加参数, 初始化向量IV : IvParameterSpec iv = new IvParameterSpec(key.getBytes());

5、DES/AES加密解密代码

/**
 * @author:秋一叶
 * @date:2020-11-18 9:11
 *  DES/AES加密解密
 */
public class DesAesDemo {
    public static void main(String[] args) throws Exception {
        String input = "原文";

        //key:DES加密算法的key必须是8个字节
        String key = "abcd1234";
        //key:AES加密算法的key必须是16个字节
        String key2 = "abcdefgh12345678";

        //获取Cipher对象的算法,默认加密模式和填充模式为 ECB/PKCS5Padding
        String transformation = "DES";
        //加密模式为CBC,必须指定初始向量,初始向量中密钥长度必须是8个字节
        String transformation1 = "DES/ECB/PKCS5Padding";
        //填充模式为NoPadding,原文的长度必须是8字节的整数倍
        String transformation2 = "DES/ECB/PKCS5Padding";

        //指定加密算法
        String algorithm = "DES";

        String encryptDES = encryptDES(input, key, transformation, algorithm);
        System.out.println("加密后为:" + encryptDES);

        String decryptDES =  decryptDES(encryptDES, key, transformation, algorithm);
        System.out.println("解密后为:" + decryptDES);
    }

    /**
     * 加密
     * @param input 原文
     * @param key   密钥
     * @param transformation    获取Cipher对象的算法
     * @param algorithm         获取密钥的算法
     * @return
     */
    public static String encryptDES(String input, String key, String transformation, String algorithm) throws Exception {
        //获取加密对象
        Cipher cipher = Cipher.getInstance(transformation);
        //创建加密规则
        SecretKeySpec sks = new SecretKeySpec(key.getBytes(), algorithm);

        //加密模式为CBC时:初始向量,长度必须是8位
        IvParameterSpec iv = new IvParameterSpec(key.getBytes());

        //初始化加密模式和算法
        cipher.init(Cipher.ENCRYPT_MODE, sks);
        //加密
        byte[] bytes = cipher.doFinal(input.getBytes());
        //对数据进行Base64编码
        String encode = Base64.encodeBase64String(bytes);
        return new String(encode);
    }

    /**
     * 解密
     * @param input
     * @param key
     * @param transformation
     * @param algorithm
     * @return
     * @throws Exception
     */
    public static String decryptDES(String input, String key, String transformation, String algorithm) throws Exception {
        //获取解密对象
        Cipher cipher = Cipher.getInstance(transformation);
        //指定密钥规则
        SecretKeySpec sks = new SecretKeySpec(key.getBytes(), algorithm);

        //加密模式为CBC时:初始向量,长度必须是8位
        IvParameterSpec iv = new IvParameterSpec(key.getBytes());

        //初始化加密模式和算法
        cipher.init(Cipher.DECRYPT_MODE, sks);
        //对数据进行Base64转码,解密
        byte[] bytes = cipher.doFinal(Base64.decodeBase64(input));
        return new String(bytes);
    }
}

说明:

  • DES和AES代码一样,只需要将指定的加密算法换一下就可以。
  • DES加密算法的key必须是8个字节,AES加密算法的key必须是16个字节。
  • 默认加密模式和填充模式为 ECB/PKCS5Padding。
  • 加密模式为CBC,必须指定初始向量,初始向量中密钥长度必须是8个字节。
  • 填充模式为NoPadding,原文的长度必须是8字节(AES是16字节)的整数倍。

二、非对称加密

1、介绍

非对称加密:加密和解密使用一对密钥(公钥和私钥),公钥加密则私钥解密,私钥加密则公钥解密。
非对称加密算法:RSA、ECC等。

非对称加密的特点:

  • 处理数据的速度较慢, 因为安全级别高;

2、RSA加密与解密代码

/**
 * @author:秋一叶
 * @date:2020-11-18 16:01
 * 非对称加密RSA
 *      综合,先把私钥和公钥保存到本地文件中,再读取出来进行私钥加密,公钥解密
 */
public class RsaDemo03 {
    public static void main(String[] args) throws Exception {
        String input = "原文";

        //generateKeyToFile("RSA", "a.pub", "a.pri");
        PrivateKey privateKey = getPrivateKey("a.pri", "RSA");
        PublicKey publicKey = getPublicKey("a.pri", "RSA");

        //加密
        String encrypt = encryptRSA("RSA", privateKey, input);
        //解密
        String decrypt = decryptRSA("RSA", publicKey, encrypt);
        System.out.println("解密后:" + decrypt);

    }

    /**
     * 保存公钥和私钥到本地文件
     * @param algorithm 加密算法
     * @param pubPath   公钥保存路径
     * @param priPath   私钥保存路径
     * @throws Exception
     */
    private static void generateKeyToFile(String algorithm, String pubPath, String priPath) throws Exception{
        //创建密钥对生成器对象
        KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
        //生成密钥对
        KeyPair keyPair = kpg.generateKeyPair();
        //生成私钥和公钥
        PrivateKey privateKey = keyPair.getPrivate();
        PublicKey publicKey = keyPair.getPublic();
        //获取私钥公钥字节数组
        byte[] privateKeyEncoded = privateKey.getEncoded();
        byte[] publicKeyEncoded = publicKey.getEncoded();
        //对公私钥进行base64编码
        String privateKeyString = Base64.encodeBase64String(privateKeyEncoded);
        String publicKeyString = Base64.encodeBase64String(publicKeyEncoded);

        //保存文件
        FileUtils.writeStringToFile(new File(pubPath), publicKeyString, Charset.forName("UTF-8"));
        FileUtils.writeStringToFile(new File(priPath), privateKeyString, Charset.forName("UTF-8"));
    }

    /**
     * 读取私钥
     * @param priPath
     * @param algorithm
     * @return
     * @throws Exception
     */
    public static PrivateKey getPrivateKey(String priPath, String algorithm) throws Exception{
        //将文件内容转为字符串
        String privateKeyString = FileUtils.readFileToString(new File(priPath), Charset.defaultCharset());
        //获取密钥工厂
        KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
        //构建密钥规范,进行Base64解码
        PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyString));
        //生成私钥
        return keyFactory.generatePrivate(spec);
    }

    /**
     * 读取公钥
     * @param pulickPath
     * @param algorithm
     * @return
     * @throws Exception
     */
    public static PublicKey getPublicKey(String pulickPath,String algorithm) throws Exception{
        // 将文件内容转为字符串
        String publicKeyString = FileUtils.readFileToString(new File(pulickPath), Charset.defaultCharset());
        // 获取密钥工厂
        KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
        // 构建密钥规范 进行Base64解码
        X509EncodedKeySpec spec = new X509EncodedKeySpec(Base64.decodeBase64(publicKeyString));
        // 生成公钥
        return keyFactory.generatePublic(spec);
    }

    /**
     * 公钥解密
     * @param algorithm 加密算法
     * @param key   公钥
     * @param encrypted 密文
     * @return
     * @throws Exception
     */
    public static String decryptRSA(String algorithm,Key key,String encrypted) throws Exception{
        // 创建加密对象
        // 参数表示加密算法
        Cipher cipher = Cipher.getInstance(algorithm);
        // 私钥进行解密
        cipher.init(Cipher.DECRYPT_MODE,key);
        // 由于密文进行了Base64编码, 在这里需要进行解码
        byte[] decode = Base64.decodeBase64(encrypted);
        // 对密文进行解密,不需要使用base64,因为原文不会乱码
        byte[] bytes1 = cipher.doFinal(decode);
        System.out.println(new String(bytes1));
        return new String(bytes1);
    }

    /**
     * 私钥加密
     * @param algorithm 加密算法
     * @param key   私钥
     * @param input 原文
     * @return
     * @throws Exception
     */
    public static String encryptRSA(String algorithm,Key key,String input) throws Exception{
        // 创建加密对象
        // 参数表示加密算法
        Cipher cipher = Cipher.getInstance(algorithm);
        // 初始化加密
        // 第一个参数:加密的模式
        // 第二个参数:使用私钥进行加密
        cipher.init(Cipher.ENCRYPT_MODE,key);
        // 私钥加密
        byte[] bytes = cipher.doFinal(input.getBytes());
        // 对密文进行Base64编码
        return Base64.encodeBase64String(bytes);
    }
}

说明:

  • 该案例是私钥加密,公钥解密;
  • 先把密钥生成器生成的公钥和私钥保存到本地中,用的时候直接从本地中获取;

三、散列(哈希)算法

1、介绍

常见哈希算法:MD5、SHA-1、SHA-256、SHA-512;
哈希加密函数通常用来做消息摘要;

2、消息摘要

  • 消息摘要也叫数字摘要;
  • 使用数字摘要生成的值不可以篡改;
  • 消息摘要是单向,不可逆的;
  • 计算的出的消息摘要长度是固定的,MD5(128位),SHA-1(160位);

3、获取数字摘要代码

/**
 * @author:秋一叶
 * @date:2020-11-18 15:43
 * 消息摘要:MD5
 */
public class DigestDemo {
    public static void main(String[] args) throws Exception {
        String input = "原文";
        //获取数字摘要对象
        MessageDigest messageDigest = MessageDigest.getInstance("MD5");
        //获取数字摘要的字节数组
        byte[] digest = messageDigest.digest(input.getBytes());
        //System.out.println(Base64.encodeBase64String(digest));

        StringBuilder sb = new StringBuilder();
        for(byte b : digest){
            //转成16进制
            String s = Integer.toHexString(b & 0xff);
            if(s.length() == 1){
                s = "0" + s;
            }
            sb.append(s);
        }
        System.out.println(sb.toString());
    }
}
  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值