2

Since openssl is deprecated in osx 10.7+, I'd like to switch from openssl to the internal osx keychain and crypto function.

But now I am stuck on asymmetric encryption/decryption.

How can I do encryption/decryption of a randomly generated symmetric key with a asymmetric (RSA) key. With openssl it's quite easy.

In the apple dev docs, they say that CommonCrypto supports asymmetric encryption, but while checking the headers, I can only see support for symmetric stuff.

Any hints?

4

1 回答 1

3

看看 Cryptographic Message Syntax Services,看看它是否能满足您的需求。

此外,您只是误读了 OpenSSL 的内容。操作系统附带的 OpenSSL 库已弃用。这并不意味着您不能继续使用 OpenSSL。OpenSSL 是开源的,没有什么能阻止您下载它并在您的应用程序中自由使用它。

Apple 的弃用只是意味着,如果您使用 OpenSSL,则需要包含您自己的 OpenSSL 库副本,以便负责使您的 OpenSSL 库保持最新,并修复在您这样做时发生的任何损坏。:-)

如果没有,iOS 非对称加密和解密功能(SecKeyEncrypt 和 SecKeyDecrypt)确实存在于 OS X 中,iOS 标头甚至显示它们在 OS X 中可用。我不确定为什么它们不在 OS X 中开发工具包。我提交了一个错误,它被标记为 dup。

Apple 将来可能无法在不破坏模拟器的情况下删除这些功能,但如果您提交到应用商店并且他们让您对使用它们感到不满,这里有一个大致兼容的替代 SecKeyEncrypt 使用 Security 构建转换 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;
}

您应该能够相当容易地修改代码以进行解密;我不需要它来达到我的目的,所以我没有编写那个函数。

于 2012-08-17T23:16:38.230 回答