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位
- (NSData *)getHashBytes:(NSData *)plainText {
    CC_SHA1_CTX ctx;
    uint8_t * hashBytes = NULL;
    NSData * hash = nil;  
    // Malloc a buffer to hold hash.
    hashBytes = malloc( kChosenDigestLength * sizeof(uint8_t) );
    memset((voidvoid *)hashBytes, 0x0, kChosenDigestLength);
    // Initialize the context.
    CC_SHA1_Init(&ctx);
    // Perform the hash.
    CC_SHA1_Update(&ctx, (voidvoid *)[plainText bytes], [plainText length]);
    // Finalize the output.
    CC_SHA1_Final(hashBytes, &ctx);  
    // Build up the SHA1 blob.
    hash = [NSData dataWithBytes:(const voidvoid *)hashBytes length:(NSUInteger)kChosenDigestLength];
    if (hashBytes) free(hashBytes);  
    return hash;
}
-(NSString *)signTheDataSHA1WithRSA:(NSString *)plainText
{
uint8_t* signedBytes = NULL;
size_t signedBytesSize = ;
OSStatus sanityCheck = noErr;
NSData* signedHash = nil; NSString * path = [[NSBundle mainBundle]pathForResource:@"keystore" ofType:@"p12"];
NSData * data = [NSData dataWithContentsOfFile:path];
NSMutableDictionary * options = [[NSMutableDictionary alloc] init]; // Set the private key query dictionary.
[options setObject:@"你的p12文件的密码" forKey:(id)kSecImportExportPassphrase];
CFArrayRef items = CFArrayCreate(NULL, , , NULL);
OSStatus securityError = SecPKCS12Import((CFDataRef) data, (CFDictionaryRef)options, &items);
if (securityError!=noErr) {
return nil ;
}
CFDictionaryRef identityDict = CFArrayGetValueAtIndex(items, );
SecIdentityRef identityApp =(SecIdentityRef)CFDictionaryGetValue(identityDict,kSecImportItemIdentity);
SecKeyRef privateKeyRef=nil;
SecIdentityCopyPrivateKey(identityApp, &privateKeyRef);
signedBytesSize = SecKeyGetBlockSize(privateKeyRef); NSData *plainTextBytes = [plainText dataUsingEncoding:NSUTF8StringEncoding]; signedBytes = malloc( signedBytesSize * sizeof(uint8_t) ); // Malloc a buffer to hold signature.
memset((voidvoid *)signedBytes, 0x0, signedBytesSize); sanityCheck = SecKeyRawSign(privateKeyRef,
kSecPaddingPKCS1SHA1,
(const uint8_t *)[[self getHashBytes:plainTextBytes] bytes],
kChosenDigestLength,
(uint8_t *)signedBytes,
&signedBytesSize); if (sanityCheck == noErr)
{
signedHash = [NSData dataWithBytes:(const voidvoid *)signedBytes length:(NSUInteger)signedBytesSize];
}
else
{
return nil;
} if (signedBytes)
{
free(signedBytes);
}
NSString *signatureResult=[NSString stringWithFormat:@"%@",[signedHash base64EncodedString]];
return signatureResult;
}
-(SecKeyRef)getPublicKey{
    NSString *certPath = [[NSBundle mainBundle] pathForResource:@"keystore" ofType:@"p7b"];
    SecCertificateRef myCertificate = nil;
    NSData *certificateData = [[NSData alloc] initWithContentsOfFile:certPath];
    myCertificate = SecCertificateCreateWithData(kCFAllocatorDefault, (CFDataRef)certificateData);
    SecPolicyRef myPolicy = SecPolicyCreateBasicX509();
    SecTrustRef myTrust;
    OSStatus status = SecTrustCreateWithCertificates(myCertificate,myPolicy,&myTrust);
    SecTrustResultType trustResult;
    if (status == noErr) {
        status = SecTrustEvaluate(myTrust, &trustResult);
    }
    return SecTrustCopyPublicKey(myTrust);
}  
-(NSString *)RSAEncrypotoTheData:(NSString *)plainText
{  
    SecKeyRef publicKey=nil;
    publicKey=[self getPublicKey];
    size_t cipherBufferSize = SecKeyGetBlockSize(publicKey);
    uint8_t *cipherBuffer = NULL;   
    cipherBuffer = malloc(cipherBufferSize * sizeof(uint8_t));
    memset((voidvoid *)cipherBuffer, *, cipherBufferSize);  
    NSData *plainTextBytes = [plainText dataUsingEncoding:NSUTF8StringEncoding];
    int blockSize = cipherBufferSize-;  // 这个地方比较重要是加密问组长度
    int numBlock = (int)ceil([plainTextBytes length] / (double)blockSize);
    NSMutableData *encryptedData = [[NSMutableData alloc] init];
    for (int i=; i<numBlock; i++) {
        int bufferSize = MIN(blockSize,[plainTextBytes length]-i*blockSize);
        NSData *buffer = [plainTextBytes subdataWithRange:NSMakeRange(i * blockSize, bufferSize)];
        OSStatus status = SecKeyEncrypt(publicKey,
                                        kSecPaddingPKCS1,
                                        (const uint8_t *)[buffer bytes],
                                        [buffer length],
                                        cipherBuffer,
                                        &cipherBufferSize);
        if (status == noErr)
        {
            NSData *encryptedBytes = [[[NSData alloc]
                                       initWithBytes:(const voidvoid *)cipherBuffer
                                       length:cipherBufferSize] autorelease];
            [encryptedData appendData:encryptedBytes];
        }
        else
        {
            return nil;
        }
    }
    if (cipherBuffer)
    {
        free(cipherBuffer);
    }
    NSString *encrypotoResult=[NSString stringWithFormat:@"%@",[encryptedData base64EncodedString]];
    return encrypotoResult;
} 
相关链接:
android、ios与服务器端php使用rsa加密解密通讯
RSA implementations in Objective C
iOS下使用SHA1WithRSA算法加签源码的更多相关文章
- 业务类接口在TCP,HTTP,BLL模式下的实例 设计模式混搭 附源码一份
		业务类接口在TCP,HTTP,BLL模式下的实例 设计模式混搭 附源码一份 WinForm酒店管理软件--框架这篇随笔可以说是我写的最被大家争议的随笔,一度是支持和反对是一样的多.大家对我做的这个行业 ... 
