Android和IOS关于RSA加密以及服务端解密的研究实现


        一、  密钥对的生成

RSA加密解密,类似于支付宝中的加解密功能,以前的app使用的是DES加密即对称加密算法,只需要一个密钥;而采用RSA实现加解密需要一个密钥对,即公钥和私钥。所以首先要做的操作是生成一个密钥对,在window 7环境下,这里借用支付宝demo中的openssl命令行工具,毕竟是通用的,密钥对的生成流程大致如下:


1、生成RSA私钥

<span style="white-space:pre">	</span>genrsa -out rsa_private_key.pem 1024

2、将RSA私钥转换成PKCS8格式,然后在命令行模式下复制到txt文件,供最后解密使用(服务端使用pem私钥解密)

<span style="white-space:pre">	</span>(1)pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt
	(2)pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -out rsa_private_key_pkcs8.pem -nocrypt

3、生成RSA pem格式公钥(Android使用pem公钥加密)
<span style="white-space:pre">	</span>rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem

4、根据私钥(注:或者是pkcs8编码下的pem,即2(2))生成csr文件,这里面会输入相关地址及公司密码信息等

<span style="white-space:pre">	</span>(1)req -new -key rsa_private_key.pem -out company.csr
<pre name="code" class="java"><span style="white-space:pre">	</span>(2)req -new -key rsa_private_key_pkcs8.pem -out company.csr



5、根据私钥(注:可能是2(2))以及csr文件生成一个10年有效期的der格式公钥(IOS使用der公钥加密)

<span style="white-space:pre">	</span>x509 -req -in company.csr -out rsa_public_key.der -outform der -signkey rsa_private_key.pem -days 3650


二、Android加密过程的实现

加密使用公钥,不过Android使用的是pem公钥,IOS使用的是der公钥,以下是Android平台下加密方法,把一个字符串用公钥加密后得到一个byte数组,然后使用base64编码得到一个字符串返回,作为传递给服务端的参数(声明:encryptByPublicKey这个方法不是原创)

<span style="white-space:pre">	</span>public static String toEncryptStr(String param) {
		// TODO Auto-generated method stub
		try {
			System.out.println("加密前:" + param);
			byte[] data = param.getBytes();
			byte[] encodedData = encryptByPublicKey(data,
					RSAConfig.RSA_PUBLIC);
			String encryptStr = Base64Utils.encode(encodedData);
			System.out.println("加密后:" + encryptStr);
			return encryptStr;
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}
	}

	public static byte[] encryptByPublicKey(byte[] data, String publicKey)
			throws Exception {
		byte[] keyBytes = Base64Utils.decode(publicKey);
		X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
		KeyFactory keyFactory = KeyFactory.getInstance("RSA",
				new org.bouncycastle.jce.provider.BouncyCastleProvider());
		Key publicK = keyFactory.generatePublic(x509KeySpec);
		// 对数据加密
		Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm(),
				new org.bouncycastle.jce.provider.BouncyCastleProvider());
		cipher.init(Cipher.ENCRYPT_MODE, publicK);
		int inputLen = data.length;
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		int offSet = 0;
		byte[] cache;
		int i = 0;
		// 对数据分段加密
		while (inputLen - offSet > 0) {
			if (inputLen - offSet > 117) {
				cache = cipher.doFinal(data, offSet, 117);
			} else {
				cache = cipher.doFinal(data, offSet, inputLen - offSet);
			}
			out.write(cache, 0, cache.length);
			i++;
			offSet = i * 117;
		}
		byte[] encryptedData = out.toByteArray();
		out.close();
		return encryptedData;
	}


三、服务端解密过程的实现

解密使用私钥,正好和加密的流程相反,不过目前技术水平来说,只能不同平台分开解密

	public static String toDecryptStr(String param) {
		// TODO Auto-generated method stub
		try {
			System.out.println("解密前:" + param);
			byte[] data = Base64Utils.decode(param);
			byte[] decodedData = decryptByPrivateKeyForAndroid(data,
					RSAConfig.RSA_PRIVATE);
			String target = new String(decodedData, "utf-8");
			System.out.println("解密后:" + target);
			return target;
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}
	}

	public static byte[] decryptByPrivateKeyForAndroid(byte[] encryptedData,
			String privateKey) throws Exception {
		byte[] keyBytes = Base64Utils.decode(privateKey);
		PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
		KeyFactory keyFactory = KeyFactory.getInstance("RSA",
				new org.bouncycastle.jce.provider.BouncyCastleProvider());
		Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
		Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm(),
				new org.bouncycastle.jce.provider.BouncyCastleProvider());
		cipher.init(Cipher.DECRYPT_MODE, privateK);
		int inputLen = encryptedData.length;
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		int offSet = 0;
		byte[] cache;
		int i = 0;
		// 对数据分段解密
		while (inputLen - offSet > 0) {
			if (inputLen - offSet > 128) {
				cache = cipher.doFinal(encryptedData, offSet, 128);
			} else {
				cache = cipher
						.doFinal(encryptedData, offSet, inputLen - offSet);
			}
			out.write(cache, 0, cache.length);
			i++;
			offSet = i * 128;
		}
		byte[] decryptedData = out.toByteArray();
		out.close();
		return decryptedData;
	}

	public static byte[] decryptByPrivateKeyForIOS(byte[] encryptedData,
			String privateKey) throws Exception {
		byte[] keyBytes = Base64Utils.decode(privateKey);
		PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
		KeyFactory keyFactory = KeyFactory.getInstance("RSA");
		Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
		Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
		cipher.init(Cipher.DECRYPT_MODE, privateK);
		int inputLen = encryptedData.length;
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		int offSet = 0;
		byte[] cache;
		int i = 0;
		// 对数据分段解密
		while (inputLen - offSet > 0) {
			if (inputLen - offSet > 128) {
				cache = cipher.doFinal(encryptedData, offSet, 128);
			} else {
				cache = cipher
						.doFinal(encryptedData, offSet, inputLen - offSet);
			}
			out.write(cache, 0, cache.length);
			i++;
			offSet = i * 128;
		}
		byte[] decryptedData = out.toByteArray();
		out.close();
		return decryptedData;
	}

加解密过程中主要使用了两个第三方jar包:bcprov-jdk15-140.jar、javabase64-1.3.1.jar

结束语:大功告成,在借鉴各位大神提供的加解密思路以及方法的前提下,加上个人的不断调试,终于实现了加解密过程;

附录:参考博文地址

java中RSA加解密的实现 http://www.open-open.com/lib/view/open1388369746625.html
Android RSA加密解密 http://blog.csdn.net/BBLD_/article/details/38777491
java与IOS之间的RSA加解密 http://yuur369.iteye.com/blog/1769395
ios下使用rsa算法与php进行加解密通讯 http://blog.yorkgu.me/2011/10/27/rsa-in-ios-using-publick-key-generated-by-openssl/
java中RSA加解密的实现 http://blog.csdn.net/centralperk/article/details/8558678
android和java webservice RSA处理的不同 http://blog.sina.com.cn/s/blog_4bce4aa301011p8x.html
OpenSSL小结http://www.cnblogs.com/phpinfo/archive/2013/08/09/3246376.html

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。