SecKeyCreateFromData在10.9上使用-2147415792失败 [英] SecKeyCreateFromData fails on 10.9 with -2147415792

查看:87
本文介绍了SecKeyCreateFromData在10.9上使用-2147415792失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个在安全框架的帮助下在MacOS上构造RSA公钥的代码.在10.11/10.12/10.13上可以正常工作,但是今天我发现在10.9上失败了.下面是包装密钥的类的构造函数:

I have a code that constructs an RSA public key on MacOS with the help of the security framework. This works fine on 10.11/10.12/10.13, but today I found that this fails on 10.9. Below is the constructor of the class that wraps the key:

CRSAPublicKey(const unsigned char* pExponent, const std::size_t nExponentSize, const unsigned char* pModulus, const std::size_t nModulusSize)
{
    static const SecAsn1Template kRsaPublicKeyTemplate[] = {
        { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(ASN1_RSA_PUBLIC_KEY) },
        { SEC_ASN1_INTEGER, offsetof(ASN1_RSA_PUBLIC_KEY, m_Modulus), 0, 0 },
        { SEC_ASN1_INTEGER, offsetof(ASN1_RSA_PUBLIC_KEY, m_Exponent), 0, 0 },
        { 0, 0, 0, 0 },
    };
    ASN1_RSA_PUBLIC_KEY Asn1Key;
    Asn1Key.m_Modulus.Data = const_cast<unsigned char*>(pModulus);
    Asn1Key.m_Modulus.Length = nModulusSize;
    Asn1Key.m_Exponent.Data = const_cast<unsigned char*>(pExponent);
    Asn1Key.m_Exponent.Length = nExponentSize;
    MacOS::CAsn1CoderReference pAsn1Coder;
    OSStatus nStatus = SecAsn1CoderCreate(&pAsn1Coder);
    // Check nStatus
    SecAsn1Item DerKey;
    nStatus = SecAsn1EncodeItem(pAsn1Coder, &Asn1Key, kRsaPublicKeyTemplate, &DerKey);
    // Check nStatus
    const void* pKeys[] = { kSecAttrKeyType, kSecAttrKeyClass };
    const void* pValues[] = { kSecAttrKeyTypeRSA, kSecAttrKeyClassPublic };
    MacOS::CReference<CFDictionaryRef> pParameters(CFDictionaryCreate(kCFAllocatorDefault, pKeys, pValues, 2, nullptr, nullptr));
    // Check pParameters
    MacOS::CReference<CFDataRef> pKeyData(CFDataCreate(kCFAllocatorDefault, DerKey.Data, static_cast<CFIndex>(DerKey.Length)));
    // Check pKeyData
    MacOS::CReference<CFErrorRef> pError;
    m_PublicKey = SecKeyCreateFromData(pParameters, pKeyData, &pError);
    // Check m_PublicKey - this fails with "The operation couldn’t be completed. (OSStatus error -2147415792.)"
}

我删除了一些检查宏等,但这应该说明调用顺序.在10.9上,我从 SecKeyCreateFromData 中获得了一个空指针,错误代码为-2147415792.我尝试添加 kSecAttrKeySizeInBits ,但这没有帮助.同时具有相同 pParametersSecKeyGeneratePair 工作正常,所以我认为问题出在实际数据上.是否仅从10.10开始支持ASN.1编码?

I removed some check macros etc, but this should illustrate the call sequence. On 10.9 I get a null pointer from SecKeyCreateFromData with an error code -2147415792. I tried adding the kSecAttrKeySizeInBits but that did not help. Meanwhile SecKeyGeneratePair with the same pParameters works fine, so I assume the issue is with the actual data. Is the ASN.1 coding supported only from 10.10 or something like that?

更新

我在测试中陷入困境,这实际上在10.11上也无法正常运行,这似乎与 SecKeyCreateWithData 附加在一起.

I got messed up in my tests, this actually does not work on 10.11 as well, which seems to corelate with addition SecKeyCreateWithData.

更新2

查看 cssmerr.h 此错误代码似乎是 CSSMERR_CSP_INVALID_KEY .

Looking at cssmerr.h this error code seems to be CSSMERR_CSP_INVALID_KEY.

推荐答案

