C++ SecKeyCreateFromData在10.9上失败,错误为-2147415792

C++ SecKeyCreateFromData在10.9上失败,错误为-2147415792,c++,macos,osx-mavericks,asn.1,seckeyref,C++,Macos,Osx Mavericks,Asn.1,Seckeyref,我有一段代码,在安全框架的帮助下在MacOS上构造RSA公钥。这在10.11/10.12/10.13上运行良好,但今天我发现在10.9上无法运行。下面是封装密钥的类的构造函数: CRSAPublicKey(const unsigned char* pExponent, const std::size_t nExponentSize, const unsigned char* pModulus, const std::size_t nModulusSize) { static const

我有一段代码,在安全框架的帮助下在MacOS上构造RSA公钥。这在10.11/10.12/10.13上运行良好,但今天我发现在10.9上无法运行。下面是封装密钥的类的构造函数:

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.)"
}
CRSAPublicKey(常量无符号字符*pExponent,常量std::size\t nExponentSize,常量无符号字符*pModulus,常量std::size\t nModulusSize)
{
静态常数SecAsn1Template krsaPubliceTypelate[]={
{SEC_ASN1_序列,0,NULL,sizeof(ASN1_RSA_公钥)},
{SEC_ASN1_整数,offsetof(ASN1_RSA_公钥,m_模),0,0},
{SEC_ASN1_整数,offsetof(ASN1_RSA_公钥,m_指数),0,0},
{ 0, 0, 0, 0 },
};
ASN1_RSA_公钥ASN1密钥;
Asn1Key.m_模数.Data=常数(pModulus);
Asn1Key.m_模量.Length=N模化;
Asn1Key.m_index.Data=const_cast(pExponent);
Asn1Key.m_index.Length=nextponentsize;
MacOS::CAsn1CoderReference PASN1编码器;
OSStatus nStatus=SecAsn1CoderCreate(&pAsn1Coder);
//检查nStatus
secasn1项DerKey;
nStatus=SecAsn1EncodeItem(pAsn1Coder和Asn1Key、kRsaPublicKeyTemplate和DerKey);
//检查nStatus
const void*pKeys[]={kSecAttrKeyType,kSecAttrKeyClass};
const void*pValues[]={kSecAttrKeyTypeRSA,ksecattrkeypasspublic};
MacOS::Creeference pParameters(CFDictionaryCreate(kCFAllocatorDefault,pKeys,pValues,2,nullptr,nullptr));
//检查参数
MacOS::引用pKeyData(CFDataCreate(kcfalocatordefault,DerKey.Data,static_cast(DerKey.Length));
//检查pKeyData
MacOS::CReference pError;
m_PublicKey=SecKeyCreateFromData(pParameters、pKeyData和pError);
//检查m_公钥-此操作失败,并显示“操作无法完成。(OSStatus错误-2147415792)。”
}
我删除了一些检查宏等,但这应该说明调用顺序。在10.9上,我从
SecKeyCreateFromData
获得一个空指针,错误代码为-2147415792。我尝试添加
kSecAttrKeySizeInBits
,但没有帮助。同时,使用相同的
pParameters
SecKeyGeneratePair
工作正常,因此我认为问题在于实际数据。ASN.1编码是否仅支持10.10或类似版本

更新

我在测试中搞砸了,这实际上在10.11上也不起作用,它似乎与addition
SecKeyCreateWithData
有关

更新2


查看此错误代码似乎是
CSSMERR\u CSP\u无效的\u键

,因为我没有在任何地方找到答案,我必须自己解决此问题,所以我希望这对其他人有帮助

对于
SecKeyCreateFromData
的行为变化,我没有找到直接的解释,但因为:

为对称密钥构造SecKeyRef对象

10.12添加了一个没有提到任何对称密钥的函数,也许他们也在
SecKeyCreateFromData
中添加了一些额外的功能,这可能就是为什么它在10.12及更高版本中对我有效的原因

然而,为了获得10.9兼容性,我使用了与ASN.1相同的编码序列:

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;
}
static SecKeyRef importpkcs1公钥(常量无符号字符*pExponent,常量std::size\t nExponentSize,常量无符号字符*pModulus,常量std::size\t nModulusSize)
{
静态常数SecAsn1Template krsaPubliceTypelate[]={
{SEC_ASN1_序列,0,NULL,sizeof(ASN1_RSA_公钥)},
{SEC_ASN1_整数,offsetof(ASN1_RSA_公钥,m_模),0,0},
{SEC_ASN1_整数,offsetof(ASN1_RSA_公钥,m_指数),0,0},
{ 0, 0, 0, 0 },
};
ASN1_RSA_公钥ASN1密钥;
Asn1Key.m_模数.Data=常数(pModulus);
Asn1Key.m_模量.Length=N模化;
Asn1Key.m_index.Data=const_cast(pExponent);
Asn1Key.m_index.Length=nextponentsize;
MacOS::CAsn1CoderReference PASN1编码器;
OSStatus nStatus=SecAsn1CoderCreate(&pAsn1Coder);
//检查nStatus和PASN1编码器
secasn1项DerKey;
nStatus=SecAsn1EncodeItem(pAsn1Coder和Asn1Key、kRsaPublicKeyTemplate和DerKey);
//检查nStatus
MacOS::引用pKeyData(CFDataCreate(kcfalocatordefault,DerKey.Data,static_cast(DerKey.Length));
//检查pKeyData
SecExternalFormat nFormat=kSecFormatBSAFE;
SecExternalItemType nType=kSecItemTypePublicKey;
MacOS::交叉点;
nStatus=SecItemImport(pKeyData,NULL,&nFormat,&nType,0,NULL,NULL,&pItems);
//检查nStatus
SecKeyRef pKey=reinterpret_cast(const_cast)(CFArrayGetValueAtIndex(pItems,0));
//检查pKey
CFRetain(pKey);
返回pKey;
}

这里的诀窍是猜测
nFormat
nType
,但幸运的是,我在Apple开源源代码和Github的[CoCoCoaCryptoMac]中找到了一个映射表。我的密钥已经有了PKCS1版本,如问题中的代码片段所示,剩下的工作只是相应地设置格式。answer有很多关于PKCS1/PKCS8的有价值的信息。另外,最初我不确定
pKeyData
是键的字符串形式还是二进制形式,因为有很多示例将字符串形式与
SecKeyCreateFromData
函数一起使用。我只是尝试了所有的选项,直到二进制版本起作用

请尝试使用
NULL,DerKey.Data,static_cast(DerKey.Length)
而不是
CFDataCreate(kcfalocatordefault,DerKey.Data,static_cast(DerKey.Length)
。两者都应使用默认分配器。区别是什么?请参阅函数“新建CFData对象,如果创建对象时出现问题,则为NULL。所有权遵循创建规则”的注释。看起来你永远不会释放它,这是你应该做的。还可以尝试引用
SecKeyCreateFromData
如:
pParameters、*pKeyData、&peror
…CR