iOS-在项目中引入RSA算法

栏目: IOS · 发布时间: 5年前

内容简介:契机是公司换了一套新接口,要求进行全报文加密。以前公司项目基本上都使用的对称加密的模式本篇不会对1.
iOS-在项目中引入RSA算法

1.前言

契机是公司换了一套新接口,要求进行全报文加密。以前公司项目基本上都使用的对称加密的模式 3DESAES ,由于对称加密的密钥只有一对,有很大的密钥泄露风险。身处金融这个极为敏感的行业,对安全的要求也是极高。趁着这个机会,把项目中的加密模式统一替换成 RSA 非对称加密。

2.关于加密算法

本篇不会对 RSA 加密算法原理进行详细的解释。在互联网异常发达的今天, RSA 算法详细的资料很容易就能获取到。安全领域也是一个能够深挖的领域,本篇文章偏向工程向,仅对一些基本基本概念进行简单的解释。

  • 对称加密和非对称加密

1. 对称加密 :加密和解密用的是同一套密钥,缺陷是密钥管理存在风险。常用的加密方式有: DES3DESAES 等。

2. 非对称加密 :加密和解密用的不同的密钥,公钥加密私钥解密。常用的加密方式有 RSA

  • RSA常见用法

1. 公钥加密,私钥解密;

2. 私钥签名;

3. 公钥验签。

3.实践

1、生成密钥:

使用终端openssl命令生成密钥

1).生成私钥,密钥长度为2048bit,base64编码。

openssl genrsa -out rsa_private_key.pem 2048
复制代码

关于密钥长度,这里要进行一下特别说明。每次加密的数据不能超出密钥的长度,2048bit长度的密钥,只能单次只能加密(2048 / 8 - 11) = 245byte长度的数据。(那11byte是RSA预留的长度)。若待加密的数据长度超过了245byte,就需要对数据进行分段加密。

2).根据之前生成的私钥生成公钥:

openssl rsa -in rsa_private_key.pem -out rsa_public_key.pem -pubout
复制代码

3).转换公钥为 PKCS8 格式,这种格式可以直接在iOS项目中使用:

openssl pkcs8 -topk8 -in rsa_private_key.pem -out pkcs8_rsa_private_key.pem -nocrypt
复制代码

我司的情况是由公司后台生成私钥和公钥,提供 .pem 格式的公钥给移动端,因此我直接使用的是pkcs8格式的公钥。

注意:不建议将私钥保存在客户端,私钥泄露后果会很严重!

2、在项目中使用:

Demo地址: github.com/Hstripe/RHR…

以上是我使用的 RSA 工具类,支持 RSA 在移动端的各种日常用法:加密、解密、加签、验签。跟网上很多 工具 类不同的是不需要导入 p12der 格式的密钥文件,支持字符串形式的密钥文件非常方便。而且使用的是 Apple 自家的 Security.framework 。网上很多例程都是使用的 openSSL 那一套加密工具类,实现也很方便就是包体积略微有点大。

若使用 IDEXcode8 及以上,请在 Capabilities 中将 KeyChain sharing 设置为 YES

1.)公钥加密

NSString *string = @"doRSAEncrypt";

NSString *publickey = @"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA61sODmFj/OXnrHUYzams\
 c/6XLni9G0HYv9sBewaPjF6qlu845nwmYSA6dQ9zPk231o5l3tmHLpUQGNnp/5rH\
 +84iB/tM+Y+2kTI8uILGbmby2DL3rgzBG+I9h7e3w3QktpdcD8Z+ZuEVa/CY3Xez\
 8X1uknEVzIIhDKY7ipAoebchVdELbTlH1BRLz8RH6mQ+Z8REH4UL0TiQLfSfTotv\
 1G5ZerNxVZ7Toi4K9KFDA+1UD+LeDGg8PY/sdg0AJpR4o6bfDBko50wKLDz4UYyp\
 7EFZv661o2Mr7+KoQ6Tpb7w8bTl7wrRKz9ugB5+tM2F7aDvv1mzr7STIF+2c7tEx\
 DQIDAQAB";

NSString *encryptString = [IPNRSAUtil encryptString:string publicKey:publickey];
复制代码

2.)私钥解密

