[转] iOS下使用SHA1WithRSA算法加签源码
首先了解一下几个相关概念,以方便后面遇到的问题的解决:
RSA算法:1977年由Ron Rivest、Adi Shamirh和LenAdleman发明的,RSA就是取自他们三个人的名字。算法基于一个数论:将两个大素数相乘非常容易,但要对这个乘积的结果进行因式分解却非常困难,因此可以把乘积公开作为公钥。该算法能够抵抗目前已知的所有密码攻击。RSA算法是一种非对称算法,算法需要一对密钥,使用其中一个加密,需要使用另外一个才能解密。我们在进行RSA加密通讯时,就把公钥放在客户端,私钥留在服务器。
PEM:既然使用RSA需要一对密钥,那么我们当然是要先使用工具来生成这样一对密钥了。在linux、unix下,最简单方便的就是使用openssl命令行了。而DER、PEM就是生成的密钥可选择的两种文件格式。DER是Distinguished Encoding Rules的简称,是一种信息传输语法规则,在ITU X.690中定义的。在ios端,我们的公钥就是需要这样一种格式的,我们可以从Certificate, Key, and Trust Services Reference这篇文档的SecCertificateCreateWithData函数的data参数的说明中看到。而PEM格式是一种对DER进行封装的格式,他只是把der的内容进行了base64编码并加上了头尾说明。openssl命令行默认输出的都是PEM格式的文件,要能够在ios下使用,我们需要指定使用DER或者先生成PEM然后转换称DER。还有那些keystore,pkcs,p7b,p12后面介绍
IOS客户端的加解密首先我们需要导入Security.framework,
在ios中,我们主要关注四个函数
-
- SecKeyEncrypt:使用公钥对数据进行加密
- SecKeyDecrypt:使用私钥对数据进行解密
- SecKeyRawVerify:使用公钥对数字签名和数据进行验证,以确认该数据的来源合法性。什么是数字签名,可以参考百度百科这篇文章?
- SecKeyRawSign:使用私钥对数据进行摘要并生成数字签名
RSA算法有2个作用一个是加密一个是加签。从这几个函数中,我们可以看到,我们第一种是使用公钥能在客户端:加密数据,以及服务器端用私钥解密。
第二个就是用私钥在客户端加签,然后用公钥在服务器端用公钥验签。第一种完全是为了加密,第二种是为了放抵赖,就是为了防止别人模拟我们的客户端来攻击我们的服务器,导致瘫痪。
1.RSA加密解密:
(1)获取密钥,这里是产生密钥,实际应用中可以从各种存储介质上读取密钥 (2)加密 (3)解密
2.RSA签名和验证
(1)获取密钥,这里是产生密钥,实际应用中可以从各种存储介质上读取密钥 (2)获取待签名的Hash码 (3)获取签名的字符串 (4)验证
3.公钥与私钥的理解:
(1)私钥用来进行解密和签名,是给自己用的。
(2)公钥由本人公开,用于加密和验证签名,是给别人用的。
(3)当该用户发送文件时,用私钥签名,别人用他给的公钥验证签名,可以保证该信息是由他发送的。当该用户接受文件时,别人用他的公钥加密,他用私钥解密,可以保证该信息只能由他接收到。
首先加入头文件
#import <CommonCrypto/CommonDigest.h>
#import <CommonCrypto/CommonCryptor.h>
#import <Security/Security.h>
#import "NSData+Base64.h"
#define kChosenDigestLength CC_SHA1_DIGEST_LENGTH // SHA-1消息摘要的数据位数160位
1 -(SecKeyRef)getPublicKey{ 2 NSString *certPath = [[NSBundle mainBundle] pathForResource:@"keystore" ofType:@"p7b"]; 3 SecCertificateRef myCertificate = nil; 4 NSData *certificateData = [[NSData alloc] initWithContentsOfFile:certPath]; 5 myCertificate = SecCertificateCreateWithData(kCFAllocatorDefault, (CFDataRef)certificateData); 6 SecPolicyRef myPolicy = SecPolicyCreateBasicX509(); 7 SecTrustRef myTrust; 8 OSStatus status = SecTrustCreateWithCertificates(myCertificate,myPolicy,&myTrust); 9 SecTrustResultType trustResult; 10 if (status == noErr) { 11 status = SecTrustEvaluate(myTrust, &trustResult); 12 } 13 return SecTrustCopyPublicKey(myTrust); 14 } 15 16 17 -(NSString *)RSAEncrypotoTheData:(NSString *)plainText 18 { 19 20 SecKeyRef publicKey=nil; 21 publicKey=[self getPublicKey]; 22 size_t cipherBufferSize = SecKeyGetBlockSize(publicKey); 23 uint8_t *cipherBuffer = NULL; 24 25 cipherBuffer = malloc(cipherBufferSize * sizeof(uint8_t)); 26 memset((voidvoid *)cipherBuffer, 0*0, cipherBufferSize); 27 28 NSData *plainTextBytes = [plainText dataUsingEncoding:NSUTF8StringEncoding]; 29 int blockSize = cipherBufferSize-11; // 这个地方比较重要是加密问组长度 30 int numBlock = (int)ceil([plainTextBytes length] / (double)blockSize); 31 NSMutableData *encryptedData = [[NSMutableData alloc] init]; 32 for (int i=0; i<numBlock; i++) { 33 int bufferSize = MIN(blockSize,[plainTextBytes length]-i*blockSize); 34 NSData *buffer = [plainTextBytes subdataWithRange:NSMakeRange(i * blockSize, bufferSize)]; 35 OSStatus status = SecKeyEncrypt(publicKey, 36 kSecPaddingPKCS1, 37 (const uint8_t *)[buffer bytes], 38 [buffer length], 39 cipherBuffer, 40 &cipherBufferSize); 41 if (status == noErr) 42 { 43 NSData *encryptedBytes = [[[NSData alloc] 44 initWithBytes:(const voidvoid *)cipherBuffer 45 length:cipherBufferSize] autorelease]; 46 [encryptedData appendData:encryptedBytes]; 47 } 48 else 49 { 50 return nil; 51 } 52 } 53 if (cipherBuffer) 54 { 55 free(cipherBuffer); 56 } 57 NSString *encrypotoResult=[NSString stringWithFormat:@"%@",[encryptedData base64EncodedString]]; 58 return encrypotoResult; 59 }