AES加密,Android, iOS, PHP三平台兼容互通

项目中遇到需要对某些敏感数据进行加密的需求,并且需要兼容Android,iOS,PHP三个平台,也就是说,各个平台上加密相同的数据,加密结果是一样,每个平台加密的密文,其他平台都能解密出正确的原文。

期初,看起来是一个很简单的需求,有强大的互联网嘛,Google下,什么都有,在经历了数次无果的尝试之后,才发现,这个问题并不是很简单,主要的原因是,每个平台实现的加解密算法都有一丝丝不同,要么是这个平台的密文,在另外一个平台不能正确解密;要么就是某两个平台的数据互通兼容了,第三个平台又不支持了;在经历了无数次的查阅资料,搜索stackoverflow后,终于搞定了这个问题,先上代码下载地址:

https://github.com/pkuoliver/EasyAES

先来了解下AES加密算法,来自维基百科

高级加密标准(英语:Advanced Encryption Standard,缩写:AES),在密码学中又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准。这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用。经过五年的甄选流程,高级加密标准由美国国家标准与技术研究院(NIST)于2001年11月26日发布于FIPS PUB 197,并在2002年5月26日成为有效的标准。2006年,高级加密标准已然成为对称密钥加密中最流行的算法之一。

AES加密算法,有不同的实现方式,比如按照秘钥位数,分为128位,192位,256位;按照工作方式,有CBC,ECB,CFB,OFB等四种(详细内容可以查看这里);除此之外,为了数据对齐,还有不同的Padding填充方式,比如NoPadding,PKCS5Padding,PKCS7Padding,ISO10126Padding等填充方式。因此这样排列组合一下,各个平台的加解密不兼容就不奇怪了。

本文实现的是128位的CBC模式PKCS5Padding方式填充的AES算法,废话不多说,上代码:

Android/Java版的

// 构造函数
public EasyAES(final String key, final int bit, final String iv) {
	if (bit == 256) {
		this.key = new SecretKeySpec(getHash("SHA-256", key), "AES");
	} else {
		this.key = new SecretKeySpec(getHash("MD5", key), "AES");
	}
	if (iv != null) {
		this.iv = new IvParameterSpec(getHash("MD5", iv));
	} else {
		this.iv = DEFAULT_IV;
	}

	init();
}

// 初始化
private void init() {
	try {
		cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
	} catch (final Exception ex) {
		throw new RuntimeException(ex.getMessage());
	}
}

// 加密
public String encrypt(final String str) {
	try {
		return encrypt(str.getBytes("UTF-8"));
	} catch (final Exception ex) {
		throw new RuntimeException(ex.getMessage());
	}
}

public String encrypt(final byte[] data) {
	try {
		cipher.init(Cipher.ENCRYPT_MODE, key, iv);
		final byte[] encryptData = cipher.doFinal(data);
		return new String(Base64.encode(encryptData, Base64.DEFAULT), "UTF-8");
	} catch (final Exception ex) {
		throw new RuntimeException(ex.getMessage());
	}
}

//解密
public String decrypt(final String str) {
	try {
		return decrypt(Base64.decode(str, Base64.DEFAULT));
	} catch (final Exception ex) {
		throw new RuntimeException(ex.getMessage());
	}
}

public String decrypt(final byte[] data) {
	try {
		cipher.init(Cipher.DECRYPT_MODE, key, iv);
		final byte[] decryptData = cipher.doFinal(data);
		return new String(decryptData, "UTF-8");
	} catch (final Exception ex) {
		throw new RuntimeException(ex.getMessage());
	}
}

而使用起来也很方便,直接传入要加密/解密的文字即可

public static String encryptString(String content) {
	//这里填写密码和iv字符串,注意要确保16位的
	MagicCrypt mc = new MagicCrypt("****************", 128, "################");
	return mc.encrypt(content);
}

public static String decryptString(String content) {
	String result = null;
	try {
		//这里填写密码和iv字符串,注意要确保16位的
		MagicCrypt mc = new MagicCrypt("****************", 128, "################");
		result = mc.decrypt(content);
	} catch(Exception ex) {
		ex.printStackTrace();
	}
	return result;
}

Android/Java版本的核心代码就这样了,可以到https://github.com/pkuoliver/EasyAES下载代码。

iOS版和php版本的也都大同小异,加上PKCS5Padding的实现即可,需要注意的是,php基于mcrypt模块,因此要先安装mcrypt模块,然后在php.ini中启用。

需要源码的可以到本人的github中下载,如有错误,欢迎指正。

本文的参考资料如下,感谢这些无私奉献的人:

高级加密标准AES的工作模式(ECB、CBC、CFB、OFB)

AES五种加密模式(CBC、ECB、CTR、OCF、CFB)

1 条关于 “AES加密,Android, iOS, PHP三平台兼容互通” 的评论

发表评论