NSString *privatekey = @"MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDrWw4OYWP85ees\
 dRjNqaxz/pcueL0bQdi/2wF7Bo+MXqqW7zjmfCZhIDp1D3M+TbfWjmXe2YculRAY\
 2en/msf7ziIH+0z5j7aRMjy4gsZuZvLYMveuDMEb4j2Ht7fDdCS2l1wPxn5m4RVr\
 8Jjdd7PxfW6ScRXMgiEMpjuKkCh5tyFV0QttOUfUFEvPxEfqZD5nxEQfhQvROJAt\
 9J9Oi2/Ubll6s3FVntOiLgr0oUMD7VQP4t4MaDw9j+x2DQAmlHijpt8MGSjnTAos\
 PPhRjKnsQVm/rrWjYyvv4qhDpOlvvDxtOXvCtErP26AHn60zYXtoO+/WbOvtJMgX\
 7Zzu0TENAgMBAAECggEBAOMf6w+ror9y6sE9+6K1hEwoO6NIN06vm8mCQwqDiVIw\
 JTYlQ+cBllQSsvc24sMUYz32C48ko1Ur2u3wleXqa+Wvxp2nQWBw9QFn1rtE0NPI\
 G8DSZr0bZ9xN1406mWdQlQF0Tg6XQnJr8q1I8WyAUTHSFzvRT/Uc+2Hmpf0RI05Y\
 t0dt5bsGn/g+ijGbCm63Z2U8u5yWXidxWfU/KyYf1Y3mw9lGLR6IJc/q9N+TO4ih\
 JM5pCraMFI4zWblGobkN2WKy7MrQ45FLSKul4W00+VyM/rVivW/fYUaqFEnlBog3\
 /4hgI6Bsw2IuSk2Ubhbc4fp//146vJf6oL4WAJHmAiECgYEA+e3AFph8joC5gC1Q\
 ok97tLJqt95fZCx4VCw6lPPbWxOHG6TJlvlo7kZIeUfKrGIlOWn38yuw5thEZKwW\
 bzE8kn5WGlUgkOQ7hJ6Iiw/TzCFPRHxV63WBKa8OnyFIn3w91zI8ZTcUgrgyns+F\
 gE5uxkEjb6iIyxxnpqC7Fk3lnikCgYEA8RKtn7kqoe0T/Yv7UsPLm7KzuWn3/01r\
 LGA+x+GCp4rP2Lf0u1K+7VY6Dv/ceTBuA/2Yujenkjt0LaF+Bz0tLWFB5BTw3n+u\
 6QshVdP3O1im4w6p3e8O9mfBCSV/CX5oBkbamemyQ7DTB9VtYNNmtGTs2aySuoel\
 zPU0czETEEUCgYAjVhwclb62nzibCM0nxbkl2TwBdy1hinAQ5pf5y2iuPdqSbAAc\
 mnLdjY5dp2reaJn+vh7SgNDoMpeo7DPX0MxRog8mdfa+xaYsoAWKM9isOeFtO28i\
 dWCnthqJITmVYwmTTYUAgoMh4E036vtjIrPC0B7kgJ2mqgN1qbAJ/UWD0QKBgFSO\
 U53hacWwDUHydm2aRXFQJd/T/mtq8Tt4aqzbOWOgubRvGYUWyecfRm/6aI+NYBlA\
 OvCeEsWk2uQib70ERTNUmLLycWXpbSVKhR/AoEgNmUOs4gH5FstwqvGVWFCxKLWC\
 5qvzn1ZE0FBAGQRMQgrmF3lmIXURnSMdoo8A2IntAoGAVCFmPpXvI8rMk2N3CvQ4\
 dkDfP3W6w1KpyMzuQRZE9N1IUBYh3KN25HfzeW1OIFHPuxInMm/6zaU/rUHJSy/b\
 ynVdQ6jvM4ZIt3rYUXZN6+a14AeA/MNNrY2LzCYlCxWIbVyNj9UN8/uda0zEtZ73\
 RWYX1BlKVMSIx5Bf7eNH4fI=";

NSString *decryptString = [IPNRSAUtil decryptString:encryptString privateKey:privatekey];
复制代码

3.)私钥加签

NSString *signature = [IPNRSAUtil rsaSignString:string WithPrivateKey:privatekey];
复制代码

4.)公钥验签

BOOL result = [IPNRSAUtil rsaVerifySignature:signature plainString:string WithPublicKey:publickey];
复制代码

5.)分段加密

若待加密的数据长度大于密钥长度,就需要对待加密的数据进行分段加密

// n为密钥单次加密长度,这里使用的是2048位的密钥,因此n的值为245(2048/8 - 11)。
NSInteger n = 245;
NSMutableData *preData = [[NSMutableData alloc] init];
for (NSInteger i=0; i<=ceilf(string.length / n); i++) {
    NSString *subString = [string substringWithRange:NSMakeRange(i * n, MIN(n, string.length - i * 245))];
    NSData *encryptData = [IPNRSAUtil encryptData:[subString dataUsingEncoding:NSUTF8StringEncoding] publicKey:publickey];
// 分段加密需要拼接加密后的data数据,不要将data转换成字符串再拼接,这样会导致结果错误。
    [preData appendData:encryptData];
}

NSData *finalData = [[NSData alloc] initWithData:preData];
finalData = [finalData base64EncodedDataWithOptions:0];
NSString *result = [[NSString alloc] initWithData:finalData encoding:NSUTF8StringEncoding];
复制代码

4.后记

为了搞这个工具类前前后后花了也有半个多月的时间了,看了很多文档和例程加上自己的实践调试才有了这个工具类。一开始使用的是 openSSL 那一套加密工具实现的,但是觉得 openSSL 占用的空间略大,还是用 Security.framework 来实现的。平时总是忙于业务需求的实现,忽视了客户端方面的安全,网上对客户端安全这一块的资源也比较有限,但愿我这篇文章能对后来人有所帮助吧。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Elements of Programming

Elements of Programming

Alexander A. Stepanov、Paul McJones / Addison-Wesley Professional / 2009-6-19 / USD 39.99

Elements of Programming provides a different understanding of programming than is presented elsewhere. Its major premise is that practical programming, like other areas of science and engineering, mus......一起来看看 《Elements of Programming》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

随机密码生成器
随机密码生成器

多种字符组合密码

URL 编码/解码
URL 编码/解码

URL 编码/解码