iOS中使用RSA对数据进行加密解密
RSA算法是一种非对称加密算法,常被用于加密数据传输.如果配合上数字摘要算法, 也可以用于文件签名.
本文将讨论如何在iOS中使用RSA传输加密数据.
本文环境
- mac os
- openssl-1.0.1j, openssl需要使用1.x版本, 推荐使用[homebrew](http://brew.sh/)安装.
- Java 8
RSA基本原理
RSA使用"秘匙对"对数据进行加密解密.在加密解密数据前,需要先生成公钥(public key)和私钥(private key).
- 公钥(public key): 用于加密数据. 用于公开, 一般存放在数据提供方, 例如iOS客户端.
- 私钥(private key): 用于解密数据. 必须保密, 私钥泄露会造成安全问题.
iOS中的Security.framework提供了对RSA算法的支持.这种方式需要对密匙对进行处理, 根据public key生成证书, 通过private key生成p12格式的密匙.
除了Secruty.framework, 也可以将openssl库编译到iOS工程中, 这可以提供更灵活的使用方式.
本文使用Security.framework的方式处理RSA.
使用openssl生成密匙对
Github Gist: https://gist.github.com/lvjian700/635368d6f1e421447680
- #!/usr/bin/env bash
- echo "Generating RSA key pair ..."
- echo "1024 RSA key: private_key.pem"
- openssl genrsa -out private_key.pem 1024
- echo "create certification require file: rsaCertReq.csr"
- openssl req -new -key private_key.pem -out rsaCertReq.csr
- echo "create certification using x509: rsaCert.crt"
- openssl x509 -req -days 3650 -in rsaCertReq.csr -signkey private_key.pem -out rsaCert.crt
- echo "create public_key.der For IOS"
- openssl x509 -outform der -in rsaCert.crt -out public_key.der
- echo "create private_key.p12 For IOS. Please remember your password. The password will be used in iOS."
- openssl pkcs12 -export -out private_key.p12 -inkey private_key.pem -in rsaCert.crt
- echo "create rsa_public_key.pem For Java"
- openssl rsa -in private_key.pem -out rsa_public_key.pem -pubout
- echo "create pkcs8_private_key.pem For Java"
- openssl pkcs8 -topk8 -in private_key.pem -out pkcs8_private_key.pem -nocrypt
- echo "finished."
Tips:
- 在创建证书的时候, terminal会提示输入证书信息. 根据wizard输入对应信息就OK.
- 在创建p12密匙时, 会提示输入密码, 此时的密码必须记住, 之后会用到.
- 如果上面指令有问题,请参考最新的openssl官方文档, 以官方的为准. 之前在网上搜索指令, 被坑了一圈之后, 还是会到啃官方文档上. 每条指令文档在最后都会有几个sample,参考sample即可.
iOS如何加载使用证书
将下面代码添加到项目中:
https://gist.github.com/lvjian700/204c23226fdffd6a505d
代码依赖Base64编码库, 如果使用cocoapods, 可以讲下面依赖添加到Podfile:
- pod 'Base64nl', '~> 1.2'
加密数据
- RSAEncryptor *rsa = [[RSAEncryptor alloc] init];
- NSLog(@"encryptor using rsa");
- NSString *publicKeyPath = [[NSBundle mainBundle] pathForResource:@"public_key" ofType:@"der"];
- NSLog(@"public key: %@", publicKeyPath);
- [rsa loadPublicKeyFromFile:publicKeyPath];
- NSString *securityText = @"hello ~";
- NSString *encryptedString = [rsa rsaEncryptString:securityText];
- NSLog(@"encrypted data: %@", encryptedString);
__[rsa rsaEncryptString:securityText]__会返回decrypted base64编码的字符串:
解密数据
在iOS下解码需要先加载private key, 之后在对数据解码. 解码的时候先进行Base64 decode, 之后在用private key decrypt加密数据.
- NSLog(@"decryptor using rsa");
- [rsa loadPrivateKeyFromFile:[[NSBundle mainBundle] pathForResource:@"private_key" ofType:@"p12"] password:@"123456"];
- NSString *decryptedString = [rsa rsaDecryptString:encryptedString];
- NSLog(@"decrypted data: %@", decryptedString);
之后会输出解密后的数据:
decrypted data: hello ~
在服务器端解码数据(Java)
在Java中解码需要使用下述指令生成的pkcs8 private key:
具体解码步骤:
- 加载pkcs8 private key:
- 读取private key文件
- 去掉private key头尾的"-----BEGIN PRIVATE KEY-----"和"-----BEGIN PRIVATE KEY-----"
- 删除private key中的换行
- 对处理后的数据进行Base64解码
- 使用解码后的数据生成private key.
- 解密数据:
- 对数据进行Base64解码
- 使用RSA decrypt数据.
这里我将iOS中"hello ~"加密的数据在Java中进行解码:
- import javax.crypto.BadPaddingException;
- import javax.crypto.Cipher;
- import javax.crypto.IllegalBlockSizeException;
- import javax.crypto.NoSuchPaddingException;
- import java.io.IOException;
- import java.nio.charset.Charset;
- import java.nio.file.Files;
- import java.nio.file.Paths;
- import java.security.InvalidKeyException;
- import java.security.KeyFactory;
- import java.security.NoSuchAlgorithmException;
- import java.security.PrivateKey;
- import java.security.spec.InvalidKeySpecException;
- import java.security.spec.PKCS8EncodedKeySpec;
- import java.util.Base64;
- import static java.lang.String.format;
- public class Encryptor {
- public static void main(String[] args) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
- PrivateKey privateKey = readPrivateKey();
- String message = "AFppaFPTbmboMZD55cjCfrVaWUW7+hZkaq16Od+6fP0lwz/yC+Rshb/8cf5BpBlUao2EunchnzeKxzpiPqtCcCITKvk6HcFKZS0sN9wOhlQFYT+I4f/CZITwBVAJaldZ7mkyOiuvM+raXMwrS+7MLKgYXkd5cFPxEsTxpMSa5Nk=";
- System.out.println(format("- decrypt rsa encrypted base64 message: %s", message));
- // hello ~, encrypted and encoded with Base64:
- byte[] data = encryptedData(message);
- String text = decrypt(privateKey, data);
- System.out.println(text);
- }
- private static String decrypt(PrivateKey privateKey, byte[] data) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
- Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
- cipher.init(Cipher.DECRYPT_MODE, privateKey);
- byte[] decryptedData = cipher.doFinal(data);
- return new String(decryptedData);
- }
- private static byte[] encryptedData(String base64Text) {
- return Base64.getDecoder().decode(base64Text.getBytes(Charset.forName("UTF-8")));
- }
- private static PrivateKey readPrivateKey() throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
- byte[] privateKeyData = Files.readAllBytes(
- Paths.get("/Users/twer/macspace/ios_workshop/Security/SecurityLogin/tools/pkcs8_private_key.pem"));
- byte[] decodedKeyData = Base64.getDecoder()
- .decode(new String(privateKeyData)
- .replaceAll("-----\\w+ PRIVATE KEY-----", "")
- .replace("\n", "")
- .getBytes());
- return KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decodedKeyData));
- }
- }
直行成功后控制台会输出"hello ~".
总结
这种加密传输方式会被用在网银类App中.虽然网银会采用全站https方案, 但是在安全登录这块会使用另一个证书对登录信息加密, 这样可以双层确保数据安全.
基于RSA加密解密算法, 还可以将其运用在数字签名场景.以后有空在聊如何使用RSA算法实现对文件的数字签名.
参考资料
iOS中使用RSA对数据进行加密解密的更多相关文章
- IOS开发数据存储篇—IOS中的几种数据存储方式
IOS开发数据存储篇—IOS中的几种数据存储方式 发表于2016/4/5 21:02:09 421人阅读 分类: 数据存储 在项目开发当中,我们经常会对一些数据进行本地缓存处理.离线缓存的数据一般都 ...
- 使用 GPG 对数据进行加密解密签名
一:使用 GPG 对数据进行加密解密签名 基本的工具使用 1. GPG 是GNUPG 免费开源的gpg加密工具,和同pgp兼容,pgp收费. 2. 在mac上使用https://gpgtools.or ...
- NET实现RSA AES DES 字符串 加密解密以及SHA1 MD5加密
本文列举了 数据加密算法(Data Encryption Algorithm,DEA) 密码学中的高级加密标准(Advanced EncryptionStandard,AES)RSA公钥加密算法 ...
- C# RSA 无 长度限制 加密解密 示例
RSA 是一种非对称加密算法.由于算法特性,加密和解密过程用不同密钥,即公钥和私钥,而被广泛应用于数字证书的安全管理. 在具体应用中,公钥用加密而私钥用于解密,或 私钥用于数字签名而公钥用于签名验证. ...
- 与众不同 windows phone (28) - Feature(特性)之手机方向, 本地化, 应用程序的试用体验, 系统主题资源, 本地数据的加密解密
原文:与众不同 windows phone (28) - Feature(特性)之手机方向, 本地化, 应用程序的试用体验, 系统主题资源, 本地数据的加密解密 [索引页][源码下载] 与众不同 wi ...
- asp.net core 使用中间件拦截请求和返回数据,并对数据进行加密解密。
原文:asp.net core 使用中间件拦截请求和返回数据,并对数据进行加密解密. GitHub demo https://github.com/zhanglilong23/Asp.NetCore. ...
- iOS开发之 AES+Base64数据混合加密与解密
2016-04-08 09:03 编辑: liubinqww 分类:iOS开发 来源:liubinqww 投稿 4 889 "APP的数据安全已经牵动着我们开发者的心,简单的MD5/ ...
- iOS中GET 和 POST 数据请求
iOS中GET 和 POST 网络数据请求 同步请求和异步请求的差别: 1.同步请求,有主线程完成网路请求任务,在数据没有请求之前,用户的所有的交互事件应用都无法处理,会造成一种卡顿现象,影响用户体验 ...
- RSA密钥生成、加密解密、签名验签
RSA 非对称加密公钥加密,私钥解密 私钥签名,公钥验签 下面是生成随机密钥对: //随机生成密钥对 KeyPairGenerator keyPairGen = null; try { keyPair ...
随机推荐
- Vue.js简介
Vue.js简介 Vue.js的作者为Evan You(尤雨溪),任职于Google Creative Lab,虽然是Vue是一个个人项目,但在发展前景上个人认为绝不输于Google的AngularJ ...
- 使用HyperV虚拟机装系统
新建虚拟机 新建虚拟机 进行相关参数设置 选择系统安装镜像位置,名称及位置 指定代数一般为1代即可 为虚拟机运行分配内存 创建虚拟硬盘或连接已有虚拟硬盘,并分配硬盘空间 核对创建虚拟机相关信息 安装系 ...
- storm学习途径
作者: xumingming | 网址: http://xumingming.sinaapp.com/category/storm/ 作者:量子恒道 | 网址:http://blog.linezin ...
- 读书笔记2013第10本:《学得少却考得好Learn More Study Less》
<学得少却考得好Learn More Study Less>这本书最早是从褪墨网站上看到的,crowncheng翻译了全文.这本书介绍了不少学习方法,非常适合在校的学生,原文的作者Scot ...
- Android Studio 插件的使用
1.GsonFormat https://github.com/zzz40500/GsonFormat 2.Android SelectorChapek http://blog.csdn.ne ...
- linux终端python自动提示
linux终端python自动提示 很多时候,在linux下编写python时, 都懒得去vi一个新文件,直接就新开一个终端, 进入python命令行模式,然后就可以写一些测试代码. 不过最悲剧的就是 ...
- 分享到QQ空间、新浪微博、腾讯微博的代码
今天公司原来的分享代码,在IE下有问题.网上找了下网上的分享代码. 给网页加上分享代码,借助网友的力量推广网站,目前已经很流行了 以下是网页代码 QQ空间分享代码如下: <a href=&quo ...
- 敏捷软件开发(1)--- STATE 模式
如果状态在运行过程中,不停的切换和改变,我们怎么办? 状态的迁移是我们生活和工程中非常普遍的一个概念.于是在数学上有一种理论来分析和解决这个问题. 有限状态机理论是一个非常成熟的理论,所有动作和流程的 ...
- ubuntu 获取root权限
实验环境: ubuntu 13.04 背景:现在有一台装有 ubuntu 的电脑,如何获取root权限? 方案一:进入单用户维护模式,重置root密码. 方案二:U盘挂载原根分区,修改/etc/pas ...
- CentOS 6.4安装配置LAMP服务器(Apache+PHP5+MySQL)
这篇文章主要介绍了CentOS 6.4安装配置LAMP服务器(Apache+PHP5+MySQL)的方法,需要的朋友可以参考下 文章写的不错,很详细:IDO转载自网络: 准备篇: 1.配置防火墙,开启 ...