我需要从公钥SecKeyRef获取原始公钥字节(使用openssl,这是' der'格式)以实现公钥密码。实际的固定功能已经写好,无法更改,并带有一个unsigned char * pubkey,size_t pubkeylen用来比较它的引脚。
这是我到目前为止所尝试的:
SecTrustRef trust;
OSStatus ret = SSLCopyPeerTrust(ctx, &trust);
SecKeyRef keyRef = SecTrustCopyPublicKey(trust);
CFDataRef publicKeyBits;
OSStatus success = SecItemExport(keyRef, kSecFormatOpenSSL, 0, NULL, &publicKeyBits) == errSecSuccess;
//OSStatus success = SecItemExport(keyRef, kSecFormatPEMSequence, 0, NULL, &publicKeyBits) == errSecSuccess;
size_t pubkeylen = CFDataGetLength(publicKeyBits);
printf("pubkeylen: %d\n", pubkeylen);
unsigned char *pubkey = CFDataGetBytePtr(publicKeyBits);
问题是这似乎根本不是DER格式,我希望pubkeylen对于这个特定的键是550,但它打印526,并且数据也不正确。我也尝试了kSecFormatPEMSequence,然后用相同的结果对它进行base64解码(它确实变成了与之前相同的526长度数组,所以至少它是一致的)。
编辑: 看起来当导出到kSecFormatPEMSequence时,PEM包含: -----开始RSA公钥----- 而不是预期的 -----开始公钥----- 这是一种不对DER进行base64-decode的不同格式,也许可以通过更多API调用将其解析回DER格式?
我错过了什么?谢谢你的帮助!
编辑: 我也尝试了以下内容:
CFDataRef d_tag = CFDataCreate(NULL, "com.bob", 7);
const void *cKeys[] = {kSecClass, kSecAttrKeyType,
kSecAttrKeyClass, kSecValueData,
kSecReturnData
};
const void *cValues[] = {kSecClassKey, kSecAttrKeyTypeRSA,
kSecAttrKeyClassPublic, keyRef,
kCFBooleanTrue
};
CFDictionaryRef saveDict = CFDictionaryCreate(NULL, cKeys, cValues,
5L, NULL, NULL);
OSStatus secStatus = SecItemCopyMatching(saveDict, (CFTypeRef)&publicKeyBits);
if (secStatus == errSecDuplicateItem ) {
printf("errSecDuplicateItem\n");
SecItemDelete(saveDict);
secStatus = SecItemAdd(saveDict, (CFTypeRef)&publicKeyBits );
}
if ( secStatus != noErr ) {
printf("return NULL\n");
return NULL;
}
size_t pubkeylen = CFDataGetLength(publicKeyBits);
printf("pubkeylen: %d\n", pubkeylen);
unsigned char *pubkey = CFDataGetBytePtr(publicKeyBits);
结果更糟糕,pubkeylen一直是96,但是pubkey中的数据总是不同!
我还尝试从objective-c转换https://github.com/datatheorem/TrustKit/blob/master/TrustKit/Pinning/public_key_utils.m#L65,我得到:
OSStatus resultAdd, resultDel = noErr;
CFDataRef d_tag = CFDataCreate(NULL, "com.bobe", 9);
const void *peerPublicKeyAddcKeys[] = {kSecClass, kSecAttrApplicationTag,
kSecValueRef, kSecAttrAccessible, kSecReturnData
};
const void *peerPublicKeyAddcValues[] = {kSecClassKey, d_tag,
keyRef, kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly,
kCFBooleanTrue
};
CFDictionaryRef peerPublicKeyAdd = CFDictionaryCreate(NULL, peerPublicKeyAddcKeys, peerPublicKeyAddcValues,
5L, NULL, NULL);
const void *publicKeyGetcKeys[] = {kSecClass, kSecAttrApplicationTag,
kSecReturnData
};
const void *publicKeyGetcValues[] = {kSecClassKey, d_tag,
kCFBooleanTrue
};
CFDictionaryRef publicKeyGet = CFDictionaryCreate(NULL, publicKeyGetcKeys, publicKeyGetcValues,
3L, NULL, NULL);
resultAdd = SecItemAdd(peerPublicKeyAdd, &publicKeyBits);
resultDel = SecItemDelete(publicKeyGet);
if ((resultAdd != errSecSuccess) || (resultDel != errSecSuccess))
{
// Something went wrong with the Keychain we won't know if we did get the right key data
printf("return NULL\n");
return NULL;
}
这次publicKeyBits总是为NULL,我开始把头发撕成碎片了!