MD5 SHA DES AES

什么是MD5?SHA?DES?AES?有没有被这些 缩写搞晕?晕就对了。

MD5、SHA是属于 哈希算法。

DES、AES是属于 加密算法。

都是JDK提供了。拿来就用。

该文不涉及原理剖析,仅 是 使用 示例。

MDA、SHA核心代码:

/**
         * 哈希,可用于 文件校验、口令存储等
         */
        //哈希算法(Hash)又称摘要算法(Digest)
        // https://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html#MessageDigest
        // 创建一个MessageDigest实例:
        // MD5:得到16个字节,SHA-1:得到20个字节, SHA-256:得到32个字节,SHA-512:得到64个字节;字节越多,碰撞就少
        MessageDigest md = MessageDigest.getInstance("SHA-1");
        // 反复调用update输入数据:相当于调用一次 md.update("HelloWorld".getBytes("UTF-8"));
        md.update("Hello".getBytes("UTF-8"));
        md.update("World".getBytes("UTF-8"));
        byte[] result = md.digest(); // 16 bytes: 68e109f0f40ca72a15e05cc22786f8e6
        System.out.println(new BigInteger(1, result).toString(16));

        // 使用第三方哈希包:注册BouncyCastle:
        Security.addProvider(new BouncyCastleProvider());
        // 按名称正常调用:
        MessageDigest md2 = MessageDigest.getInstance("RipeMD160");
        md2.update("HelloWorld".getBytes("UTF-8"));
        byte[] result2 = md2.digest();
        System.out.println(new BigInteger(1, result2).toString(16));


        //Hmac Hash-based Message Authentication Code
        // Hmac 算法是一种标准的基于密钥的哈希算法,可以配合MD5、SHA-1等哈希算法,计算的摘要长度和原摘要算法长度相同
        KeyGenerator keyGen = KeyGenerator.getInstance("HmacMD5");
        SecretKey key = keyGen.generateKey();
        Mac mac = Mac.getInstance("HmacMD5");
        mac.init(key);
        mac.update("HelloWorld".getBytes("UTF-8"));
        byte[] result3 = mac.doFinal();
        System.out.println(new BigInteger(1, result3).toString(16));

        SecretKey key2 = new SecretKeySpec(key.getEncoded(), "HmacMD5");
        Mac mac2 = Mac.getInstance("HmacMD5");
        mac2.init(key2);
        mac2.update("HelloWorld".getBytes("UTF-8"));
        byte[] result4 = mac2.doFinal();
        System.out.println(new BigInteger(1, result4).toString(16));

DES、AES核心代码:

ECB填充模式:

// 加密:
    public static byte[] encrypt(byte[] key, byte[] input) throws GeneralSecurityException {
        // 根据 算法名称/工作模式/填充模式获取Cipher实例
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        // 根据算法名称初始化一个 SecretKey 实例,密钥必须是指定长度
        SecretKey keySpec = new SecretKeySpec(key, "AES");
        // 使用 SecretKey 初始化Cipher实例,并设置加密或解密模式
        cipher.init(Cipher.ENCRYPT_MODE, keySpec);
        // 传入明文或密文,获得密文或明文
        return cipher.doFinal(input);
    }

    // 解密:
    public static byte[] decrypt(byte[] key, byte[] input) throws GeneralSecurityException {
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        SecretKey keySpec = new SecretKeySpec(key, "AES");
        cipher.init(Cipher.DECRYPT_MODE, keySpec);
        return cipher.doFinal(input);
    }

CBC填充模式:

// 加密:
    public static byte[] encrypt2(byte[] key, byte[] input,byte[] iv) throws GeneralSecurityException {
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        SecretKey keySpec = new SecretKeySpec(key, "AES");
        AlgorithmParameterSpec ivps = new IvParameterSpec(iv);
        cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivps);
        byte[] data = cipher.doFinal(input);
        return data;
    }

    // 解密:
    public static byte[] decrypt2(byte[] key, byte[] input,byte[] iv) throws GeneralSecurityException {
        // 解密:
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        SecretKey keySpec = new SecretKeySpec(key, "AES");
        AlgorithmParameterSpec ivps = new IvParameterSpec(iv);
        cipher.init(Cipher.DECRYPT_MODE, keySpec, ivps);
        return cipher.doFinal(input);
    }

