rsa非对称加解密,java服务器端对应android、IOS客户端以及javaScript的加解密

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/KokJuis/article/details/53886166

 

很多朋友开发项目时会用到加解密,像MD5SHAHMAC、AES、DES、RSA等等算法。不同的加密算法有不同的使用场景。本文只介绍RSA非对称加密,需要了解其他加密算法的朋友可以自行百度一下。

 

前言

由于网上很多资料基本都是单讲一种环境下的RSA加解密,基本没有介绍在不同客户端环境下的整合。虽然我们可以找不同的资料去探索,但未免会浪费大量时间,特别是不熟悉其他开发语言环境的朋友,弄起来就比较蛋疼了。所以本文就介绍JAVA服务器端与android客户端,IOS客户端,以及在web上用javaScript 互相加解密的情况。希望对大家有所帮助。

 

首先还是介绍一下RSA算法的特点:

RSA:由RSA公司发明,是一个支持变长密钥的公共密钥算法,需要加密的文件块的长度也是可变的。RSA算法是非对称加密算法的典型代表,既能加密、又能解密。

和对称加密算法比如DES的明显区别在于,DES加解密使用的密钥是一样的,只要你知道密钥就能解密,而RSA用于加密、解密的密钥是不同的,分为公钥和私钥。使用公钥加密的信息只能用私钥解密,使用私钥的加密的信息只能使用公钥解密,并且每次加密的密文都是不一样的。

我们可以把私钥保存在服务器端,而把公钥发送给客户端使用。可以这么说,使用RSA算法,只要密钥足够长(一般默认要求1024bit)。加密后的信息在不知道密钥的情况下是基本不可能被破解的。

我们一般把RSA加密用在一些安全要求比较高的信息传输上,比如注册或者登录的帐号密码可以加密。但需要注意的是,虽然RSA加密安全性比较高,但加密速度比较慢(相对的,其实对于一般字符串,瞬间就完成了),一般我们只用在加密比较小的数据上,如果是比较大的数据。用DES加密会合适一点。

注:大部分情况下,客户端和服务器端通过RSA进行加解密,最好是用两套密钥。交叉相互加解密(客户端公钥加密->服务器私钥解密。服务器公钥加密->客户端私钥解密),我这里偷懒,只用一套(公钥加密->私钥解密,私钥加密->公钥解密)。除非你只是加密少量的东西。如果使用很频繁,建议还是两套交叉,避免后面有拓展性问题

言归正传,现在我们来捣鼓一下:(这里只介绍已经生成好密钥的情况)

1、获取密钥

使用RSA加密,首先我们需要获取密钥,获取密钥有几种方式,一种是直接使用JDK自带的工具类获取,一种是使用openssl工具来生成密钥。我们这里介绍使用openssl生成密钥,我这里已经上传了相关工具,使用方法也已经打包在里面,需要的朋友可以前往下载:http://download.csdn.net/detail/kokjuis/9721404 点击打开链接

 

 

 

RSA密钥生成命令
生成RSA私钥
openssl>genrsa -out rsa_private_key.pem 1024
生成RSA公钥
openssl>rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
将RSA私钥转换成PKCS8格式
openssl>pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt

注意:“>”符号后面的才是需要输入的命令。


生成密钥操作比较简单,直接cd 到bin 目录执行命令就可以了。

 

 

得到的密钥形式大概是这样的:

私钥:

公钥:

私钥pcks8格式:(不用问为什么要转成pcks8,就是要这样干的)

 

 

到这里密钥我们就已经得到了。

 

2、在java服务器端加解密

 

首先我是用了一个 rsa_key.properties保存生成好的密钥,便于管理,注意,密钥只取中间那段,并且不能有换行,我们要把生成的密钥手动删除换行符。如下图:

 

 

下面是JAVA服务器端使用的加密工具类,看代码,不多解释了:

需要依赖一个的jar,主要是为了兼容安卓和IOS客户端,http://download.csdn.net/detail/kokjuis/9721482点击打开链接

 

RsaEncryptUtil:

 

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.security.Key;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Security;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Properties;

import javax.crypto.Cipher;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

/**
 * RSA非对称加密解密工具类
 * 
 * @ClassName RsaEncryptUtil
 * @author kokjuis 189155278@qq.com
 * @date 2016-4-6
 * @content
 */
public class RsaEncryptUtil {

	/** */
	/**
	 * 加密算法RSA
	 */
	public static final String KEY_ALGORITHM = "RSA";// RSA/ECB/PKCS1Padding

	/**
	 * String to hold name of the encryption padding.
	 */
	public static final String PADDING = "RSA/NONE/PKCS1Padding";// RSA/NONE/NoPadding

	/**
	 * String to hold name of the security provider.
	 */
	public static final String PROVIDER = "BC";

	/** */
	/**
	 * 签名算法
	 */
	public static final String SIGNATURE_ALGORITHM = "MD5withRSA";

	/** */
	/**
	 * 获取公钥的key
	 */
	private static final String PUBLIC_KEY = "rsa_public_key";

	/** */
	/**
	 * 获取私钥的key
	 */
	private static final String PRIVATE_KEY = "rsa_private_pkcs8";

	/** */
	/**
	 * RSA最大加密明文大小
	 */
	private static final int MAX_ENCRYPT_BLOCK = 117;

	/** */
	/**
	 * RSA最大解密密文大小
	 */
	private static final int MAX_DECRYPT_BLOCK = 128;

	/*
	 * 公钥加密
	 */
	public static String encryptByPublicKey(String str) throws Exception {
		Security.addProvider(new BouncyCastleProvider());

		Cipher cipher = Cipher.getInstance(PADDING, PROVIDER);

		// 获得公钥
		Key publicKey = getPublicKey();

		// 用公钥加密
		cipher.init(Cipher.ENCRYPT_MODE, publicKey);
		// 读数据源
		byte[] data = str.getBytes("UTF-8");

		int inputLen = data.length;
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		int offSet = 0;
		byte[] cache;
		int i = 0;
		// 对数据分段加密
		while (inputLen - offSet > 0) {
			if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
				cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
			} else {
				cache = cipher.doFinal(data, offSet, inputLen - offSet);
			}
			out.write(cache, 0, cache.length);
			i++;
			offSet = i * MAX_ENCRYPT_BLOCK;
		}
		byte[] encryptedData = out.toByteArray();
		out.close();

