首先了解一下几个相关概念,以方便后面遇到的问题的解决:

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. - (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. }
  1. -(NSString *)signTheDataSHA1WithRSA:(NSString *)plainText
  2. {
  3. uint8_t* signedBytes = NULL;
  4. size_t signedBytesSize = ;
  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(NULL, , , NULL);
  13. OSStatus securityError = SecPKCS12Import((CFDataRef) data, (CFDictionaryRef)options, &items);
  14. if (securityError!=noErr) {
  15. return nil ;
  16. }
  17. CFDictionaryRef identityDict = CFArrayGetValueAtIndex(items, );
  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. }
  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. -(NSString *)RSAEncrypotoTheData:(NSString *)plainText
  17. {
  18.  
  19. SecKeyRef publicKey=nil;
  20. publicKey=[self getPublicKey];
  21. size_t cipherBufferSize = SecKeyGetBlockSize(publicKey);
  22. uint8_t *cipherBuffer = NULL;
  23.  
  24. cipherBuffer = malloc(cipherBufferSize * sizeof(uint8_t));
  25. memset((voidvoid *)cipherBuffer, *, cipherBufferSize);
  26.  
  27. NSData *plainTextBytes = [plainText dataUsingEncoding:NSUTF8StringEncoding];
  28. int blockSize = cipherBufferSize-; // 这个地方比较重要是加密问组长度
  29. int numBlock = (int)ceil([plainTextBytes length] / (double)blockSize);
  30. NSMutableData *encryptedData = [[NSMutableData alloc] init];
  31. for (int i=; i<numBlock; i++) {
  32. int bufferSize = MIN(blockSize,[plainTextBytes length]-i*blockSize);
  33. NSData *buffer = [plainTextBytes subdataWithRange:NSMakeRange(i * blockSize, bufferSize)];
  34. OSStatus status = SecKeyEncrypt(publicKey,
  35. kSecPaddingPKCS1,
  36. (const uint8_t *)[buffer bytes],
  37. [buffer length],
  38. cipherBuffer,
  39. &cipherBufferSize);
  40. if (status == noErr)
  41. {
  42. NSData *encryptedBytes = [[[NSData alloc]
  43. initWithBytes:(const voidvoid *)cipherBuffer
  44. length:cipherBufferSize] autorelease];
  45. [encryptedData appendData:encryptedBytes];
  46. }
  47. else
  48. {
  49. return nil;
  50. }
  51. }
  52. if (cipherBuffer)
  53. {
  54. free(cipherBuffer);
  55. }
  56. NSString *encrypotoResult=[NSString stringWithFormat:@"%@",[encryptedData base64EncodedString]];
  57. return encrypotoResult;
  58. }

相关链接:

iOS下使用SHA1WithRSA算法加签源码

iOS中使用RSA对数据进行加密解密

ios下使用RSA算法加密与java后台解密配合demo

android、ios与服务器端php使用rsa加密解密通讯

iOS下使用SHA1WithRSA算法加签源码

RSA implementations in Objective C

