I have generated keys using ECC. I need to add random number and secret key i.e x=r+s. Here's my code:
KeyPairGenerator kpg = KeyPairGenerator.getInstance("ECDSA", "BC");
kpg.initialize(ecSpec, new SecureRandom());
KeyPair keyPair = kpg.generateKeyPair();
PublicKey pubKey = keyPair.getPublic();
System.out.println(pubKey);
PrivateKey privKey = keyPair.getPrivate();
System.out.println(privKey);
Random rand = new Random();
int numNoRange = rand.nextInt();
Now I need to add x=numNoRange+privkey; but I couldn't add it. Any suggestions for new ideas?
You can extract the BigInteger by casting the private key to an ECPrivateKey like the following example:
BigInteger s = ((ECPrivateKey) privKey).getS();
Related
We have an enterprise mobile app that ships with an encrypted private key. We intend to provide users with the passphrase in order to use that private key, which will then allow them to communicate with a backend server. I've previously set this up using Python or C# but cannot figure out how to do this in Swift or Objective C. I've adapted some of this from this stack overflow question: Encrypt using RSA Certificate in Swift
static func getCertificate(from certificate: String?, usingPhrase phrase: String?) -> SecKey? {
guard let certificate = certificate else {
print("Nil string passed in, nil being returned")
return nil
}
let beginning = "-----BEGIN ENCRYPTED PRIVATE KEY-----"
let tail = "-----END ENCRYPTED PRIVATE KEY-----"
let certificateString = certificate.replacingOccurrences(of: beginning, with: "")
.replacingOccurrences(of: tail, with: "")
.replacingOccurrences(of: "\n", with: "")
.replacingOccurrences(of: " ", with: "")
guard let data = Data(base64Encoded: certificateString) else {
print("Unable to cast string to data")
return nil
}
// ** I'm assuming here is where I need to decrypt the key before I can create the certificate **
guard let cert = SecCertificateCreateWithData(nil, data as NSData) else {
print("Unable to cast certificate to SecCertificate")
return nil
}
var secTrust: SecTrust?
// Retrieve a SecTrust using the SecCertificate object. Provide X509 as policy
let status = SecTrustCreateWithCertificates(cert, SecPolicyCreateBasicX509(), &secTrust)
// Check if the trust generation is success
guard status == errSecSuccess else { return nil }
// Retrieve the SecKey using the trust hence generated
guard let trust = secTrust else {
print("Trust policy not created")
return nil
}
// ** I acknowledge that this method creates a public key and I am passing in a private key
// ** I am not sure what method needs to be used instead
guard let secKey = SecTrustCopyPublicKey(trust) else { return nil }
return secKey
}
Ultimately, I need to decrypt the private key using a passphrase. I was planning on using it as a SecKey, but getting the Base64 String representation of it works for me as well. I am comfortable working through an Objective-C or Swift based answer.
EDIT
Here is a sample key for test purposes:
-----BEGIN ENCRYPTED PRIVATE KEY-----
MIIFDjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIj6w/NvIjTXICAggA
MBQGCCqGSIb3DQMHBAi6qjkA0+yxyQSCBMhqdUDLRCLUjbgqe3rbF2lHn6yTsYbk
pfLWHkKT4pvQtaqXJvPZErb3E27va3HXvVDJfJS0/iwsnzIn6p2J9ZtgIGs4OBRU
kUw8lVAhNHTkAw/sj+OHdWexfOL5vKE3DgXqnAVGyhm4CNDXQ/9UDqkmtmHsMOlz
nqbOdWhMS/Uj/Dh41urw3sstpX4wZCHGTFNDL83pDAv7jfAZF/NSQq8ft/BPknMu
HLvYvd3fR4iKqKswcvR5c2q+CLbfEbXbVty6B/JMDSoi3wuh9lezMesIhTUYDSaK
QgkCEtrJ4FsO/tPXtyGvCjKVgvfvn8njQPtphq/gbKBeXpopsFGi19iY8fCkPQSb
Cp6FttMvJPwJvIb/qUZWGu9OWaBhmn0MH+qtXED6yxqXSyQDRYg1Vurfm0azQxUb
zJIy8qgla9GVvoGYpIGDvsQZFzur6le8G6/6c85raI9LZ88Bo8gEsTeQgPMxG1c+
7kRvn/hl/n0Oh8VsPOHjx2N/Y9vcmlyIlCDPIuGiYcNy1ICDv/kaBD9JVJVA5S7X
+MRZG8+EesjTiZseVUwK9OhnE4Jws2UzAk3zfMvzvnAgxue/FcRPUfYiHakNu83z
SFqayIUGz3zD0XLdWBVrh2QPvxW6eP3AFdIpjrPzwq1kDDw19VaAu7mw7JexrOyW
qvCO/VIHXqflL/OCxPT5BUQ9pbxTCEfv5wbWzczKWWub0AhPexDBW7wat3HwUGeb
oeEwnmNxAXxxz/RJeK1zKUAKGWQPI8X4bG/IZFmk1dgeJ8bo9My5b05Zw9d/gw7C
Xi5nZ5sG5ERp3jKLsT2czbr66w4HV4L38mASVtTUeXyySvnz//Ib40FC46Gi7SqP
pcpl1CrDi0UWe/cbQ/qkcaFrgdvIGsuSfZf8amq1FHnB47NUblYmm1WPCqeNtgzY
srAy/aVtF6FvG+uy6sCrP76c9HY1ZvyeO/82t/Sd5jnoq+VCKtarRNjEEfdwNGQp
X/ycspdn+a0XkXthSBvHWcCmQmgAV8Yp5TR0r2PgGqHk3lRq9/yKWy1gRuPSiRpZ
HzOOfZ4DmVELRf5R5+UCVJ5idkKZb2t+R7rl5/9grf8iCeUPngIkxrZvr4b7/mQm
fkmIMSUYT9CVeBprF5f2wLbbAmPpoUnULTnVzrOhZYCZGRQLyGGdX+CELBNxc8Er
dt4deeutCQm+H0d5V09HO9AOAwlESyt9q4CEAcSzSzzMygvWLe04csdcCSV2htAm
n0zDwhqGZ2LI+dUTGw4apOdBuNeveaHBrlp7XhCIOJ35SAWrb8baPizwl4iw5fA0
ucBZzRDAavDhj6XMQSwsOaCfzYfpASqwkm2Zjk3znWS18xpXRxvgqfCHpJRo9M4f
SQlRpT3Nqw5vn8BV+ioBvwxQd/1XsMbjKKwbwk+1wB/E/mHAiIQUQJ6Ec/WqzKqn
biqlBuSGLrS5O8ynu83DERFiatCAkNkl6nCaWtNu2KWtKM52y03BN3MBxS1kU+FI
afb7mN75j1gTZFH6EmujfVfrL/f8aO1dkxHO4IuWb5r7DaY7AByZgo1EKGiSIh3N
rtQVsAQr1/NcO6GVSHQU5egpI/eocvHvrAzsvlE2sqNBKm4NVogXjms7avKIbtA4
+Ro=
-----END ENCRYPTED PRIVATE KEY-----
The passcode for this key is
8720c10d735d7fb218b9e48db942a494
I took the sample encrypted key you provided and pasted it into this excellent ASN.1 decoder. It produces the following result:
Which is actually a very useful summary of the steps required to decrypt the ciphertext using the key you have:
The first two OBJECT IDENTIFIER entries hint at the padding mode used during encryption and the key derivation function used to obtain an encryption key from your "passcode": PKCS #5 padding and PBKDF2 for key derivation. The OCTET STRING and INTEGER values under that are the salt and iteration count for PBKDF2.
The third OBJECT IDENTIFIER indicates the encryption algorithm - TripleDES in CBC mode. Not ideal, but secure enough I guess. The OCTET STRING under that is the 8-byte IV, since DES has an 64 bit block size.
The final OCTET STRING is the ciphertext.
So, in summary, you need to:
Find a way to get at the values you need e.g. salt, iteration count, IV and ciphertext - assuming the algorithms used for these keys stay the same. Sometimes you can get away with jumping around in the raw data and slicing these values out - depending on your needs, you might need to use an ASN.1 decoder.
When it comes time to decrypt - pull out the salt and iteration count (first OCTET STRING and INTEGER). Pull out the IV (second OCTET STRING) and the ciphertext (last OCTET STRING).
Apply PBKDF2 using the specified salt and iteration count to your passcode, the one you provide in the question. You'll need to extract 192 bits of key material from this, since we're using TripleDES.
Decrypt the ciphertext using the key material from the last step in CBC mode using the IV you extracted. Use PCKS#5 padding, which is usually the default.
Done!
I'm trying to get a PEM encoded key from a SecKey on iOS. The EC private key is stored on the Keychain.
I'm getting a Data object from the SecKey object:
if #available(iOS 10.0, *) {
var error: Unmanaged<CFError>?
if let cfdata = SecKeyCopyExternalRepresentation(key, &error) {
return cfdata as Data
}
}
The Data object is in the 04 || X || Y || K format. How do I convert that to a PEM key?
Which curve do you use?
if you use kSecECCurveSecp256r1 and kSecAttrTokenIDSecureEnclave, you can't export the ECPrivateKey! Keys created within a trusted coprocessor cannot he exported (and I believe ones imported can’t either). Plus, you should never transfer private key material. It defeats the entire point of the SEP.
see:
https://developer.apple.com/documentation/security/ksecattrtokenidsecureenclave
https://support.apple.com/en-ng/guide/security/sec59b0b31ff/web
I have the following JWT token which i was able to decode using JWTDecode Cocoapod.
let token = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJEZXYyLVNES1Byb2ZpbGVTZXJ2aWNlIiwiaWF0IjoxNTI0MDQxNzI4LCJuYmYiOjE1MjQwNDE3MjgsImV4cCI6MTUyNjYzMzcyOCwianRpIjoiMzA3MGEyYzJiMDNiNDIwMTljNjc1NjU5NGExZTMyZTEiLCJpZGVudGlmaWVyIjoiMzEyNGJjZTYtYTQ3ZS00OTBjLWFjZmItYThjNjAwODc5NDYxIiwiY3VzdG9tZXIiOiIzNDM5IiwiT2JzZXJ2ZWRUeiI6IkFtZXJpY2EvTmV3X1lvcmsiLCJkZXZpY2VzIjoiW1wiYnBjdWZmXypcIixcIndlaWdodHNjYWxlXypcIixcIip3ZWxjaGFsbHluKlwiXSIsInRhcmdldHMiOiJbe1wiVXJsXCI6XCJodHRwczovL2RldjItdml0YWxzc2VydmljZS5oaG1hZXN0cm8ubmV0XCIsXCJTdGF0dXNcIjp0cnVlLFwiSGVhZGVyc1wiOntcIkF1dGhvcml6YXRpb25cIjpcImV5SmhiR2NpT2lKU1V6STFOaUlzSW5SNWNDSTZJa3BYVkNKOS5leUpwYzNNaU9pSkVaWFl5TFZORVMxQnliMlpwYkdWVFpYSjJhV05sSWl3aWFXRjBJam94TlRJME1EUXhOekk0TENKdVltWWlPakUxTWpRd05ERTNNamdzSW1WNGNDSTZNVFV5TmpZek16Y3lPQ3dpYW5ScElqb2lOR1JpTURZMFpHSTFZMkpqTkRrMFpHRmpOalJtWWpCaVl6ZG1aREJrT1dVaUxDSnBaR1Z1ZEdsbWFXVnlJam9pTXpFeU5HSmpaVFl0WVRRM1pTMDBPVEJqTFdGalptSXRZVGhqTmpBd09EYzVORFl4SWl3aVkzVnpkRzl0WlhJaU9pSXpORE01SWl3aVQySnpaWEoyWldSVWVpSTZJa0Z0WlhKcFkyRXZUbVYzWDFsdmNtc2lmUS5WbVAycm5OdzFiRjhJSVBUTnNQNGVCajJfUVJrRWFuYlpFZmt2NEZ2NjMzSFRlaHNSX010N3FMVUV2TERvQVlEQTA5NmxNbUdTZXA1enhLQkpEYkZwR3VWZmxjUTlCaTJ6MlJfY29SdFktcjU3U19NRVlZQVFORW1XZnRBVVVFZm1MTWFGM0piUHg5V0EwbE41V0hCOWhhcHBjT1NMYXRfcmdwX1pUd1VVd1V5WURDRTF4SXZjNWJockJLaXluM01qNTZlSlB0bEtUZElBZ01YZ29WOGRoSGd3XzZGZXo2dlMwZ2J1djdDMmd1TkNRUFJzRmZvcWFxUEZCNzZtU0VLUWtZUWFlQUlnRW1oSG9wRjRoRXVpcmRIR0JaT0tLYTNNejFvRnNqSjQ2OTVsLUcwX3NFbmV6b3FJSXlYZTN2X3ZsUVhlYmN4eHhfSk5vVjBfTmhDdmdcIn19XSJ9.pDp8cDssRcdB5FA_ykm-c0-g_jPEHPbod252d-bQzpo5PgsKTh4CRFrZ8bt6fam26IMOG_oYcXGZw9NUJowJ_qq5txQXJ7NPeX36Qy77-IpFttEDdAKEvwd6Y3j-hA-BUEzBuHUEPQASAfpFX9gY_ZqJsb6rIsqwi-_hh8vgBJdTODl4_n7vdAW2jtrZvp_BTSTDJ1-ZdJ_U0Oq_11_d5YgmU2s3bee_oVlLRs7o7dGEltbcgVThr4NfL8IVdoZ8H9YiUVeL69mh_LZZ1c7zYLZ4XNMyGSspdBVN8HewnNUD5_f9MGjXDanzX2U8Qc4BlsYd8nxZBSL02OfAkM53Uw"
do{
let jwt = try decode(jwt: token3)
print(jwt)
}
This code using the JWTDecode Library decodes the token successfully. Next step is I have to verify the signature of this token.The public and private key strings are available.
let publicKey = "LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0NCk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBcWtuU2dVcVVBZW5kUGR6bU9LSDYNClp1djd1czY4cFlsYWhkc0RHa1BCKzcwd2VSWWZHUUU3Wkl4cWR1WHhwbi80eUhWMDNHZmhKbXFLdktyOTZIWk8NCklkWkp5S3UvQWpkZGFWMGFsTmtwSisxRzRqSlg3RlVhSGplN3pYVk5WOEw2akVpVmpLcUNOMVNkKzc3dmpKNDUNClk5TXNMKzBQOVlGSFRkRVdNUWdjMmUrekRqdjVmc3E0SEpQcUJVU0VybUZRN2puRXVCa1lJemRLaXpFdTluSUwNCmE4a0Q1VVlhT0NUL2xJbEoveTJpbzdMSGJQRmQrTDBTYkREZUtwNGF1WVdsb3dQWkYrWVovKzBxdkRVMml4cUkNCi96bSt3TUlXUFdmanYxOHhEV3hLY2ErN2RBWlJ3bTVGNUxxU2ZGckcxNGhQcjg3RXJyNldXeUtsNkdXMnFhQ0oNCk9RSURBUUFCDQotLS0tLUVORCBQVUJMSUMgS0VZLS0tLS0NCg=="
The privateKey used is
let privateKey = "LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQ0KTUlJRXBBSUJBQUtDQVFFQXFrblNnVXFVQWVuZFBkem1PS0g2WnV2N3VzNjhwWWxhaGRzREdrUEIrNzB3ZVJZZg0KR1FFN1pJeHFkdVh4cG4vNHlIVjAzR2ZoSm1xS3ZLcjk2SFpPSWRaSnlLdS9BamRkYVYwYWxOa3BKKzFHNGpKWA0KN0ZVYUhqZTd6WFZOVjhMNmpFaVZqS3FDTjFTZCs3N3ZqSjQ1WTlNc0wrMFA5WUZIVGRFV01RZ2MyZSt6RGp2NQ0KZnNxNEhKUHFCVVNFcm1GUTdqbkV1QmtZSXpkS2l6RXU5bklMYThrRDVVWWFPQ1QvbElsSi95MmlvN0xIYlBGZA0KK0wwU2JERGVLcDRhdVlXbG93UFpGK1laLyswcXZEVTJpeHFJL3ptK3dNSVdQV2ZqdjE4eERXeEtjYSs3ZEFaUg0Kd201RjVMcVNmRnJHMTRoUHI4N0VycjZXV3lLbDZHVzJxYUNKT1FJREFRQUJBb0lCQVFDbDFHQWZzazJ5RTFsMQ0KWGdJQVVwVHoxNGo3NFVuS2RwamwwMk1SRjd6M2RzU1dsbGxRVTJmUVFnR0hxZU9LdmdLNnk4OHl1Q0tFODZvSg0Ka3diU2N5c2hQbm41NW02TExQbFZtdXBBMjcxOWVVN1hCaW1qSnpqWkJuTm40SHlpSTJrMFpaYmxOa0s2dVRkaw0KS2d0RHgrMmhiY3NSSE8yMnFkK1RRek0yS20xV09NVWlja0RLalhsN0hucmgvSU9FTGh5WTRCZk5oODB0ZU9Ibg0KOFpnclJBNTRLcktJSTAvN1lzR3pDdlBRZ3NCQm1haTdVYm83QlFxR3BZWXZPb0g0d2kzQU45c1VnTkdJWXBWMQ0KdE5BcUdxUWlvRkNXZkVxck8xMHRManBveXE2aXl2WnZpa0FkcjhBQitiejRyK0FYMUIzY3ZlbjZEMVBnekN2Yw0KNEdaTHpUaUJBb0dCQU5ncnFuL2g5Z0luN0owbWNJNEJMTWxmMXpIdVJBNHRTK1BOdzBOVXJyS2JsdDhyUjZrUQ0KOGtqT056MjQrMi9pMUJRa0l5eVM4bzdOTnJHNFoxbnVRaERWN2hiL0tUMXEyK2hYRmIvQWdZUXpYWXU5R2g0Ug0KVUZXdEt2bFBpV0plZUI3TksyYTI2TDNtWEJ4MUE5Y1BmcS91OWpSYXhwT3lqWHJxM0phNDUyU3BBb0dCQU1tcA0KL0FVa3hpaHQ4ZVdibFJMY1VvemxLajI2WHRxQXR5cHNpSHB2ayt0WnA5bVJxV2RYeDIzM3hhOFdkTkJCcXA4UQ0KWGFIRzVjZThuS2NaSWt1S2ZvWXBueEt6WE5RenVRSlh1M3dqZ005Z3V4RFUyNU8vMENNNDJyMjZlUEhJeVdNQQ0KSWxUTkVVVnkyQUZWSkUzTk1mZFNvblVqMjJVRVloeEkrVHpXR2tvUkFvR0JBS3dYNXo2ejF6UFVNT3pUQTF3cA0KMTB2aHZ1SURPNjdGcE5zUW5samwrOFk1VTUwTFNadHc0RkhSeWV5YmJhQ2ZSaE5heVozY3hybWs2ZHdHWUZFWg0KK3dLSUxXbWxiV0YxeHVockcrZHlEQ29BOG9JaTQ3MzRMcXBtbUFXdXFrTGp6bUZIR1R4R2RYZHBBditzc0lmdg0Kei8ya0VlR1FPdkt1ZlMvVDloVVAwemN4QW9HQVp5MmtkeEZBblpEYkVlb1BWSzRMUW5GQnNvRjNaSDQwdU96OA0KeXYvcGc2SEVna25IamN0WWl3Z1pTYUxJczREVmhqcStYVFpCZkhjaEExR1Z2V2FubzRjS0QyeGJrMnEvUHRhYQ0KWTBKYTlqOThsbmtCdTArSmMydjBadHhRWXd5akZSY05lYXZPS1dVLzVUYWxzM1RJR3MxWnQydFlKaEFmRG0rNw0KcllleHZiRUNnWUJxN3JqM05YRjdwSjZnQllMSURWOEttTCtTdnFhbS9KQkN6RjFQMnUvYTFabHd6b0Q3ZVhoWg0KUmd0eStrZ3lPU0pwUTFBZTdPUk1VSlFGRmtiY2VCanluQzdnSXFTTnlxV3B4SjJBTUpBL1pwYXE3WHFoVVZYSQ0KWEx2TVE1RGhoY0U4RG1CY09SYkFKaTg4S1JVZVVVYjdHWlBJa3lmRmYvSURFTlB1a01aZHBBPT0NCi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tDQo="
The algorithm used is RSA 256. Can someone guide me on how to verify the signature for the token using the public key.
Often, JWT libraries provide functionality to verify a JWT's signature.
Anyway, in case you want to do it yourself: The input to a JWT's sign function is the following concatenation: header + "." + payload. So if you want to verify a signature, you need to do that against that concatenation.
Once you have imported your keys as SecKey, e.g. using SecKeyCreateWithData, you should be able to just use iOS's Security framework to verify the signature somewhat like this:
let parts = token.components(separatedBy: ".")
let header = parts[0]
let payload = parts[1]
let signature = Data(base64URLEncoded: parts[2])!
let signingInput = (header + "." + payload).data(using: .ascii)!
SecKeyVerifySignature(publicKey, .rsaSignatureMessagePKCS1v15SHA256, signingInput as CFData, signature as! CFData, nil)
Accepted answer is good, but you have to remember that base64 string must be correctly encoded when creating Data() object. So complete code is:
let parts = token.components(separatedBy: ".")
let header = parts[0]
let payload = parts[1]
let signature = Data(base64URLEncoded: base64StringWithPadding (base64str:parts[2]))!
let signingInputStr = (header + "." + payload)
let signingInput = signingInputStr.data(using: .ascii)!
SecKeyVerifySignature(publicKey, .rsaSignatureMessagePKCS1v15SHA256, signingInput as CFData, signature as! CFData, nil)
func base64StringWithPadding(base64str: String) -> String {
var newStr = base64str.replacingOccurrences(of: "-", with: "+")
.replacingOccurrences(of: "_", with: "/")
let count = newStr.count % 4
if count > 0 {
let amount = 4 - count
for _ in 0..<amount {
newStr += "="
}
}
return newStr
}
Also few words about public key. When using text form .pem, inside you have to have something like this:
-----BEGIN PUBLIC KEY-----
key data
-----END PUBLIC KEY-----
and BEGIN and END strings have to be removed. Also remember that when your key is containing not valid base64 chars, you may need to skip them. (NSDataBase64DecodingIgnoreUnknownCharacters)
You can generate keys like this: (on Mac, similarly on other platforms)
ssh-keygen -t rsa -b 4096 -m PEM -f jwtRS256.key
Don't add passphrase
openssl rsa -in jwtRS256.key -pubout -outform PEM -out jwtRS256.key.pub
Also, there is no need to use any library to decode base64 strings. This functionality is already on iOS. Do this: Convert base64 to base64Withpadding, create Data(), create String from data using Ascii encoding, done.
(writing this for future self)
Currently I am generating a RSAKeyPair with the iOS security framework
statusCode = SecKeyGeneratePair(keyPairAttributes as CFDictionary, &newPublicKey, &newPrivateKey)
I then want to export these keys to a PEM format with PKCS8. The standard method apple provides to export keys is this:
let cfData = SecKeyCopyExternalRepresentation(self, &error)
but this data gives me the key in the PKCS1 format. Is there a way to convert the PKCS1 format to PKCS8?
So far all my research left me clueless on what to actually do to convert these formats.
I can't translate into Swift, but here's the nearly-Objective-C:
SecItemImportExportKeyParameters keyParams = {};
keyParams.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION;
keyParams.passphrase = you_need_a_cfstringref_here;
SecExternalFormat dataFormat = kSecFormatWrappedPKCS8;
OSStatus status = SecItemExport(privateKey, dataFormat, 0, &keyParams, &cfData);
Use case:
The app imports PKCS 12 file (with cert and private key) and saves it for later use.
Current status:
I was able to use SecImportExport.ImportPkcs12 in order to get SecIdentity and SecTrust objects.
Unfortunately I’m unable to assign SecIdentity and SecTrust object to SecRecord.
The code:
SecIdentity identityObject = ...;
SecTrust trustObject = ...;
SecRecord record = new SecRecord(SecKind.Identity);
record.Account = "Identity";
record.ValueData = ? //HOW TO CONVERT SecIdentity to NSData?
var res = SecKeyChain.Add(record);
You can use the SecRecord.SetValueRef (identityObject) which can be used to store keys (SecKey), certificates (SecCertificate) or identities.