		return Base64Util.encode(encryptedData);
	}

	/**
	 * 私钥加密
	 * 
	 * @param str
	 * @return
	 * @throws Exception
	 * @author kokJuis
	 * @date 2016-4-7 下午12:53:15
	 * @comment
	 */
	public static String encryptByPrivateKey(String str) throws Exception {

		Security.addProvider(new BouncyCastleProvider());

		Cipher cipher = Cipher.getInstance(PADDING, PROVIDER);

		// 获得私钥
		Key privateKey = getPrivateKey();

		// 用私钥加密
		cipher.init(Cipher.ENCRYPT_MODE, privateKey);
		// 读数据源
		byte[] data = str.getBytes("UTF-8");

		int inputLen = data.length;
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		int offSet = 0;
		byte[] cache;
		int i = 0;
		// 对数据分段加密
		while (inputLen - offSet > 0) {
			if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
				cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
			} else {
				cache = cipher.doFinal(data, offSet, inputLen - offSet);
			}
			out.write(cache, 0, cache.length);
			i++;
			offSet = i * MAX_ENCRYPT_BLOCK;
		}
		byte[] encryptedData = out.toByteArray();
		out.close();

		return Base64Util.encode(encryptedData);
	}

	/*
	 * 公钥解密
	 */
	public static String decryptByPublicKey(String str) throws Exception {
		Security.addProvider(new BouncyCastleProvider());

		Cipher cipher = Cipher.getInstance(PADDING, PROVIDER);

		// 获得公钥
		Key publicKey = getPublicKey();

		// 用公钥解密
		cipher.init(Cipher.DECRYPT_MODE, publicKey);

		// 读数据源
		byte[] encryptedData = Base64Util.decode(str);

		int inputLen = encryptedData.length;
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		int offSet = 0;
		byte[] cache;
		int i = 0;
		// 对数据分段解密
		while (inputLen - offSet > 0) {
			if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
				cache = cipher
						.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
			} else {
				cache = cipher
						.doFinal(encryptedData, offSet, inputLen - offSet);
			}
			out.write(cache, 0, cache.length);
			i++;
			offSet = i * MAX_DECRYPT_BLOCK;
		}
		byte[] decryptedData = out.toByteArray();
		out.close();

		return new String(decryptedData, "UTF-8");
	}

	/*
	 * 私钥解密
	 */
	public static String decryptByPrivateKey(String str) throws Exception {

		Security.addProvider(new BouncyCastleProvider());

		Cipher cipher = Cipher.getInstance(PADDING, PROVIDER);
		// 得到Key
		Key privateKey = getPrivateKey();
		// 用私钥去解密
		cipher.init(Cipher.DECRYPT_MODE, privateKey);
		// 读数据源
		byte[] encryptedData = Base64Util.decode(str);

		int inputLen = encryptedData.length;
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		int offSet = 0;
		byte[] cache;
		int i = 0;
		// 对数据分段解密
		while (inputLen - offSet > 0) {
			if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
				cache = cipher
						.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
			} else {
				cache = cipher
						.doFinal(encryptedData, offSet, inputLen - offSet);
			}
			out.write(cache, 0, cache.length);
			i++;
			offSet = i * MAX_DECRYPT_BLOCK;
		}
		byte[] decryptedData = out.toByteArray();
		out.close();

		// 二进制数据要变成字符串需解码
		return new String(decryptedData, "UTF-8");
	}

	/**
	 * 从文件中读取公钥
	 * 
	 * @return
	 * @throws Exception
	 * @author kokJuis
	 * @date 2016-4-6 下午4:38:22
	 * @comment
	 */
	private static Key getPublicKey() throws Exception {
		InputStream stream = Thread.currentThread().getContextClassLoader()
				.getResourceAsStream("rsa_key.properties");
		Properties properties = new Properties();
		properties.load(stream);

		String key = properties.getProperty(PUBLIC_KEY);

		byte[] keyBytes;
		keyBytes = Base64Util.decode(key);
		X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
		KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
		PublicKey publicKey = keyFactory.generatePublic(keySpec);
		return publicKey;
	}

	/**
	 * 从文件中读取公钥String
	 * 
	 * @return
	 * @throws Exception
	 * @author kokJuis
	 * @date 2016-4-6 下午4:38:22
	 * @comment
	 */
	public static String getStringPublicKey() throws Exception {
		InputStream stream = Thread.currentThread().getContextClassLoader()
				.getResourceAsStream("rsa_key.properties");
		Properties properties = new Properties();
		properties.load(stream);

		String key = properties.getProperty(PUBLIC_KEY);

		return key;
	}

	/**
	 * 获取私钥
	 * 
	 * @return
	 * @throws Exception
	 * @author kokJuis
	 * @date 2016-4-7 上午11:46:12
	 * @comment
	 */
	private static Key getPrivateKey() throws Exception {

		InputStream stream = Thread.currentThread().getContextClassLoader()
				.getResourceAsStream("rsa_key.properties");
		Properties properties = new Properties();
		properties.load(stream);

		String key = properties.getProperty(PRIVATE_KEY);

		byte[] keyBytes;
		keyBytes = Base64Util.decode(key);
		PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
		KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
		PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
		return privateKey;
	}

}


Base64Util:

 

 

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;

import com.sun.org.apache.xml.internal.security.utils.Base64;

/**
 * 
 * @ClassName Base64Util
 * @author kokjuis 189155278@qq.com
 * @date 2016-4-7
 * @content
 */
public class Base64Util {

	/** */
	/**
	 * 文件读取缓冲区大小
	 */
	private static final int CACHE_SIZE = 1024;

	/** */
	/**
	 * <p>
	 * BASE64字符串解码为二进制数据
	 * </p>
	 * 
	 * @param base64
	 * @return
	 * @throws Exception
	 */
	public static byte[] decode(String base64) throws Exception {
		return Base64.decode(base64.getBytes());
	}

	/** */
	/**
	 * <p>
	 * 二进制数据编码为BASE64字符串
	 * </p>
	 * 
	 * @param bytes
	 * @return
	 * @throws Exception
	 */
	public static String encode(byte[] bytes) throws Exception {
		return new String(Base64.encode(bytes));
	}

	/** */
	/**
	 * <p>
	 * 将文件编码为BASE64字符串
	 * </p>
	 * <p>
	 * 大文件慎用,可能会导致内存溢出
	 * </p>
	 * 
	 * @param filePath
	 *            文件绝对路径
	 * @return
	 * @throws Exception
	 */
	public static String encodeFile(String filePath) throws Exception {
		byte[] bytes = fileToByte(filePath);
		return encode(bytes);
	}

	/** */
	/**
	 * <p>
	 * BASE64字符串转回文件
	 * </p>
	 * 
	 * @param filePath
	 *            文件绝对路径
	 * @param base64
	 *            编码字符串
	 * @throws Exception
	 */
	public static void decodeToFile(String filePath, String base64)
			throws Exception {
		byte[] bytes = decode(base64);
		byteArrayToFile(bytes, filePath);
	}

	/** */
	/**
	 * <p>
	 * 文件转换为二进制数组
	 * </p>
	 * 
	 * @param filePath
	 *            文件路径
	 * @return
	 * @throws Exception
	 */
	public static byte[] fileToByte(String filePath) throws Exception {
		byte[] data = new byte[0];
		File file = new File(filePath);
		if (file.exists()) {
			FileInputStream in = new FileInputStream(file);
			ByteArrayOutputStream out = new ByteArrayOutputStream(2048);
			byte[] cache = new byte[CACHE_SIZE];
			int nRead = 0;
			while ((nRead = in.read(cache)) != -1) {
				out.write(cache, 0, nRead);
				out.flush();
			}
			out.close();
			in.close();
			data = out.toByteArray();
		}
		return data;
	}

