700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > iOS使用Security.framework进行RSA 加密解密签名和验证签名

iOS使用Security.framework进行RSA 加密解密签名和验证签名

时间:2024-04-25 16:21:34

相关推荐

iOS使用Security.framework进行RSA 加密解密签名和验证签名

iOS 上 Security.framework为我们提供了安全方面相关的api;

Security框架提供的RSA在iOS上使用的一些小结

支持的RSA keySize 大小有:512,768,1024,2048位支持的RSA 填充方式有三种:NOPadding,PKCS1,OAEP 三种方式 ,填充方式影响最大分组加密数据块的大小签名使用的填充方式PKCS1, 支持的签名算法有 sha1,sha256,sha224,sha384,sha512Nopadding填充最大数据块为 下面接口SecKeyGetBlockSize 大小;PKCS1 填充方式最大数据为SecKeyGetBlockSize大小 减去11OAEP 填充方式最大数据为SecKeyGetBlockSize 大小减去 42RSA加密解密签名,适合小块的数据处理,大量数量需要处理分组逻辑;密码学中推荐使用对称加密进行数据加密,使用RSA来加密对称密钥iOS10,以及mac 10.12中新增加了几个接口,以下测试用的是老接口,支持iOS2.0+

在这里说明一下RSA 相关的接口使用和示例;

1. 主要接口有

/*!//生成密钥对*/OSStatus SecKeyGeneratePair(CFDictionaryRef parameters, SecKeyRef * _Nullable CF_RETURNS_RETAINED publicKey,SecKeyRef * _Nullable CF_RETURNS_RETAINED privateKey) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0);//加密OSStatus SecKeyEncrypt(SecKeyRef key,SecPaddingpadding,const uint8_t *plainText,size_t plainTextLen,uint8_t *cipherText,size_t *cipherTextLen)__OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0);//解密OSStatus SecKeyDecrypt(SecKeyRef key,/* Private key */SecPaddingpadding, /* kSecPaddingNone,kSecPaddingPKCS1,kSecPaddingOAEP */const uint8_t *cipherText,size_t cipherTextLen, /* length of cipherText */uint8_t *plainText, size_t *plainTextLen) /* IN/OUT */__OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0);//签名OSStatus SecKeyRawSign(SecKeyRef key,SecPaddingpadding,const uint8_t *dataToSign,size_t dataToSignLen,uint8_t *sig,size_t *sigLen)__OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0);//验证签名OSStatus SecKeyRawVerify(SecKeyRef key,SecPaddingpadding,const uint8_t *signedData,size_t signedDataLen,const uint8_t *sig,size_t sigLen)__OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0);//分组加密的数据块大小size_t SecKeyGetBlockSize(SecKeyRef key)__OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0);

2. 首先生成RSA密钥对,生成1024位,即是 128字节

#define kRSA_KEY_SIZE 1024@interface ViewController : UIViewController{SecKeyRef publicKeyRef; //公钥SecKeyRef privateKeyRef;//私钥}//生成RSA密钥对,公钥和私钥,支持的SIZE有// sizes for RSA keys are: 512, 768, 1024, 2048.- (void)generateRSAKeyPair:(int )keySize{OSStatus ret = 0;publicKeyRef = NULL;privateKeyRef = NULL;ret = SecKeyGeneratePair((CFDictionaryRef)@{(id)kSecAttrKeyType:(id)kSecAttrKeyTypeRSA,(id)kSecAttrKeySizeInBits:@(keySize)}, &publicKeyRef, &privateKeyRef);NSAssert(ret==errSecSuccess, @"密钥对生成失败:%d",ret);NSLog(@"%@",publicKeyRef);NSLog(@"%@",privateKeyRef);NSLog(@"max size:%lu",SecKeyGetBlockSize(privateKeyRef));}

3. 使用上面生成的密钥对进行加密解密测试