- OpenCV学习笔记(27)KAZE 算法原理与源码分析(一)非线性扩散滤波
		http://blog.csdn.net/chenyusiyuan/article/details/8710462 OpenCV学习笔记(27)KAZE 算法原理与源码分析(一)非线性扩散滤波 201 ... 
- iOS Socket 整理以及CocoaAsyncSocket、SRWebSocket源码解析(一)
		写在准备动手的时候: Socket通讯在iOS中也是很常见,自己最近也一直在学习Telegram这个开源项目,Telegram就是在Socket的基础上做的即时通讯,这个相信了解这个开源项目的也都知道 ... 
- iOS硬解H.264:-VideoToolboxDemo源码分析[草稿]
		来源:http://www.cnblogs.com/michaellfx/p/understanding_-VideoToolboxDemo.html iOS硬解H.264:-VideoToolbox ... 
- 【转载】MacOS下IntelliJ IDEA关联JDK1.8源码
		原文地址: MacOS下IntelliJ IDEA关联JDK1.8源码 1 打开jdk设置,找到具体添加的地方 2 找到自己jdk的源码位置替换掉 3 如果没有源码或者源码没有下载解压,自己下载解压, ... 
- iOS  即时通讯 + 仿微信聊天框架 + 源码
		这些你造吗? 即时通讯(IM),在IOS这片江湖里面已经算是一个老者了,我这小旋风也是在很早以前巡山的时候,就知道有即时通讯这个妖怪,以前也多多少少接触过一些,在造APP的时候用过,哎呀,说着说着就感 ... 