	/** */
	/**
	 * <p>
	 * 二进制数据写文件
	 * </p>
	 * 
	 * @param bytes
	 *            二进制数据
	 * @param filePath
	 *            文件生成目录
	 */
	public static void byteArrayToFile(byte[] bytes, String filePath)
			throws Exception {
		InputStream in = new ByteArrayInputStream(bytes);
		File destFile = new File(filePath);
		if (!destFile.getParentFile().exists()) {
			destFile.getParentFile().mkdirs();
		}
		destFile.createNewFile();
		OutputStream out = new FileOutputStream(destFile);
		byte[] cache = new byte[CACHE_SIZE];
		int nRead = 0;
		while ((nRead = in.read(cache)) != -1) {
			out.write(cache, 0, nRead);
			out.flush();
		}
		out.close();
		in.close();
	}

}

 

3、android客户端加解密:

 

安卓跟java非常类似了,只是方法有点不一样,另外就是安卓上base64编码需要额外添加一个jar ,因为安卓上的SDK跟J2EE上还是有些区别的。安卓SDK没有自带的base64编码

 

依赖javabase64-1.3.1.jar  下载地址:http://download.csdn.net/detail/kokjuis/9721502 点击打开链接

 

RsaEncryptUtil:

 

 

import java.io.ByteArrayOutputStream;
import java.security.Key;
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.Cipher;

import com.kokjuis.travel.comm.Constant;

/**
 * RSA非对称加密解密工具类
 * 
 * @ClassName RsaEncryptUtil
 * @author kokjuis 189155278@qq.com
 * @date 2016-4-6
 * @content
 */
public class RsaEncryptUtil {

	/** */
	/**
	 * 加密算法RSA
	 */
	public static final String KEY_ALGORITHM = "RSA";// RSA/NONE/NoPadding,RSA/NONE/PKCS1Padding

	/**
	 * String to hold name of the encryption padding.
	 */
	public static final String PADDING = "RSA/NONE/PKCS1Padding";// RSA/NONE/NoPadding

	/**
	 * String to hold name of the security provider.
	 */
	public static final String PROVIDER = "BC";

	/** */
	/**
	 * 签名算法
	 */
	public static final String SIGNATURE_ALGORITHM = "MD5withRSA";

	/** */
	/**
	 * 获取公钥的key
	 */
	private static final String PUBLIC_KEY = "RSAPublicKey";

	/** */
	/**
	 * 获取私钥的key
	 */
	private static final String PRIVATE_KEY = "RSAPrivateKey";

	/** */
	/**
	 * RSA最大加密明文大小
	 */
	private static final int MAX_ENCRYPT_BLOCK = 117;

	/** */
	/**
	 * RSA最大解密密文大小
	 */
	private static final int MAX_DECRYPT_BLOCK = 128;

	/*
	 * 公钥加密
	 */
	public static String encryptByPublicKey(String str) throws Exception {

		Cipher cipher = Cipher.getInstance(PADDING, PROVIDER);
		// 获得公钥
		Key publicKey = getPublicKey();

		// 用公钥加密
		cipher.init(Cipher.ENCRYPT_MODE, publicKey);
		// 读数据源
		byte[] data = str.getBytes("UTF-8");

		int inputLen = data.length;
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		int offSet = 0;
		byte[] cache;
		int i = 0;
		// 对数据分段加密
		while (inputLen - offSet > 0) {
			if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
				cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
			} else {
				cache = cipher.doFinal(data, offSet, inputLen - offSet);
			}
			out.write(cache, 0, cache.length);
			i++;
			offSet = i * MAX_ENCRYPT_BLOCK;
		}
		byte[] encryptedData = out.toByteArray();
		out.close();

		return Base64Util.encode(encryptedData);
	}

	/*
	 * 公钥解密
	 */
	public static String decryptByPublicKey(String str) throws Exception {
		Cipher cipher = Cipher.getInstance(PADDING, PROVIDER);

		// 获得公钥
		Key publicKey = getPublicKey();

		// 用公钥解密
		cipher.init(Cipher.DECRYPT_MODE, publicKey);

		// 读数据源
		byte[] encryptedData = Base64Util.decode(str);

		int inputLen = encryptedData.length;
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		int offSet = 0;
		byte[] cache;
		int i = 0;
		// 对数据分段解密
		while (inputLen - offSet > 0) {
			if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
				cache = cipher
						.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
			} else {
				cache = cipher
						.doFinal(encryptedData, offSet, inputLen - offSet);
			}
			out.write(cache, 0, cache.length);
			i++;
			offSet = i * MAX_DECRYPT_BLOCK;
		}
		byte[] decryptedData = out.toByteArray();
		out.close();

		return new String(decryptedData, "UTF-8");
	}

	/**
	 * 读取公钥
	 * 
	 * @return
	 * @throws Exception
	 * @author kokJuis
	 * @date 2016-4-6 下午4:38:22
	 * @comment
	 */
	private static Key getPublicKey() throws Exception {

		String key = Constant.rsa_public_key;

		byte[] keyBytes;
		keyBytes = Base64Util.decode(key);
		X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
		KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
		PublicKey publicKey = keyFactory.generatePublic(keySpec);
		return publicKey;
	}

}


Base64Util:

 

 

 

import it.sauronsoftware.base64.Base64;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;

/**
 * * BASE64编码解码工具包 依赖javabase64-1.3.1.jar
 * 
 * @ClassName Base64Util
 * @author kokjuis 189155278@qq.com
 * @date 2016-4-7
 * @content
 */
public class Base64Util {

	/** */
	/**
	 * 文件读取缓冲区大小
	 */
	private static final int CACHE_SIZE = 1024;

	/** */
	/**
	 * <p>
	 * BASE64字符串解码为二进制数据
	 * </p>
	 * 
	 * @param base64
	 * @return
	 * @throws Exception
	 */
	public static byte[] decode(String base64) throws Exception {
		return Base64.decode(base64.getBytes());
	}

	/** */
	/**
	 * <p>
	 * 二进制数据编码为BASE64字符串
	 * </p>
	 * 
	 * @param bytes
	 * @return
	 * @throws Exception
	 */
	public static String encode(byte[] bytes) throws Exception {
		return new String(Base64.encode(bytes));
	}

	/** */
	/**
	 * <p>
	 * 将文件编码为BASE64字符串
	 * </p>
	 * <p>
	 * 大文件慎用,可能会导致内存溢出
	 * </p>
	 * 
	 * @param filePath
	 *            文件绝对路径
	 * @return
	 * @throws Exception
	 */
	public static String encodeFile(String filePath) throws Exception {
		byte[] bytes = fileToByte(filePath);
		return encode(bytes);
	}

	/** */
	/**
	 * <p>
	 * BASE64字符串转回文件
	 * </p>
	 * 
	 * @param filePath
	 *            文件绝对路径
	 * @param base64
	 *            编码字符串
	 * @throws Exception
	 */
	public static void decodeToFile(String filePath, String base64)
			throws Exception {
		byte[] bytes = decode(base64);
		byteArrayToFile(bytes, filePath);
	}