由于我没有找到可以自己解决的答案,因此希望对其他人有所帮助.

Since I did not find the answer anywhere I had to solve this myself so I hope this helps others.

我没有找到有关 SecKeyCreateFromData 的行为更改的直接解释,但是由于

I did not find a direct explanation for the behavior changes of SecKeyCreateFromData, but since the documentation states:

为对称密钥构造一个SecKeyRef对象.

Constructs a SecKeyRef object for a symmetric key.

10.12添加了 SecKeyCreateWithData ,其中没有提及任何内容关于对称密钥,也许他们也向 SecKeyCreateFromData 中添加了一些附加功能,这可能就是为什么它在10.12及更高版本上对我有效的原因.

10.12 added a SecKeyCreateWithData which does not mention anything about symmetric keys, maybe they added some additional functionality into SecKeyCreateFromData as well and that could be why it was working for me on 10.12 and up.

尽管如此,为了获得10.9兼容性,我使用了 SecItemImport 具有相同的ASN.1编码序列:

Nevertheless, to obtain 10.9 compatibility I used SecItemImport with the same ASN.1 encoded sequence:

static SecKeyRef ImportPkcs1PublicKey(const unsigned char* pExponent, const std::size_t nExponentSize, const unsigned char* pModulus, const std::size_t nModulusSize)
{
    static const SecAsn1Template kRsaPublicKeyTemplate[] = {
        { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(ASN1_RSA_PUBLIC_KEY) },
        { SEC_ASN1_INTEGER, offsetof(ASN1_RSA_PUBLIC_KEY, m_Modulus), 0, 0 },
        { SEC_ASN1_INTEGER, offsetof(ASN1_RSA_PUBLIC_KEY, m_Exponent), 0, 0 },
        { 0, 0, 0, 0 },
    };
    ASN1_RSA_PUBLIC_KEY Asn1Key;
    Asn1Key.m_Modulus.Data = const_cast<unsigned char*>(pModulus);
    Asn1Key.m_Modulus.Length = nModulusSize;
    Asn1Key.m_Exponent.Data = const_cast<unsigned char*>(pExponent);
    Asn1Key.m_Exponent.Length = nExponentSize;
    MacOS::CAsn1CoderReference pAsn1Coder;
    OSStatus nStatus = SecAsn1CoderCreate(&pAsn1Coder);
    // Check nStatus and pAsn1Coder
    SecAsn1Item DerKey;
    nStatus = SecAsn1EncodeItem(pAsn1Coder, &Asn1Key, kRsaPublicKeyTemplate, &DerKey);
    // Check nStatus
    MacOS::CReference<CFDataRef> pKeyData(CFDataCreate(kCFAllocatorDefault, DerKey.Data, static_cast<CFIndex>(DerKey.Length)));
    // Check pKeyData
    SecExternalFormat nFormat = kSecFormatBSAFE;
    SecExternalItemType nType = kSecItemTypePublicKey;
    MacOS::CReference<CFArrayRef> pItems;
    nStatus = SecItemImport(pKeyData, NULL, &nFormat, &nType, 0, NULL, NULL, &pItems);
    // Check nStatus
    SecKeyRef pKey = reinterpret_cast<SecKeyRef>(const_cast<void*>(CFArrayGetValueAtIndex(pItems, 0)));
    // Check pKey
    CFRetain(pKey);
    return pKey;
}

这里的窍门是猜测 nFormat nType ,但是幸运的是,我在Apple开源源和Github中的[CocoaCryptoMac]中找到了一个带有映射的表.如问题片段中所示,我已经为我的密钥安装了PKCS1版本,剩下的工作就是相应地设置格式.

The trick here was to guess nFormat and nType, but luckily I found a table with the mapping in Apple open source sources and [CocoaCryptoMac] in Github. I already had the PKCS1 version for my key as seen in the snippet in the question the remaining job was just to set the format accordingly. This answer has a lot of valuable info on PKCS1/PKCS8. Also, initially I was not sure if pKeyData is the string or binary form of the key, since there are lots of examples that use the string form with the SecKeyCreateFromData function. I just tried out all the options until the binary version worked.

这篇关于SecKeyCreateFromData在10.9上使用-2147415792失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