解释:

 /**
         * 在软件开发中,常用的对称加密算法有:
         *
         * 算法	    密钥长度	        工作模式	                    填充模式
         * DES	    56/64	        ECB/CBC/PCBC/CTR/...	    NoPadding/PKCS5Padding/...
         * AES	    128/192/256	    ECB/CBC/PCBC/CTR/...	    NoPadding/PKCS5Padding/PKCS7Padding/...
         * IDEA	    128	            ECB	                        PKCS5Padding/PKCS7Padding/...
         *
         * 不同加密算法在使用时,需要 使用 自己对应的 密钥长度、工作模式、填充模式
         * 比如:
         * DES 需要 密钥长度 是 56或者64 个 bit,对应7个byte或者8个byte
         * AES 需要 密钥长度是 128/192/256 个 bit,对应16个byte,24个byte,32个byte
         *
         * Cipher  [ˈsaɪfə(r)] 密码算法;密码;密文;加密算法;欣技, 知道这个单词,有利于学习后面的加密算法
         *
         * public class IvParameterSpec implements AlgorithmParameterSpec
         *
         * AlgorithmParameterSpec 接口,没有任何方法,表示  加密算法 参数规范
         * IvParameterSpec 是一个实现类,简称IV: initialization vector ,表示 初始化向量
         * CBC 需要这个类作为参数
         *
         * AES算法的 IV参数长度必须是 16 个 byte
         * DES算法的 IV参数长度必须是 8 个 byte
         *
         * 所以,如果需要使用 CBC模式,IV参数的 字节数 还不一样。
         *
         * 简单步骤:
         * ECB模式:
         * 1. 获取 加密算法 对象 Cipher
         * 2. 获取 密钥对象 SecretKey
         * 3. 利用 密钥对象 对 加密算法 进行初始化
         * 4. 加密 数据
         *
         * CBC模式:
         * 1. 获取 加密算法 对象 Cipher
         * 2. 获取 密钥对象 SecretKey
         * 3. 获取 IV 对象(IvParameterSpec)
         * 4. 利用 密钥对象 和 IV对象 初始化 加密算法
         * 5. 加密数据
         *
         * 加密算法的 的加密方法的入参是字节数组,
         * 意味着 需要程序把 密钥 和 原文转为字节流,
         * 加密后的数据 也是字节流, 可以 使用 Base64最字节进行编码成文本
         */

        /**
         * 以下使用 AES 算法演示,
         *
         * 如果 换成 DES,则需要 修改一下 密钥 和 IV,因为 不同算法对应的长度不一样
         */

        // 原文:
        String message = "Hello, world!";
        System.out.println("Message: " + message);
        // 128位密钥 = 16 bytes Key:
        byte[] key85 = "1234567890abcdef".getBytes("UTF-8");
        // 加密:
        byte[] data = message.getBytes("UTF-8");
        byte[] encrypted = encrypt(key85, data);
        System.out.println("Encrypted: " + Base64.getEncoder().encodeToString(encrypted));
        // 解密:
        byte[] decrypted = decrypt(key85, encrypted);
        System.out.println("Decrypted: " + new String(decrypted, "UTF-8"));


        /**
         * ECB模式是最简单的AES加密模式,它只需要一个固定长度的密钥,
         * 固定的明文会生成固定的密文,这种一对一的加密方式会导致安全性降低,
         * 更好的方式是通过CBC模式,它需要一个随机数作为IV参数,这样对于同一份明文,每次生成的密文都不同
         */

        // 原文:
        String message116 = "Hello, world!";
        System.out.println("Message: " + message116);
        // 256位密钥 = 32 byte Key:
        byte[] key119 = "1234567890abcdef1234567890abcdef".getBytes("UTF-8");

        // CBC模式需要生成一个16 byte的 initialization vector:
        // 在CBC模式下,需要一个随机生成的16字节IV参数,必须使用SecureRandom生成
        SecureRandom sr = SecureRandom.getInstanceStrong();
        byte[] iv = sr.generateSeed(16);

        // 加密:
        byte[] data121 = message116.getBytes("UTF-8");
        byte[] encrypted122 = encrypt2(key119, data121,iv);
        System.out.println("Encrypted: " + Base64.getEncoder().encodeToString(encrypted122));
        // 解密:
        byte[] decrypted125 = decrypt2(key119, encrypted122,iv);
        System.out.println("Decrypted: " + new String(decrypted125, "UTF-8"));

另外补充一下:

// URL编解码,对url进行编解码
        String encoded = URLEncoder.encode("中文!", StandardCharsets.UTF_8.name());
        System.out.println(encoded);
        String decoded = URLDecoder.decode("%E4%B8%AD%E6%96%87%21", StandardCharsets.UTF_8.name());
        System.out.println(decoded);


        // Base64 编解码, 对 字节流 进行编码
        byte[] input = new byte[] { (byte) 0xe4, (byte) 0xb8, (byte) 0xad };
        String b64encoded = Base64.getEncoder().encodeToString(input);
        System.out.println(b64encoded);

        byte[] output = Base64.getDecoder().decode("5Lit");
        System.out.println(Arrays.toString(output)); // [-28, -72, -83]

这种是属于对称加密,还有其他的加密方式。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值