You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS 10之前版本Objective-C实现RSA OAEP SHA256加密技术问询

iOS 10及以下版本RSA OAEP-SHA256加密适配方案

Hey there! I see you've already got RSA encryption working with kSecKeyAlgorithmRSAEncryptionOAEPSHA256 on newer iOS versions, and now need to adapt it for iOS 10 and earlier. The core issue here is that kSecKeyAlgorithmRSAEncryptionOAEPSHA256 was introduced in iOS 10—so we need alternative approaches for older systems. Let's break down two reliable solutions:

方案1:降级使用PKCS#1 v1.5填充(服务器需配合调整)

If your server team can adjust their decryption logic to support both OAEP and PKCS#1 v1.5, this is the simplest approach since it uses Apple's native Security framework without third-party dependencies.

代码实现

Add version checking to switch between algorithms based on the iOS version:

SecKeyRef keyRef = [self addPublicKey:pubKey];
if (!keyRef) {
    return nil;
}

NSData *encryptedData = nil;
CFErrorRef error = NULL;

if (@available(iOS 10.0, *)) {
    // 高版本使用OAEP-SHA256
    SecKeyAlgorithm algorithm = kSecKeyAlgorithmRSAEncryptionOAEPSHA256;
    if (SecKeyIsAlgorithmSupported(keyRef, kSecKeyOperationTypeEncrypt, algorithm)) {
        encryptedData = (__bridge_transfer NSData *)SecKeyCreateEncryptedData(keyRef, algorithm, (__bridge CFDataRef)plainData, &error);
    }
} else {
    // iOS 10及以下使用PKCS#1 v1.5
    SecKeyAlgorithm algorithm = kSecKeyAlgorithmRSAEncryptionPKCS1;
    if (SecKeyIsAlgorithmSupported(keyRef, kSecKeyOperationTypeEncrypt, algorithm)) {
        encryptedData = (__bridge_transfer NSData *)SecKeyCreateEncryptedData(keyRef, algorithm, (__bridge CFDataRef)plainData, &error);
    }
}

if (error) {
    NSLog(@"Encryption error: %@", error);
    CFRelease(error);
}
CFRelease(keyRef);
return encryptedData;

注意事项

  • Make sure your server updates its decryption code to handle both padding schemes. For example, in Java, this would mean checking the iOS version from the request (or trying both paddings if possible) to use OAEPWithSHA-256AndMGF1Padding or PKCS1Padding accordingly.

方案2:使用OpenSSL实现OAEP-SHA256(无需修改服务器)

If your server can't change its decryption logic and must use OAEP-SHA256, you'll need to use a third-party library like OpenSSL to implement the encryption on iOS 10 and below.

步骤1:集成OpenSSL

You can add OpenSSL to your project via CocoaPods by adding this to your Podfile:

pod 'OpenSSL-Universal'

Run pod install to set it up.

步骤2:OAEP-SHA256加密代码实现

Here's a helper method to encrypt data using OpenSSL's OAEP-SHA256 implementation:

#import <openssl/rsa.h>
#import <openssl/pem.h>
#import <openssl/err.h>

- (NSData *)rsaOAEPEncryptWithOpenSSL:(NSData *)plainData publicKey:(NSString *)pubKey {
    // 将PEM格式公钥转换为OpenSSL的EVP_PKEY
    BIO *bio = BIO_new_mem_buf((void *)[pubKey UTF8String], (int)[pubKey length]);
    EVP_PKEY *pkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL);
    BIO_free(bio);
    
    if (!pkey) {
        NSLog(@"Failed to load public key");
        ERR_print_errors_fp(stderr);
        return nil;
    }
    
    EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(pkey, NULL);
    if (!ctx || EVP_PKEY_encrypt_init(ctx) <= 0) {
        NSLog(@"Failed to init encryption context");
        EVP_PKEY_free(pkey);
        return nil;
    }
    
    // 设置OAEP-SHA256参数
    if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) <= 0 ||
        EVP_PKEY_CTX_set_rsa_oaep_md(ctx, EVP_sha256()) <= 0) {
        NSLog(@"Failed to set OAEP parameters");
        EVP_PKEY_CTX_free(ctx);
        EVP_PKEY_free(pkey);
        return nil;
    }
    
    // 计算加密后的数据长度
    size_t outLen = 0;
    if (EVP_PKEY_encrypt(ctx, NULL, &outLen, plainData.bytes, plainData.length) <= 0) {
        NSLog(@"Failed to calculate output length");
        EVP_PKEY_CTX_free(ctx);
        EVP_PKEY_free(pkey);
        return nil;
    }
    
    // 分配内存并执行加密
    unsigned char *outBuf = malloc(outLen);
    if (EVP_PKEY_encrypt(ctx, outBuf, &outLen, plainData.bytes, plainData.length) <= 0) {
        NSLog(@"Encryption failed");
        ERR_print_errors_fp(stderr);
        free(outBuf);
        EVP_PKEY_CTX_free(ctx);
        EVP_PKEY_free(pkey);
        return nil;
    }
    
    NSData *encryptedData = [NSData dataWithBytes:outBuf length:outLen];
    free(outBuf);
    EVP_PKEY_CTX_free(ctx);
    EVP_PKEY_free(pkey);
    
    return encryptedData;
}

步骤3:版本判断整合

Combine this with version checking to use native framework on iOS 10+ and OpenSSL on older versions:

SecKeyRef keyRef = [self addPublicKey:pubKey];
if (!keyRef) {
    return nil;
}

NSData *encryptedData = nil;
CFErrorRef error = NULL;

if (@available(iOS 10.0, *)) {
    SecKeyAlgorithm algorithm = kSecKeyAlgorithmRSAEncryptionOAEPSHA256;
    if (SecKeyIsAlgorithmSupported(keyRef, kSecKeyOperationTypeEncrypt, algorithm)) {
        encryptedData = (__bridge_transfer NSData *)SecKeyCreateEncryptedData(keyRef, algorithm, (__bridge CFDataRef)plainData, &error);
    }
    CFRelease(keyRef);
} else {
    // iOS 10及以下使用OpenSSL实现OAEP-SHA256
    encryptedData = [self rsaOAEPEncryptWithOpenSSL:plainData publicKey:pubKey];
}

if (error) {
    NSLog(@"Encryption error: %@", error);
    CFRelease(error);
}

return encryptedData;

注意事项

  • Ensure your public key is in PEM format (starts with -----BEGIN PUBLIC KEY----- and ends with -----END PUBLIC KEY-----). If you're using a DER format key, you'll need to convert it to PEM first.
  • Always clean up OpenSSL resources (like EVP_PKEY, EVP_PKEY_CTX, BIO) to avoid memory leaks.

最后建议

  • Test both implementations thoroughly on iOS 9/10 devices to ensure compatibility.
  • If possible, prefer the native Security framework approach (方案1) since it avoids third-party dependencies and is more maintainable.

内容的提问来源于stack exchange,提问作者daniel1511

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 06:52:03