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,sha512
  • Nopadding填充最大数据块为 下面接口 SecKeyGetBlockSize 大小; 
  • PKCS1 填充方式最大数据为 SecKeyGetBlockSize大小 减去11
  • OAEP 填充方式最大数据为 SecKeyGetBlockSize 大小减去 42
  • RSA加密解密签名,适合小块的数据处理,大量数量需要处理分组逻辑;密码学中推荐使用对称加密进行数据加密,使用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,
    SecPadding          padding,
    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 */
    SecPadding          padding,            /* 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,
    SecPadding          padding,
    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,
    SecPadding          padding,
    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的大小,如这里128
 kSecPaddingPKCS1     = 1,   要加密的数据块大小<=128-11
 kSecPaddingOAEP      = 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

 View Code

 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中的所有数据;

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

 封装工具:https://github.com/cocoajin/Security-iOS

参考:

https://developer.apple.com/library/content/documentation/Security/Conceptual/cryptoservices/CryptographyConcepts/CryptographyConcepts.html#//apple_ref/doc/uid/TP40011172-CH8-SW1

https://developer.apple.com/library/content/samplecode/CryptoExercise/Introduction/Intro.html#//apple_ref/doc/uid/DTS40008019

https://developer.apple.com/library/content/samplecode/CryptoCompatibility/Introduction/Intro.html#//apple_ref/doc/uid/DTS40013654

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值