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 = 0;
    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, 0, 0, NULL);
    OSStatus securityError = SecPKCS12Import((CFDataRef) data, (CFDictionaryRef)options, &items);
    if (securityError!=noErr) {
        return nil ;
    }
    CFDictionaryRef identityDict = CFArrayGetValueAtIndex(items, 0);
    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, 0*0, cipherBufferSize);  

    NSData *plainTextBytes = [plainText dataUsingEncoding:NSUTF8StringEncoding];
    int blockSize = cipherBufferSize-11;  // 这个地方比较重要是加密问组长度
    int numBlock = (int)ceil([plainTextBytes length] / (double)blockSize);
    NSMutableData *encryptedData = [[NSMutableData alloc] init];
    for (int i=0; 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;
} 

相关链接:

iOS下使用SHA1WithRSA算法加签源码

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

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

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

iOS下使用SHA1WithRSA算法加签源码

RSA implementations in Objective C

时间: 2024-10-13 11:59:34

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

Maxwin-z/XListView-Android(下拉刷新上拉加载)源码解析(一)

本次解析的内容,是github上一个用于下拉刷新上拉加载的控件xlistview,这个功能相信大家在开发的过程中会经常用到. 控件的源码地址是https://github.com/Maxwin-z/XListView-Android 在这个控件之前,我看过一些相同功能的控件,挑选后觉得XListView功能比较完善,而且易于理解.在android-open-project里面,有提到一个DropDownListView,个人使用过以后,觉得功能是具备了,但是操作体验不好,原因就是没有使用到Scr

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

写在准备动手的时候: Socket通讯在iOS中也是很常见,自己最近也一直在学习Telegram这个开源项目,Telegram就是在Socket的基础上做的即时通讯,这个相信了解这个开源项目的也都知道,希望自己能慢慢的了解一下它的这个MtProtoKit开源协议,即时通讯这一块的东西我以前写过一篇<iOS 即时通讯 + 仿微信聊天框架 + 源码>,从点击量看的出来真的这一块的东西我们的需求量还是很大,<iOS 即时通讯 + 仿微信聊天框架 + 源码>这篇文章由于自己去年也是能力有限

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

http://blog.csdn.net/chenyusiyuan/article/details/8710462 OpenCV学习笔记(27)KAZE 算法原理与源码分析(一)非线性扩散滤波 2013-03-23 17:44 16963人阅读 评论(28) 收藏 举报 分类: 机器视觉(34) 版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[+] KAZE系列笔记: OpenCV学习笔记(27)KAZE 算法原理与源码分析(一)非线性扩散滤波 OpenCV学习笔记(28)KA

插件式换肤框架搭建 - 资源加载源码分析

1. 概述 大部分控件我们都会使用,但是我们未必知道其资源加载的原理,目前换肤的框架比较多我们可以随随便便拿过来用,但早在几年前这些资料是比较少的,如果想做一个换肤的框架那就只能自己一点一点啃源码. 如果说我们现在不去用第三方的开源框架,要做一个换肤的功能,摆在我们面前的其实只有一个问题需要解决,那就是如何读取另外一个皮肤apk中的资源. 所有分享大纲:2017Android进阶之路与你同行 视频讲解地址:http://pan.baidu.com/s/1bC3lAQ 2. 资源加载源码分析 2.

iOS那些值得参考的App项目源码

iOS那些值得参考的App项目源码 https://cloud.tencent.com/developer/article/1332192 https://github.com/siegrainwong/WeChat iOS工具——Xcode9无证书真机调试 原文地址:https://www.cnblogs.com/kaola8023/p/12145642.html

ios下使用rsa算法与php进行加解密通讯

首先了解一下几个相关概念,以方便后面遇到的问题的解决: RSA算法:1977年由Ron Rivest.Adi Shamirh和LenAdleman发明的,RSA就是取自他们三个人的名字.算法基于一个数论:将两个大素数相乘非常容易,但要对这个乘积的结果进行因式分解却非常困难,因此可以把乘积公开作为公钥.该算法能够抵抗目前已知的所有密码攻击.RSA算法是一种非对称算法,算法需要一对密钥,使用其中一个加密,需要使用另外一个才能解密.我们在进行RSA加密通讯时,就把公钥放在客户端,私钥留在服务器. DE

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

首先了解一下几个相关概念,以方便后面遇到的问题的解决: 原网址:http://blog.csdn.net/jinglijun/article/details/7770315RSA算法:1977年由Ron Rivest.Adi Shamirh和LenAdleman发明的,RSA就是取自他们三个人的名字.算法基于一个数论:将两个大素数相乘非常容易,但要对这个乘积的结果进行因式分解却非常困难,因此可以把乘积公开作为公钥.该算法能够抵抗目前已知的所有密码攻击.RSA算法是一种非对称算法,算法需要一对密钥

【特征匹配】RANSAC算法原理与源码解析

转载请注明出处:http://blog.csdn.net/luoshixian099/article/details/50217655 随机抽样一致性(RANSAC)算法,可以在一组包含"外点"的数据集中,采用不断迭代的方法,寻找最优参数模型,不符合最优模型的点,被定义为"外点".在图像配准以及拼接上得到广泛的应用,本文将对RANSAC算法在OpenCV中角点误匹配对的检测中进行解析. 1.RANSAC原理 OpenCV中滤除误匹配对采用RANSAC算法寻找一个最佳

根据MATLAB的histeq函数改写的运行在OpenCV下的直方图规定化C源码!

据说,图像的直方图规定化比直方图均衡化用得更多,但是很奇怪的是OpenCV居然没有图像直方图规定化的源码!所以,我就有必要在OpenCV下写一个图像直方图规定化处理的函数,以方便将来使用. 我在网上找了几个直方图均稀化的源码,并基于OpenCV来改写这些源码,效果都不如MATLAB的histeq函数,这其中改写的艰辛与繁琐就不细说了.最后,没办法,只好学习MATALB的histeq函数源码,并对其进行基于OpenCV的改写. 虽然我最终改写成功了,但是对算法还是不太理解,只能按照MATLAB的帮