//公钥加密私钥密钥测试/** 三种填充方式区别kSecPaddingNone= 0, 要加密的数据块大小<=SecKeyGetBlockSize的大小,如这里128kSecPaddingPKCS1= 1, 要加密的数据块大小<=128-11kSecPaddingOAEP= 2, 要加密的数据块大小<=128-42密码学中的设计原则,一般用RSA来加密 对称密钥,用对称密钥加密大量的数据非对称加密速度慢,对称加密速度快*/- (void)testRSAEncryptAndDecrypt{[self generateRSAKeyPair:kRSA_KEY_SIZE];NSData *srcData = [@"0123456789" dataUsingEncoding:NSUTF8StringEncoding];NSLog(@"%@",srcData);uint8_t encData[kRSA_KEY_SIZE/8] = {0};uint8_t decData[kRSA_KEY_SIZE/8] = {0};size_t blockSize = kRSA_KEY_SIZE / 8 ;OSStatus ret;ret = SecKeyEncrypt(publicKeyRef, kSecPaddingNone, srcData.bytes, srcData.length, encData, &blockSize);NSAssert(ret==errSecSuccess, @"加密失败");ret = SecKeyDecrypt(privateKeyRef, kSecPaddingNone, encData, blockSize, decData, &blockSize);NSAssert(ret==errSecSuccess, @"解密失败");NSData *dedData = [NSData dataWithBytes:decData length:blockSize];NSLog(@"dec:%@",dedData);if (memcmp(srcData.bytes, dedData.bytes, srcData.length)==0) {NSLog(@"PASS");}}

4. 使用公钥密钥进行数据签名和验证签名

对数据签名:首先对原始数据进行hash计算,可以得到数据的hash值;然后对hash值进行签名;

