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位 


[objc]  view plain copy
  1. - (NSData *)getHashBytes:(NSData *)plainText {  
  2.     CC_SHA1_CTX ctx;  
  3.     uint8_t * hashBytes = NULL;  
  4.     NSData * hash = nil;  
  5.       
  6.     // Malloc a buffer to hold hash.  
  7.     hashBytes = malloc( kChosenDigestLength * sizeof(uint8_t) );  
  8.     memset((voidvoid *)hashBytes, 0x0, kChosenDigestLength);  
  9.     // Initialize the context.  
  10.     CC_SHA1_Init(&ctx);  
  11.     // Perform the hash.  
  12.     CC_SHA1_Update(&ctx, (voidvoid *)[plainText bytes], [plainText length]);  
  13.     // Finalize the output.  
  14.     CC_SHA1_Final(hashBytes, &ctx);  
  15.       
  16.     // Build up the SHA1 blob.  
  17.     hash = [NSData dataWithBytes:(const voidvoid *)hashBytes length:(NSUInteger)kChosenDigestLength];  
  18.     if (hashBytes) free(hashBytes);  
  19.       
  20.     return hash;  
  21. }  



[objc]  view plain copy
  1. -(NSString *)signTheDataSHA1WithRSA:(NSString *)plainText  
  2. {  
  3.     uint8_t* signedBytes = NULL;  
  4.     size_t signedBytesSize = 0;  
  5.     OSStatus sanityCheck = noErr;  
  6.     NSData* signedHash = nil;  
  7.   
  8.     NSString * path = [[NSBundle mainBundle]pathForResource:@"keystore" ofType:@"p12"];  
  9.     NSData * data = [NSData dataWithContentsOfFile:path];  
  10.     NSMutableDictionary * options = [[NSMutableDictionary alloc] init]; // Set the private key query dictionary.  
  11.     [options setObject:@"你的p12文件的密码" forKey:(id)kSecImportExportPassphrase];  
  12.     CFArrayRef items = CFArrayCreate(NULL00NULL);  
  13.     OSStatus securityError = SecPKCS12Import((CFDataRef) data, (CFDictionaryRef)options, &items);  
  14.     if (securityError!=noErr) {  
  15.         return nil ;  
  16.     }  
  17.     CFDictionaryRef identityDict = CFArrayGetValueAtIndex(items, 0);  
  18.     SecIdentityRef identityApp =(SecIdentityRef)CFDictionaryGetValue(identityDict,kSecImportItemIdentity);   
  19.     SecKeyRef privateKeyRef=nil;  
  20.     SecIdentityCopyPrivateKey(identityApp, &privateKeyRef);  
  21.     signedBytesSize = SecKeyGetBlockSize(privateKeyRef);  
  22.       
  23.     NSData *plainTextBytes = [plainText dataUsingEncoding:NSUTF8StringEncoding];  
  24.       
  25.     signedBytes = malloc( signedBytesSize * sizeof(uint8_t) ); // Malloc a buffer to hold signature.  
  26.     memset((voidvoid *)signedBytes, 0x0, signedBytesSize);  
  27.       
  28.     sanityCheck = SecKeyRawSign(privateKeyRef,  
  29.                                 kSecPaddingPKCS1SHA1,  
  30.                                 (const uint8_t *)[[self getHashBytes:plainTextBytes] bytes],  
  31.                                 kChosenDigestLength,  
  32.                                 (uint8_t *)signedBytes,  
  33.                                 &signedBytesSize);     
  34.       
  35.     if (sanityCheck == noErr)  
  36.     {  
  37.         signedHash = [NSData dataWithBytes:(const voidvoid *)signedBytes length:(NSUInteger)signedBytesSize];  
  38.     }  
  39.     else  
  40.     {  
  41.         return nil;  
  42.     }  
  43.   
  44.     if (signedBytes)  
  45.     {  
  46.         free(signedBytes);  
  47.     }  
  48.     NSString *signatureResult=[NSString stringWithFormat:@"%@",[signedHash base64EncodedString]];  
  49.     return signatureResult;  
  50. }  



[objc]  view plain copy
  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. }  

你可能感兴趣的:(iOS下使用SHA1WithRSA算法加签源码)