zoukankan      html  css  js  c++  java
  • AES加密解密

    AES是对称加密算法,秘钥是相同的。

    这里参考了CSDN上的一篇文章(点击这里)。与之不同的是我需要先把加密后的密文保存成一个TXT文件,再读取并解密。

    按理说应该是很简单的但我却就被这个保存——读取的中间环节弄得晕头转向花费了大量时间。

    因为保存之后再读取解密的时候总是出现提示:

    Input length must be multiple of 16 when decrypting with padded cipher.

    解密时的输入长度必须是16(字节?比特?)的倍数。

    那篇文章的作者也提到了:

    加密后的byte数组是不能强制转换成字符串的,换言之:字符串和byte数组在这种情况下不是互逆的;要避免这种情况,我们需要做一些修订,可以考虑将二进制数据转换成十六进制表示。

    他提供的一种方法是先转换成16进制,再转换回来。

    一开始我用FileReader每次读取100字节的buffer到一个String里面保存起来。

    后来发现解密的时候总是报错说不是16的倍数。我把读到的内容输出,却发现里面确实都是16进制的数字啊(0~F)。(题外话,用FileOutputStream输出byte,用OutputStreamWriter输出String。)

    后来经过比对我发现读出的String跟加密并且转换成16进制的String有一点细微差别就是结尾多读了「0F503019」,是的,是多读了而不是多写了,我把转换成16进制的密文直接复制过来定义成一个String,是可以解码的,而加了结尾的「0F503019」就不行了。

    我大概了解了16的倍数的意思,意思是这整个“013DDD1AC930DCA9D20D763A68CEC033AD04CC2FA039E2EB286CC3B28FAB5658EE1623D29ECF5928452A8A94602E6B7406ACF959A3B9C14CBCC27AF4F1B46C8AC5B8A1FB4CC42598A....”一串字符是16的倍数,而加了「0F503019」之后看上去虽然仍然好像都是16进制数但是其实已经不是16的倍数了。

    我操。

    结合在百度知道上得到的信息(HERE):

    「如果这个文件内容只是一些文本信息,不是类图片等的二进制数据,不要使用这种方式读写,应该用BufferedReader和FileReader,可指定文本的编码方式,因为文本中的一个字符可能由1字节、或2字节或更多字节组成(由编码方式不同而不同)。」

    我用FileReader 和 BufferedReader,用ReadLine方法读取那个加密后的16进制的密文再解密,不提示「不是16的倍数了」,并且能够解密了。

    解决这个问题实在耗费了太多精力。太累了。我不敢保证下次不会再碰到这样蛋疼的问题,希望在这样的总结之后以后面对这样的问题能够更加得心应手。

    明天把这个代码弄到Android里,不知道能不能成功。

    Mar.23 

    -------------------------------------

    今天是25号,昨天弄了一天也没弄成,遇到很多问题。

    1:            //KeyGenerator kgen = KeyGenerator.getInstance("AES"); //android4.1以后会有bug,替换下边一句

          SecureRandom sr = SecureRandom.getInstance("SHA1PRNG"); 
                   替换为:SecureRandom sr = SecureRandom.getInstance("SHA1PRNG", "Crypto");  

          经过测试,如果不加上后面的"Crypto",解密出来就会出现无规则、无格式的乱码。

            替换之后格式对了,英文、数字也正常了,但是中文仍然是乱码。格式是UTF-8,考虑到是不是应该输出成别的编码?但是按照往常的经验,即便编码不       对,在windows下用记事本还是应该可以正常阅读的。后来尝试输出了别的编码,但只能用toString()方法把byte转换成string,这样就又出现了输出      @[BXXXX一串HOLY CRAP的情况。

    2:             //Cipher cipher = Cipher.getInstance("AES"); //4.3以上有bug,用下边一句ok
                    Cipher cipher = Cipher.getInstance("AES/ECB/ZeroBytePadding"); 

          若不这样改,会出现:

          javax.crypto.BadPaddingException: pad block corrupted

  • 相关阅读:
    SVN版本控制服务
    JVM内存结构
    Git的使用
    Nginx详解
    Apache(httpd)详解
    rsyslog日志收集器
    nsswitch名称解析框架
    NFS网络文件系统
    ThreadLocal详解
    RocketMQ踩坑记
  • 原文地址:https://www.cnblogs.com/larrylawrence/p/3619693.html
Copyright © 2011-2022 走看看