App creates an RSA key pair suitable for sign/verify & encrypt/decrypt and stores them in a private keychain. A CSR is generated via openssl, supplying the private key from above. The CSR is sent to a server for registration. The server returns a certificate, which is added to the keychain. Keychain associates the cert & private key as an identity. The app is built for 10.12+ and uses: SecKeyCreateSignature, SecKeyVerifySignature, SecKeyCreateEncryptedData, SecKeyCreateDecryptedData
Generating the key pair and returning the private key
SecKeyGeneratePair, private key is returned in PEM fomat
CFDataRef dataRef;
SecKeyCopyExternalRepresentation( privateKey, &error );
SecItemImportExportKeyParameters params = {};
SecItemExport( privateKey, kSecFormatOpenSSL, kSecItemPemArmour, ¶ms, &dataRef );
NSString* pemString = [NSString stringWithUTF8String:[(__bridge NSData*)dataRef bytes]];
for use with openssl req -new -key <private key> -config <config file>
(In test code) I see different behaviors depending on which combination of keys is used.
Here are three scenarios...
1. 'original' key pair
public key = query keychain for kSecAttrKeyClassPrivate by kSecAttrLabel
private key = query keychain for kSecAttrKeyClassPublic by kSecAttrLabel
testSignAndVerify SUCCEEDED
testEncryptAndDecrypt SUCCEEDED
But of course, this scenario cannot be used since the server will need to use the public key associated with the certificate to encrypt data and verify signatures.
2. identity provides both keys
Fetch the identity by kSecAttrLabel
public key = SecIdentityCopyCertificate; SecCertificateCopyPublicKey
private key = SecIdentityCopyPrivateKey
testSignAndVerify FAILED - CSSMERR_CSP_OPERATION_AUTH_DENIED
testEncryptAndDecrypt FAILED - CSSMERR_CSP_OPERATION_AUTH_DENIED
3. hybrid
Fetch the identity by kSecAttrLabel
public key = SecIdentityCopyCertificate; SecCertificateCopyPublicKey
private key = query keychain for kSecAttrKeyClassPublic by kSecAttrLabel
testSignAndVerify FAILED - CSSMERR_CSP_VERIFY_FAILED
testEncryptAndDecrypt FAILED - CSSMERR_CSP_INVALID_DATA
So, I don't know what is going on, but it seems that whenever the certificate is involved, things don't work. Looks like there is some sort of mismatch between the keys, but I checked the modulus and exponent - they match.