	/** */
	/**
	 * <p>
	 * 文件转换为二进制数组
	 * </p>
	 * 
	 * @param filePath
	 *            文件路径
	 * @return
	 * @throws Exception
	 */
	public static byte[] fileToByte(String filePath) throws Exception {
		byte[] data = new byte[0];
		File file = new File(filePath);
		if (file.exists()) {
			FileInputStream in = new FileInputStream(file);
			ByteArrayOutputStream out = new ByteArrayOutputStream(2048);
			byte[] cache = new byte[CACHE_SIZE];
			int nRead = 0;
			while ((nRead = in.read(cache)) != -1) {
				out.write(cache, 0, nRead);
				out.flush();
			}
			out.close();
			in.close();
			data = out.toByteArray();
		}
		return data;
	}

	/** */
	/**
	 * <p>
	 * 二进制数据写文件
	 * </p>
	 * 
	 * @param bytes
	 *            二进制数据
	 * @param filePath
	 *            文件生成目录
	 */
	public static void byteArrayToFile(byte[] bytes, String filePath)
			throws Exception {
		InputStream in = new ByteArrayInputStream(bytes);
		File destFile = new File(filePath);
		if (!destFile.getParentFile().exists()) {
			destFile.getParentFile().mkdirs();
		}
		destFile.createNewFile();
		OutputStream out = new FileOutputStream(destFile);
		byte[] cache = new byte[CACHE_SIZE];
		int nRead = 0;
		while ((nRead = in.read(cache)) != -1) {
			out.write(cache, 0, nRead);
			out.flush();
		}
		out.close();
		in.close();
	}

}

 

4、IOS客户端加解密:

 

ios于java进行RSA加解密就比较蛋疼了,为什么呢?原因是因为IOS系统本身自带的RSA加密类有个很让人蛋疼的特性,就是只  能用公钥加密,私钥解密的方式,而反过来私钥加密,公钥解密就不行了。

所以很多朋友就会出现这样的情况,在IOS客户端用公钥加密的数据传到JAVA服务器端用私钥解密没有问题。但反过来在java服务器端用私钥加密的数据传到IOS客户端用公钥解密,就报-9809或-50的错误。

很多朋友网上找呀找呀,死活找不到解决案例。这不我开始也遇到这样的问题,最后用了下openssl,使用openssl库解决了这个问题。使用openssl既可以使用公钥加密,也可以使用私钥进行加密,而且与java的加解密的结果相同。下面我们就一起来捣鼓一下吧。

这里提供两种方式,第一种是使用openssl的包,但是这种会让工程体积很大。第二种是自己实现RSA,这里提供两种方式,推荐第二种,往下看。

第一种:

在IOS上要使用openssl需要先编译openssl的库才能使用,我这里已经编译好了直接下载就可以使用,http://download.csdn.net/detail/kokjuis/9723109 点击打开链接

下载完以后解压,然后导入到你的xcode工程中

 

然后在build settings的Header Search Paths里面引用 include路径,并且把Always Search User Paths设置为Yes,如图:

 

 

 

然后在 Library Search Paths 引用lib目录。一般导入以后XCODE会自动引用的,如果没有引用,自己手动引用一下。

 

 

到这里就基本能正常使用openssl库的加解密功能了,下面是我写的一个工具类,可以参考一下,是用OC语言写的,想用swift写的话也很简单,可以自己转换一下,这里不折腾了:

RsaUtil.h:

 

//
//  IOS使用OpenSSL 生成的公私玥字符串进行RSA加解密
//  RsaUtil.h
//
//  Created by kokjuis on 16/8/19.
//
//

#import <Foundation/Foundation.h>
#import <openssl/rsa.h>
#import <openssl/pem.h>

@interface RsaUtil : NSObject


/*
 注意,RSA加解密的特征是:公钥加密->私钥解密、私钥加密->公钥解密。
 */

+(NSString *) encryptString:(NSString *)content withPublicKey:(NSString *)publicKey;//公钥加密
+(NSString *) decryptString:(NSString *)encryptContent withPublicKey:(NSString *)publicKey;//公钥解密

+(NSString *) encryptString:(NSString *)content withPrivateKey:(NSString *)privateKey;//私钥加密
+(NSString *) decryptString:(NSString *)encryptContent withPrivateKey:(NSString *)privateKey;//私钥解密

@end

 

 

 

 

 

 

 

 

RsaUtil.m:这里加密后的数据为了便于传输用了base64编码,这里用的是GTMBase64这个类库,可以用Pods导入,怎么导入不介绍了,你也可以使用系统自带的库编码,一样的。

 

 

//
//  RsaUtil.m
//  BestTravel
//
//  Created by kokjuis on 16/8/19.
//
//

#import "RsaUtil.h"
#import <Security/Security.h>
//#import "GTMBase64.h"

@implementation RsaUtil


#pragma mark -通过公私钥字符串生成公私钥
//通过公钥生成key
+(RSA *)createRsaKeyWithPublicKey:(NSString *) publicKey{
    
    
    //为了避免写法的不同意,如果公钥已经带有下面标记字符,先去除,后面再统一加上固定格式
    NSRange spos = [publicKey rangeOfString:@"-----BEGIN PUBLIC KEY-----"];
    NSRange epos = [publicKey rangeOfString:@"-----END PUBLIC KEY-----"];
    if(spos.location != NSNotFound && epos.location != NSNotFound){
        NSUInteger s = spos.location + spos.length;
        NSUInteger e = epos.location;
        NSRange range = NSMakeRange(s, e-s);
        publicKey = [publicKey substringWithRange:range];
    }
    
    //除去换行符,空格等
    publicKey = [publicKey stringByReplacingOccurrencesOfString:@"\r" withString:@""];
    publicKey = [publicKey stringByReplacingOccurrencesOfString:@"\n" withString:@""];
    publicKey = [publicKey stringByReplacingOccurrencesOfString:@"\t" withString:@""];
    publicKey = [publicKey stringByReplacingOccurrencesOfString:@" "  withString:@""];
    
    // ras公钥
    NSMutableString * rsa_public_key = [[NSMutableString alloc]initWithString:publicKey];
    
    //从内存中读取,公钥字符串开头要加上“-----BEGIN PUBLIC KEY-----\n”,结尾加上“\n-----END PUBLIC KEY-----\n”。否则会出现error:0906D06C:PEM routines:PEM_read_bio:no start line
    [rsa_public_key insertString:@"-----BEGIN PUBLIC KEY-----\n" atIndex:0];
    [rsa_public_key appendString:@"\n-----END PUBLIC KEY-----\n"];
    
    BIO *bio = NULL;
    const char * chPublicKey =[rsa_public_key UTF8String];
    if ((bio = BIO_new_mem_buf(chPublicKey, -1)) == NULL)       //从字符串读取RSA公钥
    {
        return nil;
    }
    
    RSA *rsa = PEM_read_bio_RSA_PUBKEY(bio, NULL, NULL, NULL);   //从bio结构中得到rsa结构
    
    return rsa;
    
}