- (void)testSignAndVerify{[self generateRSAKeyPair:kRSA_KEY_SIZE];NSString *tpath = [[NSBundle mainBundle] pathForResource:@"src.txt" ofType:nil];NSData *ttDt = [NSData dataWithContentsOfFile:tpath];

//使用了下面封装的hash接口NSData *sha1dg = [ttDt hashDataWith:CCDIGEST_SHA1];OSStatus ret;//私钥签名,公钥验证签名size_t siglen = SecKeyGetBlockSize(privateKeyRef);uint8_t *sig = malloc(siglen);bzero(sig, siglen);ret = SecKeyRawSign(privateKeyRef, kSecPaddingPKCS1SHA256, sha1dg.bytes, sha1dg.length, sig, &siglen);NSAssert(ret==errSecSuccess, @"签名失败");ret = SecKeyRawVerify(publicKeyRef, kSecPaddingPKCS1SHA256, sha1dg.bytes, sha1dg.length,sig, siglen);NSAssert(ret==errSecSuccess, @"验证签名失败");if (ret==errSecSuccess) {NSLog(@"SIGN VERIFY PASS");}}

5. 另外 iOS上CommonCrypto/CommonDigest.h 中提供了密码学中常用的hash算法

如下我封装了一个NSData的分类,可以在签名中直接使用

支持的hash算法有 md2,md4,md5,sha1,sha224,sha256,sha384,sha512

//// NSData+KKHASH.h// SecurityiOS//// Created by cocoa on 16/12/15.// Copyright © dev.keke@. All rights reserved.//#import <Foundation/Foundation.h>typedef enum : NSUInteger {//md2 16字节长度CCDIGEST_MD2 = 1000,//md4 16字节长度 CCDIGEST_MD4,//md5 16字节长度 CCDIGEST_MD5,//sha1 20字节长度 CCDIGEST_SHA1,//SHA224 28字节长度 CCDIGEST_SHA224,//SHA256 32字节长度 CCDIGEST_SHA256,//SHA384 48字节长度 CCDIGEST_SHA384,//SHA512 64字节长度 CCDIGEST_SHA512,} CCDIGESTAlgorithm;@interface NSData (KKHASH)/**计算数据的hash值,根据不同的算法*/- (NSData *)hashDataWith:(CCDIGESTAlgorithm )ccAlgorithm;/**返回 hex string的 data*/- (NSString *)hexString;@end

View Code

//// NSData+KKHASH.m// SecurityiOS//// Created by cocoa on 16/12/15.// Copyright © dev.keke@. All rights reserved.//#import "NSData+KKHASH.h"#include <CommonCrypto/CommonDigest.h>@implementation NSData (KKHASH)- (NSData *)hashDataWith:(CCDIGESTAlgorithm )ccAlgorithm{NSData *retData = nil;if (self.length <1) {return nil;}unsigned char *md;switch (ccAlgorithm) {case CCDIGEST_MD2:{md = malloc(CC_MD2_DIGEST_LENGTH);bzero(md, CC_MD2_DIGEST_LENGTH);CC_MD2(self.bytes, (CC_LONG)self.length, md);retData = [NSData dataWithBytes:md length:CC_MD2_DIGEST_LENGTH];}break;case CCDIGEST_MD4:{md = malloc(CC_MD4_DIGEST_LENGTH);bzero(md, CC_MD4_DIGEST_LENGTH);CC_MD4(self.bytes, (CC_LONG)self.length, md);retData = [NSData dataWithBytes:md length:CC_MD4_DIGEST_LENGTH];}break;case CCDIGEST_MD5:{md = malloc(CC_MD5_DIGEST_LENGTH);bzero(md, CC_MD5_DIGEST_LENGTH);CC_MD5(self.bytes, (CC_LONG)self.length, md);retData = [NSData dataWithBytes:md length:CC_MD5_DIGEST_LENGTH];}break;case CCDIGEST_SHA1:{md = malloc(CC_SHA1_DIGEST_LENGTH);bzero(md, CC_SHA1_DIGEST_LENGTH);CC_SHA1(self.bytes, (CC_LONG)self.length, md);retData = [NSData dataWithBytes:md length:CC_SHA1_DIGEST_LENGTH];}break;case CCDIGEST_SHA224:{md = malloc(CC_SHA224_DIGEST_LENGTH);bzero(md, CC_SHA224_DIGEST_LENGTH);CC_SHA224(self.bytes, (CC_LONG)self.length, md);retData = [NSData dataWithBytes:md length:CC_SHA224_DIGEST_LENGTH];}break;case CCDIGEST_SHA256:{md = malloc(CC_SHA256_DIGEST_LENGTH);bzero(md, CC_SHA256_DIGEST_LENGTH);CC_SHA256(self.bytes, (CC_LONG)self.length, md);retData = [NSData dataWithBytes:md length:CC_SHA256_DIGEST_LENGTH];}break;case CCDIGEST_SHA384:{md = malloc(CC_SHA384_DIGEST_LENGTH);bzero(md, CC_SHA384_DIGEST_LENGTH);CC_SHA384(self.bytes, (CC_LONG)self.length, md);retData = [NSData dataWithBytes:md length:CC_SHA384_DIGEST_LENGTH];}break;case CCDIGEST_SHA512:{md = malloc(CC_SHA512_DIGEST_LENGTH);bzero(md, CC_SHA512_DIGEST_LENGTH);CC_SHA512(self.bytes, (CC_LONG)self.length, md);retData = [NSData dataWithBytes:md length:CC_SHA512_DIGEST_LENGTH];}break;default:md = malloc(1);break;}free(md);md = NULL;return retData;}- (NSString *)hexString{NSMutableString *result = nil;if (self.length <1) {return nil;}result = [[NSMutableString alloc] initWithCapacity:self.length * 2];for (size_t i = 0; i < self.length; i++) {[result appendFormat:@"%02x", ((const uint8_t *) self.bytes)[i]];}return result;}@end

View Code

6. 另外如果密钥由服务器生成,可以生成p12文件,来在ios上调用接口导入开发

OSStatus SecPKCS12Import(CFDataRef pkcs12_data, CFDictionaryRef options,CFArrayRef * __nonnull CF_RETURNS_RETAINED items) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0);

7. 另外为了配合验证,可以用openssl 命令对数据进行RSA加密解密

//使用公钥加密 1024位密钥 ,128字节//openssl rsautl -encrypt -out pubenc.txt -in src.txt -inkey public.pem -pubin//使用私钥解密//openssl rsautl -decrypt -in pubenc.txt -inkey private.pem -out pridec.txt

总结:

另外RSA密钥,私钥保存在手机上是不安全的;

一般在非越狱的手机上,我们可以把生成的SecKeyRef 保存在 keychain中;

但是在越狱的手机上,也是不安全的,因为可以导出keychain中的所有数据;

没有绝对的安全,根据业务场景来实际开发吧

封装工具:/cocoajin/Security-iOS

参考:

/library/content/documentation/Security/Conceptual/cryptoservices/CryptographyConcepts/CryptographyConcepts.html#//apple_ref/doc/uid/TP40011172-CH8-SW1

/library/content/samplecode/CryptoExercise/Introduction/Intro.html#//apple_ref/doc/uid/DTS40008019

/library/content/samplecode/CryptoCompatibility/Introduction/Intro.html#//apple_ref/doc/uid/DTS40013654

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。