Android 平台DES IV 加密解密随笔
Android 平台DES IV 加密解密随笔
好记性不如烂笔头,所以开始写博客了。一方面加深自己的理解,二方面给后面初学者少走弯路,不论难易,有些东西可能理解的不深,欢迎各位高手指导赐教加吐槽!
DES加密接触过好多次了,但总容易忘,和服务器交互时,加出来不一致后面能解密成功但是头部是乱码导致小坑了一会,在此记录下来~
根据百度百科和自己的理解,DES是一个基于56位密钥的对称的加密算法,就是两边的密钥需要一致,在此就不考虑为什么不用安全性更高的AES或者采用非对称加密方法,比如RSA等等;关于密钥空间小,可以使用DES的派生算法3DES来进行加密。DES算法是把64位的明文输入块变成64位的密文输出块,所以这里需要BASE64编解码工具类,加密需要3个参数(Key、Data、Mode) Mode是加密还是解密,其它就不解释了,注释写的比较清楚。
下面是加密解密方法:
<span style="font-size:18px;">public class EncryptUtils { <span style="white-space:pre"> </span>public static String encryptDES(String encryptString, String encryptKey) <span style="white-space:pre"> </span>throws Exception { <span style="white-space:pre"> </span>//返回实现指定转换的 Cipher 对象<span style="white-space:pre"> </span>“算法/模式/填充” <span style="white-space:pre"> </span>Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding"); <span style="white-space:pre"> </span>//创建一个 DESKeySpec 对象,使用 8 个字节的key作为 DES 密钥的密钥内容。 <span style="white-space:pre"> </span>DESKeySpec desKeySpec = new DESKeySpec(encryptKey.getBytes("UTF-8")); <span style="white-space:pre"> </span>//返回转换指定算法的秘密密钥的 SecretKeyFactory 对象。 <span style="white-space:pre"> </span>SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); <span style="white-space:pre"> </span>//根据提供的密钥生成 SecretKey 对象。 <span style="white-space:pre"> </span>SecretKey secretKey = keyFactory.generateSecret(desKeySpec); <span style="white-space:pre"> </span>//使用 iv 中的字节作为 IV 来构造一个 IvParameterSpec 对象。复制该缓冲区的内容来防止后续修改。 <span style="white-space:pre"> </span>IvParameterSpec iv = new IvParameterSpec(encryptKey.getBytes()); <span style="white-space:pre"> </span>//用密钥和一组算法参数初始化此 Cipher;Cipher:加密、解密、密钥包装或密钥解包,具体取决于 opmode 的值。 <span style="white-space:pre"> </span>cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv); <span style="white-space:pre"> </span>//加密同时解码成字符串返回 <span style="white-space:pre"> </span>return new String(BASE64.encode(cipher.doFinal(encryptString <span style="white-space:pre"> </span>.getBytes("UTF-8")))); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>public static String decryptDES(String decodeString, String decodeKey) throws Exception { <span style="white-space:pre"> </span>//使用指定密钥构造IV <span style="white-space:pre"> </span>IvParameterSpec iv = new IvParameterSpec(decodeKey.getBytes()); <span style="white-space:pre"> </span>//根据给定的字节数组和指定算法构造一个密钥。 <span style="white-space:pre"> </span>SecretKeySpec skeySpec = new SecretKeySpec(decodeKey.getBytes(), "DES"); <span style="white-space:pre"> </span>//返回实现指定转换的 Cipher 对象 <span style="white-space:pre"> </span>Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding"); <span style="white-space:pre"> </span>//解密初始化 <span style="white-space:pre"> </span>cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv); <span style="white-space:pre"> </span>//解码返回 <span style="white-space:pre"> </span>byte[] byteMi = BASE64.decode(decodeString.toCharArray()); <span style="white-space:pre"> </span>byte decryptedData[] = cipher.doFinal(byteMi); <span style="white-space:pre"> </span>return new String(decryptedData); <span style="white-space:pre"> </span>} } </span>
几个错误需要解释下:
java.security.InvalidAlgorithmParameterException: IV must be 8 bytes long.
java.security.InvalidKeyException: key too short
这两种错误都是key的长度造成的,但官方说密钥是56位长度,这个有点不太明白,但你只要记住key的长度必须是8位!这个地方还请高手赐教!
IV向量:主要作用就是防止篡改的,这个地方如果不一致会导致数据的头部解出来是乱码,而后面正常。
BASE64 编解码工具类
<span style="font-size:18px;">public class BASE64 { static public char[] encode(byte[] data) { char[] out = new char[((data.length + 2) / 3) * 4]; for (int i = 0, index = 0; i < data.length; i += 3, index += 4) { boolean quad = false; boolean trip = false; int val = (0xFF & (int) data[i]); val <<= 8; if ((i + 1) < data.length) { val |= (0xFF & (int) data[i + 1]); trip = true; } val <<= 8; if ((i + 2) < data.length) { val |= (0xFF & (int) data[i + 2]); quad = true; } out[index + 3] = alphabet[(quad ? (val & 0x3F) : 64)]; val >>= 6; out[index + 2] = alphabet[(trip ? (val & 0x3F) : 64)]; val >>= 6; out[index + 1] = alphabet[val & 0x3F]; val >>= 6; out[index + 0] = alphabet[val & 0x3F]; } return out; } static public byte[] decode(char[] data) { int len = ((data.length + 3) / 4) * 3; if (data.length > 0 && data[data.length - 1] == '=') --len; if (data.length > 1 && data[data.length - 2] == '=') --len; byte[] out = new byte[len]; int shift = 0; int accum = 0; int index = 0; for (int ix = 0; ix < data.length; ix++) { int value = codes[data[ix] & 0xFF]; if (value >= 0) { accum <<= 6; shift += 6; accum |= value; if (shift >= 8) { shift -= 8; out[index++] = (byte) ((accum >> shift) & 0xff); } } } if (index != out.length) throw new Error("miscalculated data length!"); return out; } static private char[] alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=" .toCharArray(); static private byte[] codes = new byte[256]; static { for (int i = 0; i < 256; i++) codes[i] = -1; for (int i = 'A'; i <= 'Z'; i++) codes[i] = (byte) (i - 'A'); for (int i = 'a'; i <= 'z'; i++) codes[i] = (byte) (26 + i - 'a'); for (int i = '0'; i <= '9'; i++) codes[i] = (byte) (52 + i - '0'); codes['+'] = 62; codes['/'] = 63; } }</span>
加密解密使用
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。