//通过私钥生成key
+(RSA *)createRsaKeyWithPrivateKey:(NSString *) privateKey{
    
    
    //为了避免写法的不同意,如果私钥已经带有下面标记字符,先去除,后面再统一加上固定格式
    NSRange spos = [privateKey rangeOfString:@"-----BEGIN RSA PRIVATE KEY-----"];
    NSRange epos = [privateKey rangeOfString:@"-----END RSA PRIVATE KEY-----"];
    if(spos.location != NSNotFound && epos.location != NSNotFound){
        NSUInteger s = spos.location + spos.length;
        NSUInteger e = epos.location;
        NSRange range = NSMakeRange(s, e-s);
        privateKey = [privateKey substringWithRange:range];
    }
    
    //除去换行符,空格等
    privateKey = [privateKey stringByReplacingOccurrencesOfString:@"\r" withString:@""];
    privateKey = [privateKey stringByReplacingOccurrencesOfString:@"\n" withString:@""];
    privateKey = [privateKey stringByReplacingOccurrencesOfString:@"\t" withString:@""];
    privateKey = [privateKey stringByReplacingOccurrencesOfString:@" "  withString:@""];

    
    // ras私钥
    NSMutableString * rsa_private_key = [[NSMutableString alloc]initWithString:privateKey];
    
    //从内存中读取,公钥字符串开头要加上“-----BEGIN RSA PRIVATE KEY-----\n”,结尾加上“\n-----END RSA PRIVATE KEY-----\n”。否则会出现error:0906D06C:PEM routines:PEM_read_bio:no start line
    [rsa_private_key insertString:@"-----BEGIN RSA PRIVATE KEY-----\n" atIndex:0];
    [rsa_private_key appendString:@"\n-----END RSA PRIVATE KEY-----\n"];
    
    
    BIO *bio = NULL;
    const char * chPrivateKey =[rsa_private_key UTF8String];
    if ((bio = BIO_new_mem_buf(chPrivateKey, -1)) == NULL)       //从字符串读取RSA公钥
    {
        return nil;
    }

    RSA *rsa=PEM_read_bio_RSAPrivateKey(bio, NULL, NULL, NULL);
    
    return rsa;
    
}




#pragma mark -公钥加解密
//分段加密
+ (NSData *) encryptData:(NSData *)data withPublicRSA:(RSA *)publicRSA{
    
    //获取公钥
    if (!publicRSA) {
        return nil;
    }
    
    int publicRSALength = RSA_size(publicRSA);          //公钥长度
    double totalLength = [data length];                 //数据总长度
    int blockSize = publicRSALength - 12;                //数据分段大小
    int blockCount = ceil(totalLength / blockSize);     //分段个数
    size_t publicEncryptSize = publicRSALength;
    NSMutableData *encryptDate = [NSMutableData data];
    for (int i = 0; i < blockCount; i++) {
        NSUInteger loc = i * blockSize;
        int dataSegmentRealSize = MIN(blockSize, totalLength - loc);
        NSData *dataSegment = [data subdataWithRange:NSMakeRange(loc, dataSegmentRealSize)];
        char *publicEncrypt = malloc(publicRSALength);
        memset(publicEncrypt, 0, publicRSALength);
        const unsigned char *str = [dataSegment bytes];
        if(RSA_public_encrypt(blockSize,str,(unsigned char*)publicEncrypt,publicRSA,RSA_PKCS1_PADDING)>=0){
            NSData *encryptData = [[NSData alloc] initWithBytes:publicEncrypt length:publicEncryptSize];
            [encryptDate appendData:encryptData];
        }
        free(publicEncrypt);
    }
    RSA_free(publicRSA);
    
    return encryptDate;
}



//分段解密
+ (NSData *) decryptData:(NSData *)data withPublicRSA:(RSA *)publicRSA{
    
    if (!publicRSA) {
        return nil;
    }
   
    int publicRSALength = RSA_size(publicRSA);
    double totalLength = [data length];
    int blockSize = publicRSALength;
    int blockCount = ceil(totalLength / blockSize);
    NSMutableData *decrypeData = [NSMutableData data];
    for (int i = 0; i < blockCount; i++) {
        NSUInteger loc = i * blockSize;
        long dataSegmentRealSize = MIN(blockSize, totalLength - loc);
        NSData *dataSegment = [data subdataWithRange:NSMakeRange(loc, dataSegmentRealSize)];
        const unsigned char *str = [dataSegment bytes];
        unsigned char *privateDecrypt = malloc(publicRSALength);
        memset(privateDecrypt, 0, publicRSALength);
        if(RSA_public_decrypt(publicRSALength,str,privateDecrypt,publicRSA,RSA_PKCS1_PADDING)>=0){
            NSInteger length =strlen((char *)privateDecrypt);
            NSData *data = [[NSData alloc] initWithBytes:privateDecrypt length:length];
            [decrypeData appendData:data];
        }
        free(privateDecrypt);
    }
    
    RSA_free(publicRSA);
    
    return decrypeData;
}



#pragma 加密
+ (NSString *) encryptString:(NSString *)content withPublicKey:(NSString *)publicKey{
    //加密
    
    RSA *publicRSA=[self createRsaKeyWithPublicKey:publicKey];
    
    NSData *data=[self encryptData:[content dataUsingEncoding:NSUTF8StringEncoding] withPublicRSA:publicRSA];
    
    //NSData *encodeData=[GTMBase64 encodeData:data];
    NSData * encodeData = [data base64EncodedDataWithOptions:0];
    
    NSString * encrypotoResult= [[NSString alloc] initWithData:encodeData encoding:NSUTF8StringEncoding];
    
    return encrypotoResult;
}

