美文网首页swift编程开发iOS之路iOS开发进阶
iOS 原生RSA加解密 及生成密钥对

iOS 原生RSA加解密 及生成密钥对

作者: XPorter | 来源:发表于2016-08-11 14:42 被阅读992次

    iOS 不仅提供了RSA加解密,签名验签的功能,同时还提供了生成密钥对的方法。

    SecKeyEncrypt (解密)
    SecKeyDecrypt(解密)
    SecKeyGeneratePair(生成密钥对)
    

    关于分段加密
    因为RSA是需要分段加密的,每一段的长度不能大于密钥的长度SecKeyGetBlockSize(keyRef),一般为128(1024bit的密钥)字节。
    但是由于RSA加密会设置填充模式,常用的模式为RSA_PKCS1_PADDING,在这种模式下,每次加密的明文长度需要再减少11个字节,所以在分段的时候每段的长度为 128 - 11 = 117 ;

    size_t src_block_size = block_size - 11;
    

    iOS 原生生成RSA密钥对的类型为SecKeyRef类型,也可以将 SecKeyRef 类型转换为NSData。这里生成的数据只包含了公钥的信息,不是标准的PEM格式的文件,如果需要PEM格式需要添加PEM头信息

    - (NSData *)getKeyBitsWithKeyIdentifier:(NSString *)keyIdentifier {
    
        if (!keyIdentifier) {
            return nil;
        }
        NSData *keyBits = nil;
        OSStatus sanityCheck = noErr;
        
        NSData * peerTag = [keyIdentifier dataUsingEncoding:NSUTF8StringEncoding];
        NSMutableDictionary * queryAttributes = [[NSMutableDictionary alloc] init];
        [queryAttributes setObject:(id)kSecClassKey forKey:(id)kSecClass];
        [queryAttributes setObject:(id)kSecAttrKeyTypeRSA forKey:(id)kSecAttrKeyType];
        [queryAttributes setObject:peerTag forKey:(id)kSecAttrApplicationTag];
        [queryAttributes setObject:[NSNumber numberWithBool:YES] forKey:(id)kSecReturnData];
        
        CFTypeRef result = NULL;
        sanityCheck = SecItemCopyMatching((CFDictionaryRef) queryAttributes, &result);
        if (sanityCheck == noErr || sanityCheck == errSecDuplicateItem) {
            keyBits = CFBridgingRelease(result);
            return keyBits;
        }
        return nil;
    }
    

    在设置queryAttributes 的参数中,下面这行

    [queryAttributes setObject:[NSNumber numberWithBool:YES] forKey:(id)kSecReturnData];
    

    key有三种类型可选

    kSecReturnData
    kSecReturnRef
    kSecReturnPersistentRef

    如果选kSecReturnPersistentRef类型,可用下面的方法转换

    - (SecKeyRef)getKeyRefWithPersistentKeyRef:(CFTypeRef)persistentRef {
    
        OSStatus sanityCheck = noErr;
        SecKeyRef keyRef = NULL;
        if (persistentRef == NULL) {
            //@"persistentRef object cannot be NULL."
            return nil;
        }
        
        NSMutableDictionary * queryKey = [[NSMutableDictionary alloc] init];
        
        // Set the SecKeyRef query dictionary.
        [queryKey setObject:(__bridge id)persistentRef forKey:(id)kSecValuePersistentRef];
        [queryKey setObject:[NSNumber numberWithBool:YES] forKey:(id)kSecReturnRef];
        
        // Get the persistent key reference.
        sanityCheck = SecItemCopyMatching((CFDictionaryRef)queryKey, (CFTypeRef *)&keyRef);
        
        return keyRef;
    }
    
    

    demo一份
    官方代码地址

    相关文章

      网友评论

      • 冰之与火焰:需要加什么头文件或者framework吗,我这里报错了
        冰之与火焰:@黑白灰_lve 没有这个写法把?
        冰之与火焰:@黑白灰_lve const void values[] = { kSecAttrKeyTypeRSA, keySize };这句话在oc里报错额
        XPorter:@18758587125 #import <Security/Security.h>

      本文标题:iOS 原生RSA加解密 及生成密钥对

      本文链接:https://www.haomeiwen.com/subject/loqssttx.html