iOS下使用SHA1WithRSA算法加签源码的更多相关文章

  1. 业务类接口在TCP,HTTP,BLL模式下的实例 设计模式混搭 附源码一份

    业务类接口在TCP,HTTP,BLL模式下的实例 设计模式混搭 附源码一份 WinForm酒店管理软件--框架这篇随笔可以说是我写的最被大家争议的随笔,一度是支持和反对是一样的多.大家对我做的这个行业 ...

  2. OpenCV学习笔记(27)KAZE 算法原理与源码分析(一)非线性扩散滤波

    http://blog.csdn.net/chenyusiyuan/article/details/8710462 OpenCV学习笔记(27)KAZE 算法原理与源码分析(一)非线性扩散滤波 201 ...

  3. iOS Socket 整理以及CocoaAsyncSocket、SRWebSocket源码解析(一)

    写在准备动手的时候: Socket通讯在iOS中也是很常见,自己最近也一直在学习Telegram这个开源项目,Telegram就是在Socket的基础上做的即时通讯,这个相信了解这个开源项目的也都知道 ...

  4. iOS硬解H.264:-VideoToolboxDemo源码分析[草稿]

    来源:http://www.cnblogs.com/michaellfx/p/understanding_-VideoToolboxDemo.html iOS硬解H.264:-VideoToolbox ...

  5. 【转载】MacOS下IntelliJ IDEA关联JDK1.8源码

    原文地址: MacOS下IntelliJ IDEA关联JDK1.8源码 1 打开jdk设置,找到具体添加的地方 2 找到自己jdk的源码位置替换掉 3 如果没有源码或者源码没有下载解压,自己下载解压, ...

  6. iOS 即时通讯 + 仿微信聊天框架 + 源码

    这些你造吗? 即时通讯(IM),在IOS这片江湖里面已经算是一个老者了,我这小旋风也是在很早以前巡山的时候,就知道有即时通讯这个妖怪,以前也多多少少接触过一些,在造APP的时候用过,哎呀,说着说着就感 ...

  7. SM4密码算法(附源码)

    SM4是我们自己国家的一个分组密码算法,是国家密码管理局于2012年发布的.网址戳→_→:http://www.cnnic.NET.cn/jscx/mixbz/sm4/ 具体的密码标准和算法官方有非常 ...

  8. sm4算法(附源码、测试代码)

    from:http://blog.csdn.net/mao0514/article/details/52930944 SM4是我们自己国家的一个分组密码算法,是国家密码管理局于2012年发布的.网址戳 ...

  9. 推荐算法_CIKM-2019-AnalytiCup 冠军源码解读

    最近在帮一初创app写推荐系统,顺便学习一波用户兴趣高速检索的冠军算法. 写总结前贴出冠军代码的git地址:https://github.com/ChuanyuXue/CIKM-2019-Analyt ...

随机推荐

  1. 【读书笔记】iOS-GCD-Dispatch Source

    一,Dispatch Source是BSD系内核惯有功能kqueue的包装. 参考资料:<Objective-C高级编程 iOS与OS X多线程和内存管理>

  2. 【读书笔记】iOS-UIFont-如何知道字体的PostScript名称

    一,名词解释 PostScript字体: 按 PostScript 页面描述语言 (PDL) 规则定义的字体,并且只能在 PostScript 兼容的打印机上打印. 二,打开Launchpad---- ...

  3. Quartz2D学习笔记

    1.drawRect方法 //1.证明drawRect方法是在viewDidLoad后自动调用的,方便处理View的相关属性 // YQView * view = [[YQView alloc] in ...

  4. Web应用程序系统的多用户权限控制设计及实现-栏目模块【8】

    前五章均是从整体上讲述了Web应用程序的多用户权限控制实现流程,本章讲述Web权限管理系统的基本模块-栏目模块.栏目模块涉及到的数据表为目录表. 1.1栏目域 为了更规范和方便后期系统的二次开发和维护 ...

  5. unity学习网站汇总

    由于最近要学习unity3d 开发,把自己找来的资料汇总下 unity3D官方学习资源:https://www.assetstore.unity3d.com/ unity3D API查询网站:http ...

  6. [Eclipse配置] Eclipse代码中显示空白字符(空格,TAB和回车)的方法

    在代码页面点击右键进入 Preferences --> General --> Editors --> Text Editors. 在 Show whitespace charact ...

  7. 利用mysql对特殊字符和超长字符会进行截断的特性 进行存储型XSS攻击——WordPress <4.1.2 & <=4.2 存储型xss

    转自:Baidu Security LabXteam http://xteam.baidu.com/?p=177 漏洞概述 本次漏洞出现两个使用不同方式截断来实现的存储型xss,一种为特殊字符截断,一 ...

  8. 在SQL2008R2查询分析器出错(在执行批处理时出现错误。错误消息为: 目录名称无效。)

    在用SQL2008R2查询分析器时 SELECT * FROM 表名; 出错: 在执行批处理时出现错误.错误消息为: 目录名称无效. 原因: 在打开查询分析器时,用360软件清空了临时文件(只是偶尔1 ...

  9. 斐波那契数列 递归 尾递归 递推 C++实现

    ==================================声明================================== 本文原创,转载请注明作者和出处,并保证文章的完整性(包括本 ...

  10. 用Qemu模拟vexpress-a9 (四) --- u-boot引导kernel,用nfs挂载根文件系统

    环境介绍 Win7 64 + Vmware 11 + ubuntu14.04 32 u-boot 版本:u-boot-2015-04 Linux kernel版本:linux-3.16.y busyb ...