【IOS】 通過 OpenSSL 和系統(tǒng)內(nèi)置方法生成 RSA 中的公鑰跟私鑰

=============蘋果自帶方法=====================

typedef void (^keyPair)(SecKeyRef publicKey ,SecKeyRef privateKey);
#pragma mark -  =============蘋果自帶方法=====================

+ (void)getRSAKeyPairWithKeySize:(int)keySize keyPair:(keyPair)pair;
{
    
    OSStatus status = noErr;
    if (keySize == 512 || keySize == 1024 || keySize == 2048) {
        
        //定義dictionary,用于傳遞SecKeyGeneratePair函數(shù)中的第1個(gè)參數(shù)。
        NSMutableDictionary *privateKeyAttr = [[NSMutableDictionary alloc] init];
        NSMutableDictionary *publicKeyAttr = [[NSMutableDictionary alloc] init];
        NSMutableDictionary *keyPairAttr = [[NSMutableDictionary alloc] init];
        
        //把第1步中定義的字符串轉(zhuǎn)換為NSData對象。
        NSData * publicTag = [NSData dataWithBytes:publicKeyIdentifier
                                            length:strlen((const char *)publicKeyIdentifier)];
        NSData * privateTag = [NSData dataWithBytes:privateKeyIdentifier
                                             length:strlen((const char *)privateKeyIdentifier)];
        //為公/私鑰對準(zhǔn)備SecKeyRef對象。
        SecKeyRef publicKey = NULL;
        SecKeyRef privateKey = NULL;
        //
        //設(shè)置密鑰對的密鑰類型為RSA。
        [keyPairAttr setObject:(id)kSecAttrKeyTypeRSA forKey:(id)kSecAttrKeyType];
        //設(shè)置密鑰對的密鑰長度為1024。
        [keyPairAttr setObject:[NSNumber numberWithInt:keySize] forKey:(id)kSecAttrKeySizeInBits];
        
        //設(shè)置私鑰的持久化屬性(即是否存入鑰匙串)為YES。
        [privateKeyAttr setObject:[NSNumber numberWithBool:YES] forKey:(id)kSecAttrIsPermanent];
        [privateKeyAttr setObject:privateTag forKey:(id)kSecAttrApplicationTag];
        
        //設(shè)置公鑰的持久化屬性(即是否存入鑰匙串)為YES。
        [publicKeyAttr setObject:[NSNumber numberWithBool:YES] forKey:(id)kSecAttrIsPermanent];
        [publicKeyAttr setObject:publicTag forKey:(id)kSecAttrApplicationTag];
        
        // 把私鑰的屬性集(dictionary)加到密鑰對的屬性集(dictionary)中。
        [keyPairAttr setObject:privateKeyAttr forKey:(id)kSecPrivateKeyAttrs];
        [keyPairAttr setObject:publicKeyAttr forKey:(id)kSecPublicKeyAttrs];
        
        //生成密鑰對
        status = SecKeyGeneratePair((CFDictionaryRef)keyPairAttr,&publicKey, &privateKey); // 13
        if (status == noErr && publicKey != NULL && privateKey != NULL) {
            pair(publicKey,privateKey);
        }
        else
            pair(publicKey,privateKey);
    }
    
}


==============OpenSSL 方式=================

#pragma mark - ==============OpenSSL 方式=================
#pragma mark ---生成密鑰對
+ (BOOL)generateRSAKeyPairWithKeySize:(int)keySize publicKey:(RSA **)publicKey privateKey:(RSA **)privateKey {
   
   if (keySize == 512 || keySize == 1024 || keySize == 2048) {
       
       /* 產(chǎn)生RSA密鑰 */
       RSA *rsa = RSA_new();
       BIGNUM* e = BN_new();
       
       /* 設(shè)置隨機(jī)數(shù)長度 */
       BN_set_word(e, 65537);
       
       /* 生成RSA密鑰對 */
       RSA_generate_key_ex(rsa, keySize, e, NULL);
       
       if (rsa) {
           *publicKey = RSAPublicKey_dup(rsa);
           *privateKey = RSAPrivateKey_dup(rsa);
           return YES;
       }
   }
   return NO;
}
#pragma mark ---RSA 轉(zhuǎn)化為字符串
+ (NSString *)PEMFormatRSAKey:(RSA *)rsaKey isPublic:(BOOL)isPublickey
{
   if (!rsaKey) {
       return nil;
   }
   
   BIO *bio = BIO_new(BIO_s_mem());
   if (isPublickey)
       PEM_write_bio_RSA_PUBKEY(bio, rsaKey);
   
   else
   {
       //此方法生成的是pkcs1格式的,IOS中需要pkcs8格式的,因此通過PEM_write_bio_PrivateKey 方法生成
       // PEM_write_bio_RSAPrivateKey(bio, rsaKey, NULL, NULL, 0, NULL, NULL);
       
       EVP_PKEY* key = NULL;
       key = EVP_PKEY_new();
       EVP_PKEY_assign_RSA(key, rsaKey);
       PEM_write_bio_PrivateKey(bio, key, NULL, NULL, 0, NULL, NULL);
   }
   
   BUF_MEM *bptr;
   BIO_get_mem_ptr(bio, &bptr);
   BIO_set_close(bio, BIO_NOCLOSE); /* So BIO_free() leaves BUF_MEM alone */
   BIO_free(bio);
   return [NSString stringWithUTF8String:bptr->data];
   
}


注意:
openssl 生成的私鑰為 pkcs1格式的,我們加密需要的是 pkcs8格式的,暫時(shí)還沒有找到轉(zhuǎn)換方法.
更新:

 //此方法生成的是pkcs1格式的,IOS中需要pkcs8格式的
   PEM_write_bio_RSAPrivateKey(bio, rsaKey, NULL, NULL, 0, NULL, NULL);

因此通過PEM_write_bio_PrivateKey 方法生成

        EVP_PKEY* key = NULL;
        key = EVP_PKEY_new();
        EVP_PKEY_assign_RSA(key, rsaKey);
        PEM_write_bio_PrivateKey(bio, key, NULL, NULL, 0, NULL, NULL);

Demo地址:https://github.com/yuying2012/WJDStudyLibrary
這是一個(gè)大工程,請從工程中尋找相關(guān)模塊代碼.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 嘟噥嘟噥:最近接到一個(gè)任務(wù):在客戶端動態(tài)生成RSA密鑰對,然后向服務(wù)器發(fā)送這個(gè)密鑰對中的公鑰字符串,由服務(wù)器進(jìn)行公...
    TimmyR閱讀 8,355評論 19 21
  • 三個(gè)小偷,一對雜貨鋪的父子,一個(gè)逃跑的小孩……今天晚上,這群角色活生生地將我?guī)нM(jìn)了他們的故事里頭。 一切的一切,都...
    TKJun閱讀 230評論 0 3
  • ZF 零標(biāo)志位(Zero Flag) 判斷結(jié)果是否為0。運(yùn)算結(jié)果0,ZF置1,否則置0。 PF 奇偶標(biāo)志位(Par...
    超人高飛閱讀 2,977評論 0 0

友情鏈接更多精彩內(nèi)容