【IOS】 通过 OpenSSL 和系统内置方法生成 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函数中的第1个参数。
        NSMutableDictionary *privateKeyAttr = [[NSMutableDictionary alloc] init];
        NSMutableDictionary *publicKeyAttr = [[NSMutableDictionary alloc] init];
        NSMutableDictionary *keyPairAttr = [[NSMutableDictionary alloc] init];
        //把第1步中定义的字符串转换为NSData对象。
        NSData * publicTag = [NSData dataWithBytes:publicKeyIdentifier
                                            length:strlen((const char *)publicKeyIdentifier)];
        NSData * privateTag = [NSData dataWithBytes:privateKeyIdentifier
                                             length:strlen((const char *)privateKeyIdentifier)];
        //为公/私钥对准备SecKeyRef对象。
        SecKeyRef publicKey = NULL;
        SecKeyRef privateKey = NULL;
        //设置密钥对的密钥类型为RSA。
        [keyPairAttr setObject:(id)kSecAttrKeyTypeRSA forKey:(id)kSecAttrKeyType];
        //设置密钥对的密钥长度为1024。
        [keyPairAttr setObject:[NSNumber numberWithInt:keySize] forKey:(id)kSecAttrKeySizeInBits];
        //设置私钥的持久化属性(即是否存入钥匙串)为YES。
        [privateKeyAttr setObject:[NSNumber numberWithBool:YES] forKey:(id)kSecAttrIsPermanent];
        [privateKeyAttr setObject:privateTag forKey:(id)kSecAttrApplicationTag];
        //设置公钥的持久化属性(即是否存入钥匙串)为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);
            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) {
       /* 产生RSA密钥 */
       RSA *rsa = RSA_new();
       BIGNUM* e = BN_new();
       /* 设置随机数长度 */
       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 转化为字符串
+ (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);
       //此方法生成的是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格式的,暂时还没有找到转换方法.
 //此方法生成的是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();