- SM4密码算法(附源码)
		SM4是我们自己国家的一个分组密码算法,是国家密码管理局于2012年发布的.网址戳→_→:http://www.cnnic.NET.cn/jscx/mixbz/sm4/ 具体的密码标准和算法官方有非常 ... 
- sm4算法(附源码、测试代码)
		from:http://blog.csdn.net/mao0514/article/details/52930944 SM4是我们自己国家的一个分组密码算法,是国家密码管理局于2012年发布的.网址戳 ... 
- 推荐算法_CIKM-2019-AnalytiCup 冠军源码解读
		最近在帮一初创app写推荐系统,顺便学习一波用户兴趣高速检索的冠军算法. 写总结前贴出冠军代码的git地址:https://github.com/ChuanyuXue/CIKM-2019-Analyt ... 
随机推荐
- GetReadyForWin10Develop
			GetReadyForWin10Develop 序言 今年4月29日晚的微软的Build大会上,微软在现场为我们演示了Android和IOS应用移植到windows平台,加上原本可以开发win8应用的 ... 
- Force.com微信开发系列(七)OAuth2.0网页授权
			OAuth是一个开放协议,允许用户让第三方应用以安全且标准的方式获取该用户在某一网站上存储的私密资源(如用户个人信息.照片.视频.联系人列表),而无须将用户名和密码提供给第三方应用.本文将详细介绍OA ... 
- 【转】Android Studio中通过快捷键来提取提取方法
			今天来给大家介绍一个非常有用的Studio Tips,有些时候我们在一个方法内部写了过多的代码,然后想要把一些代码提取出来再放在一个单独的方法里,通常我们的做法是复制粘贴,现在我来教给大家一个非常简洁 ... 
- Android项目实战(二):安卓应用程序退出的三种方法
			现在的APP退出的时候都不是让用户点击了“后退键”就退出.防止用户点错了后退键而造成的用户体检不好. 一年前搞的Demo代码不见了,重新写下就当是复习和以后直接拿来用把 目前流行的解决一般分为两种: ... 
- JAVA基础学习day19--IO流一、FileWrite与FileReader
			一.IO简述 1.1.简述 IO:input/output IO流用来处理设备之间的数据传输 Java对数据的操作是通过流的方式 Java用于操作流的对象都在IO包中. 1.2.结构 字节流抽象类: ... 
- iOSQuartz2D-04-手动剪裁图片并保存到相册
			实现效果 操作步骤 绘制一个矩形框,弹出一个alertView,提示是否保存图片 点击"是",将图片保存到相册 在相册中查看保存的图片 效果图 实现思路 在控制器的view上添加一 ... 
- leangoo更换背景、设置颜色标签功能上线啦!
			leangoo看板背景太单调?卡片标签想要添加多个?没有问题,Leangoo的本次更新就给大家带来了漂亮背景和实用的颜色标签设置,接下来就让我们一起来看看吧! 设置背景: 点击看板右上角个人头像图标按 ... 
- 《ASP.NET MVC 5 框架揭秘》
			<ASP.NET MVC 5 框架揭秘> 基本信息 作者: 蒋金楠 出版社:电子工业出版社 ISBN:9787121237812 上架时间:2014-8-1 出版日期:2014 年8月 开 ... 
- JavaScript Patterns 3.4 Array Literal
			Array Literal Syntax To avoid potential errors when creating dynamic arrays at runtime, it's much sa ... 
- SQLServer中char与varchar的区别
			今天写一个项目的用户登录部分 刚开始做,所以是数据库和程序一起写 一开始没注意 在定义表T_Person时吧PerID和PerPwd的类型设定都是char(20) 并且写入了几个数据,诸如 id:01 ... 
