最近在设计一个给IOS和Android提供接口的项目框架,在接口安全上准备使用常规的加密技术,确保在非法访问接口的情况下拿到的数据一时半会也没用。

查了相关的资料,用的最多的几种加密算法,DES、AES、3DES等,考虑到手机端的兼容,先用了DES。但我遇到一个现象后,让我决定放弃DES,不知道有没有大神也遇到过,就是我用DES加密后,再用AES加密DES解密后的内容。拿到密文后使用AES反过来解密,结果AES一次解密后就得到了两次加密前的明文。为了排除是内存的问题,我特地在A机器上加密,B机器上解密,结果还是坑爹的一样。为了节省时间就没有细细的研究了,有时间了再细细研究。

最后决定选用AES,密钥长度为128位作为加解密工具,在与前端联调的发现了个问题,就是服务器加密的数据,客户端无法解密。经过研究发现,是由于IOS加密填充方式是PKCS7Padding和而服务器使用的加密填充方式是PKCS5Padding,只支持56位密钥。查询资料后发现使用AES密钥为256位加密后在客户端可以正常的解密。但有个问题,就是我使用的JDK1.6自带的security是不支持256位的。这个使用可以使用Bouncy castle,它支持PKCS7Padding的64位算法。

下面说说具体的实现办法:

1、声明密钥算法

public static final String KEY_ALGORITHM="AES";

2、声明加密填充方式public static final String CIPHER_ALGORITHM="AES/ECB/PKCS7Padding";

3、生成密钥,生成的密钥原本是byte[]类型,为了对密钥进行在加工,这里我用Base64加密了一次,如果不要的这里可以直接返回byte[]public static String initkey() throws Exception{ //实例化密钥生成器 Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); KeyGenerator kg=KeyGenerator.getInstance(KEY_ALGORITHM, "BC"); //初始化密钥生成器,AES要求密钥长度为128位、192位、256位 kg.init(256); //生成密钥 SecretKey secretKey=kg.generateKey(); //获取二进制密钥编码形式 return Base64.encode(secretKey.getEncoded());}4、密钥转换public static Key toKey(byte[] key) throws Exception{ //实例化DES密钥 //生成密钥 SecretKey secretKey=new SecretKeySpec(key,KEY_ALGORITHM); return secretKey;}5、加密方法,跟生成密钥一样,对传参部分进行了处理public static String encrypt(String data,String key) throws Exception{ byte[] keys = Base64.decode(key); //还原密钥 Key k=toKey(keys); /** * 实例化 * 使用 PKCS7PADDING 填充方式,按如下方式实现,就是调用bouncycastle组件实现 * Cipher.getInstance(CIPHER_ALGORITHM,"BC") */ Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); Cipher cipher=Cipher.getInstance(CIPHER_ALGORITHM, "BC"); //初始化,设置为加密模式 cipher.init(Cipher.ENCRYPT_MODE, k); //执行操作 return Base64.encode(cipher.doFinal(data.getBytes()));}5、解密数据public static String decrypt(String data,String key) throws Exception{ byte[] datas = Base64.decode(data); byte[] keys = Base64.decode(key); //欢迎密钥 Key k =toKey(keys); /** * 实例化 * 使用 PKCS7PADDING 填充方式,按如下方式实现,就是调用bouncycastle组件实现 * Cipher.getInstance(CIPHER_ALGORITHM,"BC") */ Cipher cipher=Cipher.getInstance(CIPHER_ALGORITHM); //初始化,设置为解密模式 cipher.init(Cipher.DECRYPT_MODE, k); //执行操作 return new String(cipher.doFinal(datas));}6、Main方法测试public static void main(String[] args) throws UnsupportedEncodingException{ String str="DaddyCai"; System.out.println("原文:"+str); try { //初始化密钥 String key = AES256Encryption.initkey(); System.out.println("密钥:"+key); //加密数据 String data=AES256Encryption.encrypt(str, key); System.out.println("加密后:"+data); //解密数据 System.out.println("解密后:"+AES256Encryption.decrypt(data, key)); } catch (Exception e) { e.printStackTrace(); }}

到这里,一个简单的加解密算法就算实现了,这里有点要注意:jdk自带的security不能生成64位密钥,需要替换原jdk下security的两个文件。以上代码仅供大家研究测试,完整代码可以在这里下载!

下载地址:http://download.csdn.net/download/localhost_8080/8551677

查看原文 >>
相关文章