zoukankan      html  css  js  c++  java
  • AES加密实现

    起因

    这段时间因为要对接一个外部接口,其参数的加密方式为AES,就需要学下AES的加密写法,但网上的资料不是很全,自己记录下遇到的坑;

    基本写法

    String str = "hello";
            String password = "1234567890123456";
            //新建一个密码编译器的实例,由三部分构成,用"/"分隔,分别代表加密的类型(如AES,DES,RC2等),模式(AES中包含ECB,CBC,CFB,CTR,CTS等),补码方式(包含nopadding/PKCS5Padding等等),依据这三个参数可以创建很多种加密方式
            Cipher cipher = Cipher.getInstance(String.format("%s/%s/%s", SymmetricAlgorithm.AES.name(), Mode.ECB.name(), Padding.PKCS5Padding.name()));
            //构建密钥
            SecretKeySpec key  = new SecretKeySpec(password.getBytes(Charset.forName("utf-8")),"AES");
            cipher.init(Cipher.ENCRYPT_MODE, key);//使用加密模式初始化 密钥
            byte[] encrypt = cipher.doFinal(str.getBytes()); //按单部分操作加密或解密数据,或者结束一个多部分操作。
            System.out.println(Base64.encode(encrypt));
            System.out.println("method2-加密:" + Arrays.toString(encrypt));
            cipher.init(Cipher.DECRYPT_MODE, key);//使用解密模式初始化 密钥
            byte[] decrypt = cipher.doFinal(encrypt);
            System.out.println("method2-解密后:" + new String(decrypt));
    

      

    优化写法

    这样一个最简单的AES加解密就完成了,但有一个缺点,密码的长度必须为128位,也就是16个字节,否则会报错;
    当使用AES/ECB/NoPadding模式时,加密的内容的字节长度也必须为16的整倍数,否则也会提示错误;
    可采用的方法是:如果key的长度小于16,则补全16位,否则截取16位
    加密内容补全为16的整倍数,以下为示例代码:

    /**
         * 测试AES加密,使用ECB/Nopadding的方式,要求key的长度为128位,内容的长度也为128位的整数倍
         * @param content
         * @param password
         * @return
         */
    private String testAes(String content,String password) throws Exception {
            //原始字节数组
            byte[] passwordBytes = password.getBytes(Charset.forName("utf-8"));
            //填充为16位
            byte[] keyBytes  = new byte[16];
            byte[] contentBytes = content.getBytes(Charset.forName("utf-8"));
            byte[] contentBytesTarget ;
            Cipher cipher = Cipher.getInstance(String.format("%s/%s/%s", SymmetricAlgorithm.AES.name(), Mode.ECB.name(), Padding.NoPadding.name()));
            if(passwordBytes.length < 16)
                System.arraycopy(passwordBytes,0,keyBytes,0,passwordBytes.length);
            else
                System.arraycopy(passwordBytes,0,keyBytes,0,16);
    
            if(contentBytes.length % 16 == 0)
                contentBytesTarget = contentBytes;
            else{
                contentBytesTarget = new byte[contentBytes.length + 16 - contentBytes.length % 16 ];
                System.arraycopy(contentBytes,0,contentBytesTarget,0,contentBytes.length);
            }
    
            SecretKeySpec key = new SecretKeySpec(keyBytes,"AES");
    
            cipher.init(Cipher.ENCRYPT_MODE, key);//使用加密模式初始化 密钥
            byte[] encrypt = cipher.doFinal(contentBytesTarget); //按单部分操作加密或解密数据,或者结束一个多部分操作。
            System.out.println(Base64.encode(encrypt));
            System.out.println("method2-加密:" + Arrays.toString(encrypt));
            cipher.init(Cipher.DECRYPT_MODE, key);//使用解密模式初始化 密钥
            byte[] decrypt = cipher.doFinal(encrypt);
            System.out.println("method2-解密后:" + new String(decrypt));
            return Base64.encode(encrypt);
        }
    

      

    测试

    可以使用在线工具进行测试:http://tool.chacuo.net/cryptaes

    <wiz_tmp_tag id="wiz-table-range-border" contenteditable="false" style="display: none;">

  • 相关阅读:
    Java字符集
    ==和equals区别
    web.xml中load-on-startup标签的含义
    使用solrJ管理索引——(十四)
    Solr管理索引库——(十三)
    [置顶] 关于redhat系统yum源的配置1
    设置Oracle用IP远程连接和客户端访问
    jqueryUI中datepicker的使用,解决与asp.net中的UpdatePanel联合使用时的失效问题
    [置顶] 关于redhat系统yum源的配置2
    浅析innodb_support_xa与innodb_flush_log_at_trx_commit
  • 原文地址:https://www.cnblogs.com/417xiaoliu/p/7892563.html
Copyright © 2011-2022 走看看