#pragma 解密
+(NSString *) decryptString:(NSString *)encryptContent withPublicKey:(NSString *)publicKey{
    //解密
    
     RSA *publicRSA=[self createRsaKeyWithPublicKey:publicKey];
    
    //NSData *encodeData=[GTMBase64 decodeString:encryptContent];
     NSData *encodeData = [[NSData alloc] initWithBase64EncodedString:encryptContent options:NSDataBase64DecodingIgnoreUnknownCharacters];
    
    NSData *data=[self decryptData:encodeData withPublicRSA:publicRSA];
    NSString * decrypotoResult= [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    
    return decrypotoResult;
}



#pragma mark -私钥加解密

//私钥加密
+ (NSData *)encryptDate:(NSData *)data withPrivateRSA:(RSA *)privateRSA{
    
    if (!privateRSA) {
        return nil;
    }
    int privateRSALength = RSA_size(privateRSA);          //公钥长度
    double totalLength = [data length];                 //数据总长度
    int blockSize = privateRSALength - 12;                //数据分段大小
    int blockCount = ceil(totalLength / blockSize);     //分段个数
    size_t privateEncryptSize = privateRSALength;
    NSMutableData *encryptDate = [NSMutableData data];
    for (int i = 0; i < blockCount; i++) {
        NSUInteger loc = i * blockSize;
        int dataSegmentRealSize = MIN(blockSize, totalLength - loc);
        NSData *dataSegment = [data subdataWithRange:NSMakeRange(loc, dataSegmentRealSize)];
        char *publicEncrypt = malloc(privateRSALength);
        memset(publicEncrypt, 0, privateRSALength);
        const unsigned char *str = [dataSegment bytes];
        if(RSA_private_encrypt(dataSegmentRealSize,str,(unsigned char*)publicEncrypt,privateRSA,RSA_PKCS1_PADDING)>=0){
            NSData *encryptData = [[NSData alloc] initWithBytes:publicEncrypt length:privateEncryptSize];
            [encryptDate appendData:encryptData];
        }
        free(publicEncrypt);
    }
    RSA_free(privateRSA);
    return encryptDate;
}

//私钥解密
+ (NSData *)decryptData:(NSData *)data withPrivateRSA:(RSA *)privateRSA {
    
    if (!privateRSA) {
        return nil;
    }
    
    int privateRSALenght = RSA_size(privateRSA);
    double totalLength = [data length];
    int blockSize = privateRSALenght;
    int blockCount = ceil(totalLength / blockSize);
    NSMutableData *decrypeData = [NSMutableData data];
    for (int i = 0; i < blockCount; i++) {
        NSUInteger loc = i * blockSize;
        long dataSegmentRealSize = MIN(blockSize, totalLength - loc);
        NSData *dataSegment = [data subdataWithRange:NSMakeRange(loc, dataSegmentRealSize)];
        const unsigned char *str = [dataSegment bytes];
        unsigned char *privateDecrypt = malloc(privateRSALenght);
        memset(privateDecrypt, 0, privateRSALenght);
        if(RSA_private_decrypt(privateRSALenght,str,privateDecrypt,privateRSA,RSA_PKCS1_PADDING)>=0){
            NSInteger length =strlen((char *)privateDecrypt);
            NSData *data = [[NSData alloc] initWithBytes:privateDecrypt length:length];
            [decrypeData appendData:data];
            
        }
        free(privateDecrypt);
    }
    
    RSA_free(privateRSA);
    return decrypeData;
}



#pragma 加密
+ (NSString *) encryptString:(NSString *)content withPrivateKey:(NSString *)privateKey{
    //加密
    
    RSA *privateRSA=[self createRsaKeyWithPrivateKey:privateKey];
    
    NSData *data=[self encryptDate:[content dataUsingEncoding:NSUTF8StringEncoding] withPrivateRSA:privateRSA];
   // NSData *encodeData=[GTMBase64 encodeData:data];
    NSData * encodeData = [data base64EncodedDataWithOptions:0];
    NSString * encrypotoResult= [[NSString alloc] initWithData:encodeData encoding:NSUTF8StringEncoding];
    
    return encrypotoResult;
}


#pragma 解密
+(NSString *) decryptString:(NSString *)encryptContent withPrivateKey:(NSString *)privateKey{
    //解密
    
      RSA *privateRSA=[self createRsaKeyWithPrivateKey:privateKey];
    
    //可以用系统自带的base64,也可以用GTMBase64这个库
    //NSData *encodeData=[GTMBase64 decodeString:encryptContent];
    NSData *encodeData = [[NSData alloc] initWithBase64EncodedString:encryptContent options:NSDataBase64DecodingIgnoreUnknownCharacters];
    
    NSData *data=[self decryptData:encodeData withPrivateRSA:privateRSA];
    NSString * decrypotoResult= [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    
    return decrypotoResult;
}



@end

 

第二种:

 

第二种很简单,就添加两个类就可以完成所有操作了,简单快捷。推荐使用

RsaUtil.h

 

//
//  IOS使用OpenSSL 生成的公私玥字符串进行RSA加解密
//  RsaUtil.h
//
//  Created by kokjuis on 16/8/19.
//
//

#import <Foundation/Foundation.h>

@interface RsaUtil : NSObject


/*
 注意,RSA加解密的特征是:公钥加密->私钥解密、私钥加密->公钥解密。
 */


// return base64 encoded string
+ (NSString *)encryptString:(NSString *)str publicKey:(NSString *)pubKey;
// return raw data
+ (NSData *)encryptData:(NSData *)data publicKey:(NSString *)pubKey;
// return base64 encoded string
+ (NSString *)encryptString:(NSString *)str privateKey:(NSString *)privKey;
// return raw data
+ (NSData *)encryptData:(NSData *)data privateKey:(NSString *)privKey;

// decrypt base64 encoded string, convert result to string(not base64 encoded)
+ (NSString *)decryptString:(NSString *)str publicKey:(NSString *)pubKey;
+ (NSData *)decryptData:(NSData *)data publicKey:(NSString *)pubKey;
+ (NSString *)decryptString:(NSString *)str privateKey:(NSString *)privKey;
+ (NSData *)decryptData:(NSData *)data privateKey:(NSString *)privKey;

@end


RsaUtil.m

 

 

 

 

//
//  RsaUtil.m
//  BestTravel
//
//  Created by kokjuis on 16/8/19.
//
//

#import "RsaUtil.h"
#import <Security/Security.h>

@implementation RsaUtil


/*
 static NSString *base64_encode(NSString *str){
 NSData* data = [str dataUsingEncoding:NSUTF8StringEncoding];
 if(!data){
 return nil;
 }
 return base64_encode_data(data);
 }
 */

static NSString *base64_encode_data(NSData *data){
    data = [data base64EncodedDataWithOptions:0];
    NSString *ret = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    return ret;
}

static NSData *base64_decode(NSString *str){
    NSData *data = [[NSData alloc] initWithBase64EncodedString:str options:NSDataBase64DecodingIgnoreUnknownCharacters];
    return data;
}

+ (NSData *)stripPublicKeyHeader:(NSData *)d_key{
    // Skip ASN.1 public key header
    if (d_key == nil) return(nil);
    
    unsigned long len = [d_key length];
    if (!len) return(nil);
    
    unsigned char *c_key = (unsigned char *)[d_key bytes];
    unsigned int  idx     = 0;
    
    if (c_key[idx++] != 0x30) return(nil);
    
    if (c_key[idx] > 0x80) idx += c_key[idx] - 0x80 + 1;
    else idx++;
    
    // PKCS #1 rsaEncryption szOID_RSA_RSA
    static unsigned char seqiod[] =
    { 0x30,   0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
        0x01, 0x05, 0x00 };
    if (memcmp(&c_key[idx], seqiod, 15)) return(nil);
    
    idx += 15;
    
    if (c_key[idx++] != 0x03) return(nil);
    
    if (c_key[idx] > 0x80) idx += c_key[idx] - 0x80 + 1;
    else idx++;
    
    if (c_key[idx++] != '\0') return(nil);
    
    // Now make a new NSData from this buffer
    return([NSData dataWithBytes:&c_key[idx] length:len - idx]);
}

//credit: http://hg.mozilla.org/services/fx-home/file/tip/Sources/NetworkAndStorage/CryptoUtils.m#l1036
+ (NSData *)stripPrivateKeyHeader:(NSData *)d_key{
    // Skip ASN.1 private key header
    if (d_key == nil) return(nil);
    
    unsigned long len = [d_key length];
    if (!len) return(nil);
    
    unsigned char *c_key = (unsigned char *)[d_key bytes];
    unsigned int  idx     = 22; //magic byte at offset 22
    
    if (0x04 != c_key[idx++]) return nil;
    
    //calculate length of the key
    unsigned int c_len = c_key[idx++];
    int det = c_len & 0x80;
    if (!det) {
        c_len = c_len & 0x7f;
    } else {
        int byteCount = c_len & 0x7f;
        if (byteCount + idx > len) {
            //rsa length field longer than buffer
            return nil;
        }
        unsigned int accum = 0;
        unsigned char *ptr = &c_key[idx];
        idx += byteCount;
        while (byteCount) {
            accum = (accum << 8) + *ptr;
            ptr++;
            byteCount--;
        }
        c_len = accum;
    }
    
    // Now make a new NSData from this buffer
    return [d_key subdataWithRange:NSMakeRange(idx, c_len)];
}

+ (SecKeyRef)addPublicKey:(NSString *)key{
    NSRange spos = [key rangeOfString:@"-----BEGIN PUBLIC KEY-----"];
    NSRange epos = [key rangeOfString:@"-----END PUBLIC KEY-----"];
    if(spos.location != NSNotFound && epos.location != NSNotFound){
        NSUInteger s = spos.location + spos.length;
        NSUInteger e = epos.location;
        NSRange range = NSMakeRange(s, e-s);
        key = [key substringWithRange:range];
    }
    key = [key stringByReplacingOccurrencesOfString:@"\r" withString:@""];
    key = [key stringByReplacingOccurrencesOfString:@"\n" withString:@""];
    key = [key stringByReplacingOccurrencesOfString:@"\t" withString:@""];
    key = [key stringByReplacingOccurrencesOfString:@" "  withString:@""];
    
    // This will be base64 encoded, decode it.
    NSData *data = base64_decode(key);
    data = [RsaUtil stripPublicKeyHeader:data];
    if(!data){
        return nil;
    }
    
    //a tag to read/write keychain storage
    NSString *tag = @"RSAUtil_PubKey";
    NSData *d_tag = [NSData dataWithBytes:[tag UTF8String] length:[tag length]];
    
    // Delete any old lingering key with the same tag
    NSMutableDictionary *publicKey = [[NSMutableDictionary alloc] init];
    [publicKey setObject:(__bridge id) kSecClassKey forKey:(__bridge id)kSecClass];
    [publicKey setObject:(__bridge id) kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
    [publicKey setObject:d_tag forKey:(__bridge id)kSecAttrApplicationTag];
    SecItemDelete((__bridge CFDictionaryRef)publicKey);
    
    // Add persistent version of the key to system keychain
    [publicKey setObject:data forKey:(__bridge id)kSecValueData];
    [publicKey setObject:(__bridge id) kSecAttrKeyClassPublic forKey:(__bridge id)
     kSecAttrKeyClass];
    [publicKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)
     kSecReturnPersistentRef];
    
    CFTypeRef persistKey = nil;
    OSStatus status = SecItemAdd((__bridge CFDictionaryRef)publicKey, &persistKey);
    if (persistKey != nil){
        CFRelease(persistKey);
    }
    if ((status != noErr) && (status != errSecDuplicateItem)) {
        return nil;
    }
    
    [publicKey removeObjectForKey:(__bridge id)kSecValueData];
    [publicKey removeObjectForKey:(__bridge id)kSecReturnPersistentRef];
    [publicKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecReturnRef];
    [publicKey setObject:(__bridge id) kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
    
    // Now fetch the SecKeyRef version of the key
    SecKeyRef keyRef = nil;
    status = SecItemCopyMatching((__bridge CFDictionaryRef)publicKey, (CFTypeRef *)&keyRef);
    if(status != noErr){
        return nil;
    }
    return keyRef;
}

+ (SecKeyRef)addPrivateKey:(NSString *)key{
    NSRange spos;
    NSRange epos;
    spos = [key rangeOfString:@"-----BEGIN RSA PRIVATE KEY-----"];
    if(spos.length > 0){
        epos = [key rangeOfString:@"-----END RSA PRIVATE KEY-----"];
    }else{
        spos = [key rangeOfString:@"-----BEGIN PRIVATE KEY-----"];
        epos = [key rangeOfString:@"-----END PRIVATE KEY-----"];
    }
    if(spos.location != NSNotFound && epos.location != NSNotFound){
        NSUInteger s = spos.location + spos.length;
        NSUInteger e = epos.location;
        NSRange range = NSMakeRange(s, e-s);
        key = [key substringWithRange:range];
    }
    key = [key stringByReplacingOccurrencesOfString:@"\r" withString:@""];
    key = [key stringByReplacingOccurrencesOfString:@"\n" withString:@""];
    key = [key stringByReplacingOccurrencesOfString:@"\t" withString:@""];
    key = [key stringByReplacingOccurrencesOfString:@" "  withString:@""];
    
    // This will be base64 encoded, decode it.
    NSData *data = base64_decode(key);
    data = [RsaUtil stripPrivateKeyHeader:data];
    if(!data){
        return nil;
    }
    
    //a tag to read/write keychain storage
    NSString *tag = @"RSAUtil_PrivKey";
    NSData *d_tag = [NSData dataWithBytes:[tag UTF8String] length:[tag length]];
    
    // Delete any old lingering key with the same tag
    NSMutableDictionary *privateKey = [[NSMutableDictionary alloc] init];
    [privateKey setObject:(__bridge id) kSecClassKey forKey:(__bridge id)kSecClass];
    [privateKey setObject:(__bridge id) kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
    [privateKey setObject:d_tag forKey:(__bridge id)kSecAttrApplicationTag];
    SecItemDelete((__bridge CFDictionaryRef)privateKey);
    
    // Add persistent version of the key to system keychain
    [privateKey setObject:data forKey:(__bridge id)kSecValueData];
    [privateKey setObject:(__bridge id) kSecAttrKeyClassPrivate forKey:(__bridge id)
     kSecAttrKeyClass];
    [privateKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)
     kSecReturnPersistentRef];
    
    CFTypeRef persistKey = nil;
    OSStatus status = SecItemAdd((__bridge CFDictionaryRef)privateKey, &persistKey);
    if (persistKey != nil){
        CFRelease(persistKey);
    }
    if ((status != noErr) && (status != errSecDuplicateItem)) {
        return nil;
    }
    
    [privateKey removeObjectForKey:(__bridge id)kSecValueData];
    [privateKey removeObjectForKey:(__bridge id)kSecReturnPersistentRef];
    [privateKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecReturnRef];
    [privateKey setObject:(__bridge id) kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
    
    // Now fetch the SecKeyRef version of the key
    SecKeyRef keyRef = nil;
    status = SecItemCopyMatching((__bridge CFDictionaryRef)privateKey, (CFTypeRef *)&keyRef);
    if(status != noErr){
        return nil;
    }
    return keyRef;
}

/* START: Encryption & Decryption with RSA private key */

+ (NSData *)encryptData:(NSData *)data withKeyRef:(SecKeyRef) keyRef isSign:(BOOL)isSign {
    const uint8_t *srcbuf = (const uint8_t *)[data bytes];
    size_t srclen = (size_t)data.length;
    
    size_t block_size = SecKeyGetBlockSize(keyRef) * sizeof(uint8_t);
    void *outbuf = malloc(block_size);
    size_t src_block_size = block_size - 11;
    
    NSMutableData *ret = [[NSMutableData alloc] init];
    for(int idx=0; idx<srclen; idx+=src_block_size){
        //NSLog(@"%d/%d block_size: %d", idx, (int)srclen, (int)block_size);
        size_t data_len = srclen - idx;
        if(data_len > src_block_size){
            data_len = src_block_size;
        }
        
        size_t outlen = block_size;
        OSStatus status = noErr;
        
        if (isSign) {
            status = SecKeyRawSign(keyRef,
                                   kSecPaddingPKCS1,
                                   srcbuf + idx,
                                   data_len,
                                   outbuf,
                                   &outlen
                                   );
        } else {
            status = SecKeyEncrypt(keyRef,
                                   kSecPaddingPKCS1,
                                   srcbuf + idx,
                                   data_len,
                                   outbuf,
                                   &outlen
                                   );
        }
        if (status != 0) {
            NSLog(@"SecKeyEncrypt fail. Error Code: %d", status);
            ret = nil;
            break;
        }else{
            [ret appendBytes:outbuf length:outlen];
        }
    }
    
    free(outbuf);
    CFRelease(keyRef);
    return ret;
    //    NSData *encodeData=[GTMBase64 encodeData:data];
//    NSData * encodeData = [data base64EncodedDataWithOptions:0];
//
//    NSString * encrypotoResult= [[NSString alloc] initWithData:encodeData encoding:NSUTF8StringEncoding];
//
//    return encrypotoResult;
}

+ (NSString *)encryptString:(NSString *)str privateKey:(NSString *)privKey{
    NSData *data = [RsaUtil encryptData:[str dataUsingEncoding:NSUTF8StringEncoding] privateKey:privKey];
    NSString *ret = base64_encode_data(data);
    return ret;
}

+ (NSData *)encryptData:(NSData *)data privateKey:(NSString *)privKey{
    if(!data || !privKey){
        return nil;
    }
    SecKeyRef keyRef = [RsaUtil addPrivateKey:privKey];
    if(!keyRef){
        return nil;
    }
    return [RsaUtil encryptData:data withKeyRef:keyRef isSign:YES];
}

+ (NSData *)decryptData:(NSData *)data withKeyRef:(SecKeyRef) keyRef{
    const uint8_t *srcbuf = (const uint8_t *)[data bytes];
    size_t srclen = (size_t)data.length;
    
    size_t block_size = SecKeyGetBlockSize(keyRef) * sizeof(uint8_t);
    UInt8 *outbuf = malloc(block_size);
    size_t src_block_size = block_size;
    
    NSMutableData *ret = [[NSMutableData alloc] init];
    for(int idx=0; idx<srclen; idx+=src_block_size){
        //NSLog(@"%d/%d block_size: %d", idx, (int)srclen, (int)block_size);
        size_t data_len = srclen - idx;
        if(data_len > src_block_size){
            data_len = src_block_size;
        }
        
        size_t outlen = block_size;
        OSStatus status = noErr;
        status = SecKeyDecrypt(keyRef,
                               kSecPaddingNone,
                               srcbuf + idx,
                               data_len,
                               outbuf,
                               &outlen
                               );
        if (status != 0) {
            NSLog(@"SecKeyEncrypt fail. Error Code: %d", status);
            ret = nil;
            break;
        }else{
            //the actual decrypted data is in the middle, locate it!
            int idxFirstZero = -1;
            int idxNextZero = (int)outlen;
            for ( int i = 0; i < outlen; i++ ) {
                if ( outbuf[i] == 0 ) {
                    if ( idxFirstZero < 0 ) {
                        idxFirstZero = i;
                    } else {
                        idxNextZero = i;
                        break;
                    }
                }
            }
            
            [ret appendBytes:&outbuf[idxFirstZero+1] length:idxNextZero-idxFirstZero-1];
        }
    }
    
    free(outbuf);
    CFRelease(keyRef);
    return ret;
}


+ (NSString *)decryptString:(NSString *)str privateKey:(NSString *)privKey{
    NSData *data = [[NSData alloc] initWithBase64EncodedString:str options:NSDataBase64DecodingIgnoreUnknownCharacters];
    data = [RsaUtil decryptData:data privateKey:privKey];
    NSString *ret = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    return ret;
}

+ (NSData *)decryptData:(NSData *)data privateKey:(NSString *)privKey{
    if(!data || !privKey){
        return nil;
    }
    SecKeyRef keyRef = [RsaUtil addPrivateKey:privKey];
    if(!keyRef){
        return nil;
    }
    return [RsaUtil decryptData:data withKeyRef:keyRef];
}

/* END: Encryption & Decryption with RSA private key */

/* START: Encryption & Decryption with RSA public key */

+ (NSString *)encryptString:(NSString *)str publicKey:(NSString *)pubKey{
    NSData *data = [RsaUtil encryptData:[str dataUsingEncoding:NSUTF8StringEncoding] publicKey:pubKey];
    NSString *ret = base64_encode_data(data);
    return ret;
}

+ (NSData *)encryptData:(NSData *)data publicKey:(NSString *)pubKey{
    if(!data || !pubKey){
        return nil;
    }
    SecKeyRef keyRef = [RsaUtil addPublicKey:pubKey];
    if(!keyRef){
        return nil;
    }
    return [RsaUtil encryptData:data withKeyRef:keyRef isSign:NO];
}

+ (NSString *)decryptString:(NSString *)str publicKey:(NSString *)pubKey{
    NSData *data = [[NSData alloc] initWithBase64EncodedString:str options:NSDataBase64DecodingIgnoreUnknownCharacters];
    data = [RsaUtil decryptData:data publicKey:pubKey];
    NSString *ret = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    return ret;
}

+ (NSData *)decryptData:(NSData *)data publicKey:(NSString *)pubKey{
    if(!data || !pubKey){
        return nil;
    }
    SecKeyRef keyRef = [RsaUtil addPublicKey:pubKey];
    if(!keyRef){
        return nil;
    }
    return [RsaUtil decryptData:data withKeyRef:keyRef];
}

/* END: Encryption & Decryption with RSA public key */


@end

 

 

 

 

 

 

 

 

5、web上RSA加密

 

 

在js上使用rsa加密就相对简单了,主要是用了一个加密类:jsencrypt.min.js    可以到这里下载:http://download.csdn.net/detail/kokjuis/9723324 点击打开链接 

下载完以后引用到你的工程里面就好了。加密方法也很简单,直接看代码:

 

 

<script src="static/js/jsencrypt.min.js"></script>

//获取服务器端传来的公钥
var MattsPublicKeyString="${rsaKey}";
//实例化加密对象
var encrypt = new JSEncrypt();
//设置加密公钥
encrypt.setPublicKey(MattsPublicKeyString);
			//进行加密操作
var enAccount = encrypt.encrypt(account);

 

 

 

 

 

(全文完)

 

 

没有更多推荐了,返回首页