zoukankan      html  css  js  c++  java
  • 廖雪峰Java10加密与安全-4加密算法-1对称加密算法

    1.对称加密算法

    加密和解密使用同一个密钥,例如WinRAR。

    • WinRAR在对文件进行打包的时候,可以设置一个密码,在解压的时候需要使用同样的密码才能正确的解压。
    • 加密:encrypt(key,message) -> s
    • 解密:decrypt(key,s) -> message
    算法 密钥长度(决定加密的强度) 工作模式(参数) 填充模式(格式的选择)
    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

    JDK提供的算法并没有包括所有的工作模式和填充模式,但我们通常只需要挑选常用的模式使用就可以了。
    DES因为密钥过短,可以在短时间内被暴力破解,所以并不安全。

    2.AES/ECB

    package com.testList;
    
    import javax.crypto.Cipher;
    import javax.crypto.spec.SecretKeySpec;
    import java.nio.charset.StandardCharsets;
    import java.security.GeneralSecurityException;
    import java.util.Base64;
    
    public class SplitString {
        //指定算法为AES,工作模式为ECB,填充模式为PKCS5Padding
        static final String CIPHER_NAME = "AES/ECB/PKCS5Padding";
        //加密
        public static byte[] encrypt(byte[] key,byte[] input) throws GeneralSecurityException{
            //传入算法、工作模式、填充模式,创建Cipher示例
            Cipher cipher = Cipher.getInstance(CIPHER_NAME);
            //将一个byte数组,转化为一个AES的key
            SecretKeySpec secretKeySpec = new SecretKeySpec(key,"AES");
            //初始化:采用加密模式,并传入key
            cipher.init(Cipher.ENCRYPT_MODE,secretKeySpec);
            //通过doFinal传入input数组获取加密后的byte数组
            return cipher.doFinal(input);
        }
        //解密
        public static byte[] decrypt(byte[] key,byte[] input) throws GeneralSecurityException{
            //传入算法、工作模式、填充模式,创建Cipher示例
            Cipher cipher = Cipher.getInstance(CIPHER_NAME);
            //将byte数组,转化为一个AES的key
            SecretKeySpec secretKeySpec = new SecretKeySpec(key,"AES");
            //初始化:采用解密模式,并传入key
            cipher.init(Cipher.DECRYPT_MODE,secretKeySpec);
            //通过doFinal传入input数组获取加密后的byte数组
            return cipher.doFinal(input);
        }
        public static void main(String[] args) throws Exception{
            String message = "Hello,world!encrypted using AES!";
            System.out.println(message);
            //密钥为128位,需要传入128/8=16个byte的字符串
            byte[] key = "1234567890abcdef".getBytes("utf-8");
            byte[] input = message.getBytes(StandardCharsets.UTF_8);
    
            byte[] encrypted = encrypt(key,input);
            //把秘闻转化为61位编码打印
            System.out.println("Encrypted data:"+Base64.getEncoder().encodeToString(encrypted));
    
            byte[] decrypted = decrypt(key,encrypted);
            //将解密后的数组还原为字符串
            System.out.println("Decrypted data:"+new String(decrypted,"utf-8"));
        }
    }
    

    3.AES/CBC

    package com.testList;
    
    import javax.crypto.Cipher;
    import javax.crypto.spec.IvParameterSpec;
    import javax.crypto.spec.SecretKeySpec;
    import java.nio.charset.StandardCharsets;
    import java.security.GeneralSecurityException;
    import java.security.SecureRandom;
    import java.util.Base64;
    
    public class AES_CBC {
        //指定算法为为AES,工作模式为CBC,填充模式为PKCS5Padding
        static final String CIPHER_NAME = "AES/CBC/PKCS5Padding";
        //加密
        public static byte[] encrypt(byte[] key,byte[] input) throws GeneralSecurityException{
            //传入算法、工作模式、填充模式,创建Cipher实例
            Cipher cipher = Cipher.getInstance(CIPHER_NAME);
            //传入key数组,获取SecretKeySpec的实例
            SecretKeySpec keySpec = new SecretKeySpec(key,"AES");
            //创建SecureRandom实例,用于获取随机数
            SecureRandom sr = SecureRandom.getInstanceStrong();
            //获取一个16位字节的数组
            byte[] iv = sr.generateSeed(16);
            //传入随机数组,获取IVParameterSpec实例
            IvParameterSpec ivps = new IvParameterSpec(iv);
            //初始化:指定加密模式,并传入SecretKeySpec实例keySpec、IvParameterSpec实例ivps
            cipher.init(Cipher.ENCRYPT_MODE,keySpec,ivps);
            //通过doFinal传入input数组,获取加密后的byte数组
            byte[] data = cipher.doFinal(input);
            //将iv,data一并返回
            return join(iv,data);
        }
        public static byte[] join(byte[] bs1,byte[] bs2){
            byte[] r = new byte[bs1.length+bs2.length];
            System.arraycopy(bs1,0,r,0,bs1.length);
            System.arraycopy(bs2,0,r,bs1.length,bs2.length);
            return r;
        }
        public static byte[] decrypt(byte[] key,byte[] input) throws GeneralSecurityException{
            //将input数组拆分为iv,data
            byte[] iv = new byte[16];
            byte[] data = new byte[input.length-16];
            System.arraycopy(input,0,iv,0,16);
            System.arraycopy(input,16,data,0,data.length);
            //传入算法、工作模式、填充模式,创建Cipher实例
            Cipher cipher = Cipher.getInstance(CIPHER_NAME);
            //传入key数组,获取AES加密后的SecretKeySpec类型实例
            SecretKeySpec keySpec = new SecretKeySpec(key,"AES");
            //获取IvParameter实例ivps
            IvParameterSpec ivps = new IvParameterSpec(iv);
            //初始化:指定解密模式,并传入SecretKeySpec实例,IvParameterSpec实例
            cipher.init(Cipher.DECRYPT_MODE,keySpec,ivps);
            //返回解密后的数组
            return cipher.doFinal(data);
        }
        public static void main(String[] args) throws Exception {
            String message = "Hello,world!encryptd using AES!";
            System.out.println("Message:"+message);
            byte[] key = "1234567890abcefg".getBytes("utf-8");
            byte[] data = message.getBytes(StandardCharsets.UTF_8);
            byte[] encrypted = encrypt(key,data);
            System.out.println("Encrypt data:"+Base64.getEncoder().encodeToString(encrypted));
            byte[] decryptd = decrypt(key,encrypted);
            System.out.println("Decrypted data:"+new String(decryptd,"utf-8"));
        }
    }
    
    

    4.AES/ECB使用256位加密

    import jdk.nashorn.internal.runtime.ECMAException;
    
    import javax.crypto.Cipher;
    import javax.crypto.spec.SecretKeySpec;
    import java.nio.charset.StandardCharsets;
    import java.security.GeneralSecurityException;
    import java.util.Base64;
    
    public class AES256_ECB {
        static final String CIPHER_NAME = "AES/ECB/PKCS5Padding";
        public static byte[] encrypt(byte[] key,byte[] input) throws GeneralSecurityException {
            Cipher cipher = Cipher.getInstance(CIPHER_NAME);
            SecretKeySpec keySpec = new SecretKeySpec(key,"AES");
            cipher.init(Cipher.ENCRYPT_MODE,keySpec);
            return cipher.doFinal(input);
        }
        public static byte[] decrypt(byte[] key,byte[] input) throws GeneralSecurityException{
            Cipher cipher = Cipher.getInstance(CIPHER_NAME);
            SecretKeySpec keySpec = new SecretKeySpec(key,"AES");
            cipher.init(Cipher.ENCRYPT_MODE,keySpec);
            return cipher.doFinal(input);
        }
        public static void main(String[] args) throws Exception {
            String message = "Hello world!encrypted using AES!";
            System.out.println(message);
            byte[] key = "1234567890abcdef1234567890abcdef".getBytes("utf-8");
            byte[] data = message.getBytes(StandardCharsets.UTF_8);
            byte[] encrypted = encrypt(key,data);
            System.out.println(Base64.getEncoder().encodeToString(encrypted));
            byte[] decrypted = decrypt(key,encrypted);
            System.out.println(new String(decrypted,"utf-8"));
        }
    }
    
    问题:256位加密执行失败 搜索jdk jce policy,[下载jar包](https://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html), window:将下载的jar包复制到jdk/jre/lib/security和jdk/lib/security目录下。 Mac: ```#shell #查看Java目录 which java #寻找jre/lib/security目录 find . -name lcoal_policy.jar ``` 如我的目录是:/Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/jre/lib/security。将下载的jar包复制到该文件。 再次运行,不再报错

    5.总结:

    • 对称加密算法使用同一个密钥进行加密和解密
    • 常用算法:DES/AES/IDEA等
    • 密钥长度由算法设计决定给,AES的密钥长度是128/192/256
    • 使用256位加密需要修改JDK的policy文件
    • 使用对称加密算法需要指定:算法名称/工作模式/填充模式
  • 相关阅读:
    EasyUI的datagrid在IE下解决缓存的方案
    [置顶] 【Mybatis】---mybatis+mysql+ IntelliJ IDEA框架搭建+实例讲解
    【深入分析JavaWeb】-DNS域名解析
    hibernate对JPA_Annotation的支持实例讲解
    【hibernate进阶】hql简单属性查询
    LeetCode 10. 正则表达式匹配
    机器学习(Machine Learning)- 吴恩达(Andrew Ng) 学习笔记(七)
    机器学习(Machine Learning)- 吴恩达(Andrew Ng) 学习笔记(六)
    机器学习(Machine Learning)- 吴恩达(Andrew Ng) 学习笔记(五)
    机器学习(Machine Learning)- 吴恩达(Andrew Ng) 学习笔记(四)
  • 原文地址:https://www.cnblogs.com/csj2018/p/10847053.html
Copyright © 2011-2022 走看看