如何在没有openssl的情况下使用OSX 10.7+进行非对称加密/解密?

时间:2012-07-29 19:52:51

标签: macos openssl keychain commoncrypto security-framework

由于openssl在osx 10.7+中已弃用,我想从openssl切换到内部osx keychain和crypto函数。

但现在我被困在非对称加密/解密上。

如何使用非对称(RSA)密钥对随机生成的对称密钥进行加密/解密。使用openssl非常容易。

apple dev docs中,他们说CommonCrypto支持非对称加密,但在检查标题时,我只能看到对对称内容的支持。

任何提示?

1 个答案:

答案 0 :(得分:3)

查看加密消息语法服务,看看它是否可以满足您的需求。

另外,你正在误读OpenSSL的事情。不推荐使用随操作系统提供的OpenSSL库。这并不意味着你不能继续使用OpenSSL。 OpenSSL是开源的,没有什么能阻止你下载它并在你的应用程序中自由使用它。

Apple的弃用只是意味着如果您使用OpenSSL,则需要包含OpenSSL库的自己的副本,以便负责保持您的OpenSSL库 - 到目前为止,并修复任何破损。 : - )

如果没有,iOS X非对称加密和解密功能(SecKeyEncrypt和SecKeyDecrypt)确实存在于OS X中,并且iOS标头甚至表明它们在OS X中可用。我不确定它们为什么不在OS X SDK。我提交了一个错误,它被标记为重复。

Apple可能无法在未打破模拟器的情况下删除这些功能,但是如果您提交到应用程序商店并且他们让您对使用它们感到悲伤,那么这里是SecKeyEncrypt构建的大致兼容的替代品使用安全转换API:

// Workaround for SecKeyEncrypt not really being public API in OS X
OSStatus OSXSecKeyEncrypt ( SecKeyRef key, SecPadding padding, const uint8_t *plainText, size_t plainTextLen, uint8_t *cipherText, size_t *cipherTextLen )
{
    CFMutableDictionaryRef parameters = CFDictionaryCreateMutable(
                                                                  kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks,
                                                                  &kCFTypeDictionaryValueCallBacks);
    CFDictionarySetValue(parameters, kSecAttrKeyType, kSecAttrKeyTypeAES);
    CFErrorRef error = NULL;
    SecTransformRef encrypt = SecEncryptTransformCreate(key, &error);

    if (error) {
        AFNSLog(@"Encryption failed: %@\n", (__bridge NSError *)error);
        return (OSStatus)[(__bridge NSError *)error code];
    }

    SecTransformSetAttribute(
                             encrypt,
                             kSecPaddingKey,
                             NULL, // kSecPaddingPKCS1Key (rdar://13661366 : NULL means kSecPaddingPKCS1Key and
                                                                          // kSecPaddingPKCS1Key fails horribly)
                             &error);

    CFDataRef sourceData = CFDataCreate(kCFAllocatorDefault, plainText, plainTextLen);
    SecTransformSetAttribute(encrypt, kSecTransformInputAttributeName,
                             sourceData, &error);

    CFDataRef encryptedData = SecTransformExecute(encrypt, &error);
    if (error) {
        AFNSLog(@"Encryption failed: %@\n", (__bridge NSError *)error);
        return (OSStatus)[(__bridge NSError *)error code];
    }

    if ((unsigned long)CFDataGetLength(encryptedData) > *cipherTextLen) {
        return errSecBufferTooSmall;
    }
    *cipherTextLen = CFDataGetLength(encryptedData);
    CFDataGetBytes(encryptedData, CFRangeMake(0, *cipherTextLen), cipherText);

    return noErr;
}

您应该能够相当容易地调整代码以进行解密;我不需要它用于我的目的,所以我没有写那个功能。