• 廖雪峰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文件
    • 使用对称加密算法需要指定:算法名称/工作模式/填充模式
  • 相关阅读:
    Asp.NET 4.0 ajax实例DataView 模板编程1
    ASP.NET 4.0 Ajax 实例DataView模板编程 DEMO 下载
    部分东北话、北京话
    .NET 培训课程解析(一)
    ASP.NET 4.0 Ajax 实例DataView模板编程2
    ASP.NET Web Game 架构设计1服务器基本结构
    ASP.NET Web Game 构架设计2数据库设计
    TFS2008 基本安装
    Linux上Oracle 11g安装步骤图解
    plsql developer远程连接oracle数据库
  • 原文地址:https://www.cnblogs.com/csj2018/p/10847053.html
Copyright © 2020-2023  润新知