Prioritize user privacy and data security in your app. Discuss best practices for data handling, user consent, and security measures to protect user information.

All subtopics
Posts under Privacy & Security topic

Post

Replies

Boosts

Views

Activity

Keychain Item Lost During Resetting Face ID
I'm using the following code to store a Keychain item: SecAccessControlCreateWithFlags( kCFAllocatorDefault, kSecAttrAccessibleWhenUnlockedThisDeviceOnly, .biometryAny, &error ) One of my app users reported an issue: 1. The user navigated to his iPhone’s Face ID settings and click `Reset Face ID`. 2. Then, before he set new Face ID, he accidentally tapped the "Back" button and returned to the iPhone Settings page. 3. He later reopened the Face ID setup page and completed the process. 4. Upon returning to my app, the Keychain item secured by Face ID was no longer found. I understand that .biometryAny may cause Keychain items to become invalidated when biometric data is reset. However, the user’s scenario — where the setup was temporarily interrupted — seems to have caused the item to disappear. 1. Is there a way to detect and handle such interruptions to prevent the Keychain item from being lost? 2. How can I design a better experience to guide the user in recreating the Keychain item when this occurs?
0
0
291
Dec ’24
Swift program to send Push Notifications
Is there a step by step program on Sending Push notifications? I seem to be stuck at load private key. I get this error. SecKeyCreateWithData failed with error: Error Domain=NSOSStatusErrorDomain Code=-50 "EC private key creation from data failed" It is a new p8 file. I tried different format. I read some articles that say that there is a bug I think. I don't know for sure because it was written in jibberish. 90% of the code is dealing with these stupid keys. This should be 1 function setting the pipe and then I can use the pipe. This is ridiculous. If anybody has any ideas. The code is a mess because I tried so many different ideas. Push Notification.txt
2
0
447
Jan ’25
SFAuthorizationPluginView and invalid password
I am using SFAuthorizationPluginView in my Security agent plugin. My code expects that its willActivate method be called. With normal screensaver unlock, this works fine. However if I enter an invalid password, then enter the correct password, I never get the willActivate call. I have reproduced this with Quinn's LoginUIAuthPlugin from the QAuthPlugins example code. My mechanisms look like this with LoginUIAuthPlugin: mechanisms HyprAuthPlugin:invoke builtin:authenticate,privileged PKINITMechanism:auth,privileged LoginUIAuthPlugin:login CryptoTokenKit:login I would like to be able to get my plugin working properly when the user had previously entered an invalid password.
0
0
367
Dec ’24
appleid.apple.com IPv6 support
Hi, I've been developing an app with a server. I'm hosting the server on an IPv6-ONLY network that's hidden behind the CloudFlare, so it works flawlessly from the clients point of view, but if server needs to access external resources, they need to be accessible over IPv6. As it turns out, appleid.apple.com doesn't support IPv6, and the Sign In with Apple happens with the help of my server. So, I can't sign users in as Apple doesn't support IPv6 traffic on appleid.apple.com. Are there any plans to support IPv6 in the near future, or should I work on the networking setup to enable IPv4 just for the Apple SSO? Or maybe there's a clever workaround I'm missing?
0
0
202
Jun ’25
Rooted iPhone 15 Pro
iOS 18.2 (22C152) My phone is currently on lockdown mode and I have gotten alerts from Experian that my information is on the dark web as well as having to reset all my accounts. However this has not fixed the issue. Even if I hard factory reset settings etc the root makes its way very shortly after, if not immediately. Though I recently got these notifications and purchased the phone in Feb. 2024 the has been an ongoing issue for a few years. I can elaborate if needed. To make it short I have a reinstalled root on my phone. Apple nor Spectrum (who I have my phone with) have been able to assist with this issue. I have been able to clarify this ”hijacking” with the Geek Squad who didn’t want their legal team involved when asking for a report so the PD can do an internal cyber investigation. So, I’ve just lived with it. Let me know what your thoughts to resolve this issue would be before spending thousands to find a resolution on my own. Side note before asked: what I’ve been told may be it’s ”gateway” is via “DNS hijacking” with WiFi or internally hotspot. I can also elaborate if needed-I’m not a web developer, however I do know where this issue stems from whom has their masters in such industry as well as 30 years experience. It’s annoying and inconvenient at this point and I’m looking for clarity, resolution and if no justice for the criminal then liability. thank you! please refrain from saying “APpLe CaNt bE hiJaCked“ ..
1
0
541
Dec ’24
Sign in with Apple Keychain savedEmail Stored Incorrectly
Using personal physical iPhone for simulations. Can't get Keychain to read or store AppleID name/email. I want to avoid hard reseting physical phone. Logs confirm Keychain is working, but userIdentifier and savedEmail are not being stored correctly. 🔄 Initializing UserManager... ✅ Saved testKeychain to Keychain: Test Value ✅ Retrieved testKeychain from Keychain: Test Value 🔍 Keychain Test - Retrieved Value: Test Value ⚠️ Keychain Retrieve Warning: No stored value found for userIdentifier ⚠️ Keychain Retrieve Warning: No stored value found for savedEmail 🔍 Debug - Retrieved from Keychain: userIdentifier=nil, savedEmail=nil ⚠️ No stored userIdentifier in Keychain. User needs to sign in. 📦 Converting User to CKRecord: Unknown, No Email ✅ User saved locally: Unknown, No Email ✅ User saved to CloudKit: Unknown, No Email Below UserManager.swift if someone can help troubleshoot. Or step by step tutorial to configure a project and build a User Login & User Account creation for Apple Only app. import Foundation import CloudKit import AuthenticationServices import SwiftData @MainActor class UserManager: ObservableObject { @Published var user: User? @Published var isLoggedIn = false @Published var errorMessage: String? private let database = CKContainer.default().publicCloudDatabase init() { print("🔄 Initializing UserManager...") // 🔍 Keychain Debug Test let testKey = "testKeychain" KeychainHelper.shared.save("Test Value", forKey: testKey) let retrievedValue = KeychainHelper.shared.retrieve(forKey: testKey) print("🔍 Keychain Test - Retrieved Value: \(retrievedValue ?? "nil")") fetchUser() // Continue normal initialization } // ✅ Sign in & Save User func handleSignIn(_ authResults: ASAuthorization) { guard let appleIDCredential = authResults.credential as? ASAuthorizationAppleIDCredential else { errorMessage = "Error retrieving Apple credentials" print("❌ ASAuthorization Error: Invalid credentials received") return } let userIdentifier = appleIDCredential.user let fullName = appleIDCredential.fullName?.givenName ?? retrieveSavedName() var email = appleIDCredential.email ?? retrieveSavedEmail() print("🔍 Apple Sign-In Data: userIdentifier=\(userIdentifier), fullName=\(fullName), email=\(email)") // 🔄 If Apple doesn't return an email, check if it exists in Keychain if appleIDCredential.email == nil { print("⚠️ Apple Sign-In didn't return an email. Retrieving saved email from Keychain.") } // ✅ Store userIdentifier & email in Keychain KeychainHelper.shared.save(userIdentifier, forKey: "userIdentifier") KeychainHelper.shared.save(email, forKey: "savedEmail") let newUser = User(fullName: fullName, email: email, userIdentifier: userIdentifier) saveUserToCloudKit(newUser) } func saveUserToCloudKit(_ user: User) { let record = user.toRecord() Task { do { try await database.save(record) DispatchQueue.main.async { self.user = user self.isLoggedIn = true self.saveUserLocally(user) print("✅ User saved to CloudKit: \(user.fullName), \(user.email)") } } catch { DispatchQueue.main.async { self.errorMessage = "Error saving user: \(error.localizedDescription)" print("❌ CloudKit Save Error: \(error.localizedDescription)") } } } } // ✅ Fetch User from CloudKit func fetchUser() { let userIdentifier = KeychainHelper.shared.retrieve(forKey: "userIdentifier") let savedEmail = KeychainHelper.shared.retrieve(forKey: "savedEmail") print("🔍 Debug - Retrieved from Keychain: userIdentifier=\(userIdentifier ?? "nil"), savedEmail=\(savedEmail ?? "nil")") guard let userIdentifier = userIdentifier else { print("⚠️ No stored userIdentifier in Keychain. User needs to sign in.") return } let predicate = NSPredicate(format: "userIdentifier == %@", userIdentifier) let query = CKQuery(recordType: "User", predicate: predicate) Task { [weak self] in guard let self = self else { return } do { let results = try await self.database.records(matching: query, resultsLimit: 1).matchResults if let (_, result) = results.first { switch result { case .success(let record): DispatchQueue.main.async { let fetchedUser = User(record: record) self.user = User( fullName: fetchedUser.fullName, email: savedEmail ?? fetchedUser.email, userIdentifier: userIdentifier ) self.isLoggedIn = true self.saveUserLocally(self.user!) print("✅ User loaded from CloudKit: \(fetchedUser.fullName), \(fetchedUser.email)") } case .failure(let error): DispatchQueue.main.async { print("❌ Error fetching user from CloudKit: \(error.localizedDescription)") } } } } catch { DispatchQueue.main.async { print("❌ CloudKit fetch error: \(error.localizedDescription)") } } } } // ✅ Save User Locally private func saveUserLocally(_ user: User) { if let encoded = try? JSONEncoder().encode(user) { UserDefaults.standard.set(encoded, forKey: "savedUser") UserDefaults.standard.set(user.fullName, forKey: "savedFullName") UserDefaults.standard.set(user.email, forKey: "savedEmail") print("✅ User saved locally: \(user.fullName), \(user.email)") } else { print("❌ Local Save Error: Failed to encode user data") } } // ✅ Retrieve Previously Saved Name private func retrieveSavedName() -> String { return UserDefaults.standard.string(forKey: "savedFullName") ?? "Unknown" } // ✅ Retrieve Previously Saved Email private func retrieveSavedEmail() -> String { return KeychainHelper.shared.retrieve(forKey: "savedEmail") ?? UserDefaults.standard.string(forKey: "savedEmail") ?? "No Email" } // ✅ Sign Out func signOut() { isLoggedIn = false user = nil UserDefaults.standard.removeObject(forKey: "savedUser") print("🚪 Signed Out") } }
0
0
241
Mar ’25
Is there a way to hide the 'Save to another device' option during iOS WebAuthn registration?
Hello, I am currently implementing a biometric authentication registration flow using WebAuthn. I am using ASAuthorizationPlatformPublicKeyCredentialRegistrationRequest, and I would like to know if there is a way to hide the "Save to another device" option that appears during the registration process. Specifically, I want to guide users to save the passkey only locally on their device, without prompting them to save it to iCloud Keychain or another device. If there is a way to hide this option or if there is a recommended approach to achieve this, I would greatly appreciate your guidance. Also, if this is not possible due to iOS version or API limitations, I would be grateful if you could share any best practices for limiting user options in this scenario. If anyone has experienced a similar issue, your advice would be very helpful. Thank you in advance.
0
0
508
Nov ’24
Device check validation API request to apple development server failed with error code 500
Our application uses device check api to validate the device token in staging server. We are using "https://api.development.devicecheck.apple.com/v1/validate_device_token"for this.But the response is 500 internal server error. Our production build is working fine.We pointed the build to "https://api.devicecheck.apple.com/v1/validate_device_token" url.We are using the same device check key for both development and production server. Device check was working fine in development server also.Suddenly it started to failed with out making any changes in our code.
2
0
376
Mar ’25
Sending emails from AWS SES to private relay service
Feedback report id: FB16605524 I'm trying to send emails to private relay service addresses using AWS SES and emails are not received. My emails are sent from dev@mydomain.fr and I've set a custom FROM domain of mail.mydomain.fr. I've added both domains and the dev@mydomain.fr adress to the "Certificates, Identifies & Profiles" section. I've set up DKIM and SPF for both. Attached a redacted version of email headers. email_headers_redacted.txt
0
0
280
Mar ’25
Safari has slight variances in people's experience
Hi team, if I log into my app on Safari and try to enroll/challenge MFA security key option, I will be able to see this pop-up that gives me the option to pick either passkeys or external security keys However, my team member who's using the same version of safari, can only see the external security key option Why is this?
1
0
262
Mar ’25
How to resolve invalid client
I've been fighting this issue for 3 days now. After several failures, I created a new app id and service id yesterday. I checked and entered domain, callback, and login usage clearly, but it keeps returning an error. Can you help me figure out what's wrong? https://appleid.apple.com/auth/authorize?response_type=code&client_id=com.smoothmail.signin&redirect_uri=https%3A%2F%2Fsmoothmail.store%2Fapple-auth&state=4157daa763&scope=name+email&response_mode=form_post
5
0
168
Jun ’25
Authentication Services uses Safari when it is not the default browser and fails the flow anyway
We are developing an app that uses Authentication Services to authenticate users. According to the documentation, this framework will open the default web browser if it supports auth session handling, and Safari otherwise. This is not entirely true, and users will be frustrated! macOS version: Sequoia 15.5; Safari version: 18.5. When: The default browser is not Safari, and supports auth session handling (Google Chrome and Microsoft Edge as examples); and - The Safari app is already running; The auth flow will: Present the confirmation dialog box with the default browser icon. Good! Open a Safari window, instead of the default browser's one. Bad! Respond with "User Cancelled" error to the app, after making the end user believe the auth was good. Very Bad!! If the app retries the auth session, the default browser window will open as expected, and it will work as expected. However, requiring users to authenticate twice is a very bad users experience... This issue does not reproduce, when either: Safari is not running at the moment of auth session start; The default browser does not support auth session handling; or - Safari is the default browser. Fellow developers, be warned! Apple engineers, feedback #18426939 is waiting for you. Cheers!
0
0
53
Jun ’25
I'm trying to use a keychain-access-group and failing
This is on macOS, not iOS. Not sure if that should make a difference? I have a GUI app and a command line tool (that will run a daemon) that I need to share credentials between. The keys/certs will be stored using the GUI app. But, both tools need to utilize them. guard let accessControl = SecAccessControlCreateWithFlags( nil, kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly, [.privateKeyUsage], nil ) else { throw KeychainCertError.keychainError(errSecAuthFailed, "Failed to create access control for private key") } // Define Key Pair Attributes let privateKeyAttributes: [String: Any] = [ kSecAttrIsPermanent as String: true, kSecAttrApplicationTag as String: privateLabel.data(using: .utf8)!, kSecAttrLabel as String: privateLabel, // kSecAttrAccessControl as String: accessControl, kSecAttrAccessGroup as String: keychainAccessGroup ] With the kSecAttrAccessControl commented out, I am able to generate a private key and generate a self signed certificate that is stored on the user login keychain. If I uncomment that line, I get an error to the affect of "Keychain error (-26275): Failed to generate key pair: A required entitlement isn't present" Also, to share the credentials, don't they need to be NOT on the user keychain for the daemon to access them? Any ideas what I am doing wrong? I think I'm a bit over my head here with the the security, crypto kit and openssl. 😁
6
0
447
Mar ’25
Can't get user info more than once upon signin ?
Hi, I know it's been discussed before, but I'm testing the Sign in with Apple feature, and I only get the user info on the first try. Now, I know that you're supposed to go to the account settings, and look for the list of accounts that you used your Apple account to sign in with, and it used to work a few months back. But for the last few weeks I haven't been able to get the user info, even after deleting the entry from my Sign In With Apple app list. Has there been a recent change to Apple security policy that prevents such a move from working ? Or am I doing something wrong ? Thank you
0
0
293
Feb ’25
Importing Cryptographic Keys
I regularly see folks having problems importing cryptographic keys, so I thought I’d write down some hints and tips on how to recognise and import the various key formats. This post describes how to import each type of key. A companion post, On Cryptographic Keys Formats, discusses how to recognise the format of the data you have. If you have questions about any of this stuff, put them a new thread in Privacy & Security > General. Tag your thread with Security or Apple CrytoKit, or both!, so that I see it. Finally, if you want to see a specific example of these techniques in action, see Importing a PEM-based RSA Private Key and its Certificate. Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" Importing Cryptographic Keys Apple platforms support 5 different key types: RSA (Security framework only) SECG secp256r1, aka NIST P-256 (Security framework and Apple CryptoKit) SECG secp384r1, aka NIST P-384 (Security framework and Apple CryptoKit) SECG secp521r1, aka NIST P-521 (Security framework and Apple CryptoKit) Curve 25519 (Apple CryptoKit only) This post explains how to import each type of key. If you’re not sure what type of key you have, or how its encoded, or you run into weird problems and suspect that you might be using the wrong key type or encoding, read On Cryptographic Keys Formats. Note This post focuses on APIs available on all Apple platforms. Some Mac-specific APIs can import other formats. The Security framework uses the SecKey type for all key types that it supports. Apple CryptoKit has a different approach: It uses different types for different key types, which helps catch common programming mistakes at compile time. There are 4 top-level enums: P256, for SECG secp256r1 P384, for SECG secp384r1 P521, for SECG secp521r1 Curve25519, for Curve 25519 Each of those enums contains a KeyAgreement enum and a Signing enum, where you express the intended purpose for your key. In this post I always use Signing but the code will work the same if you choose KeyAgreement. Finally, in each of those enums you’ll find both Public and Private types; these are structs that represent a specific public or private key. Undo PEM Encoding Writing a full-featured PEM parser is tricky. It is, however, relatively straightforward to undo the PEM encoding of a known simple PEM file. For example, if you have this file: % cat p256-private-key.pem -----BEGIN PRIVATE KEY----- MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgmGp6kcu19PgWNuga r/CDWncdxmhlxAeo6ERpz2q4pHehRANCAASXR+mBqrjqcaJVzZoVYoWMQGAG8eQY Jg0x4ad/bCs1qaMTLyMtsANR2dgANIfU7lKEeZAxPap8ch+I1LtW2pHH -----END PRIVATE KEY----- Decode it like so: let u = URL(fileURLWithPath: "p256-private-key.pem") guard let pem = try? String(contentsOf: u) else { … handle error … } let pemBase64 = pem .split(separator: "\n") .dropFirst() .dropLast() .joined() guard let pemData = Data(base64Encoded: String(pemBase64)) else { … handle error … } debugPrint(pemData as NSData) // prints: // <30818702 01003013 06072a86 48ce3d02 0106082a 8648ce3d … d4bb56da 91c7> Import RSA Keys Use SecKeyCreateWithData to import an RSA key. If you have an RSAPublicKey structure like this: % xxd -p rsa-public-key.der 3082010a0282010100cf243c324b262470131648614b62ee9c52af43319c 2498a7c16ba9790bb3a881f960f7b0303f8f49e86fedd6813be5fa888393 55d04426df0050dbb771eb683773b7dd929949695093f910c8dcdb633674 de986ada8d643e0e819b7cd5ab3bde4372103797472dc843a2711699e21a 4afddeed9f62810316903457342c345a35ebb2f06da019fed2afa56e7856 6e75a0d712849ae255155d9304348318930611b3b4f1153d77ee5970f076 299c548c8afff53157205048ade26d40930af2ecc96d4f77e8591523b767 fa3cdbc45a8a210339c4a556cea2e0dfa3ee819b62e463f75d87a53c2fbd 1bbcb8ec8fe2e8000ce37235fa903113c7b37d9c2a8b39c54b0203010001 % % dumpasn1 -p -a rsa-public-key.der SEQUENCE { INTEGER 00 CF 24 3C 32 4B 26 24 70 13 16 48 61 4B 62 EE 9C 52 AF 43 31 9C 24 98 A7 C1 6B A9 79 0B B3 A8 81 F9 60 F7 B0 30 3F 8F 49 E8 6F ED D6 81 3B E5 FA 88 83 93 55 D0 44 26 DF 00 50 DB B7 71 EB 68 37 73 B7 DD 92 99 49 69 50 93 F9 10 C8 DC DB 63 36 74 DE 98 6A DA 8D 64 3E 0E 81 9B 7C D5 AB 3B DE 43 72 10 37 97 47 2D C8 43 A2 71 16 99 E2 1A 4A FD DE ED 9F 62 81 03 16 90 34 57 34 2C 34 5A 35 EB B2 F0 6D A0 19 FE D2 AF A5 6E 78 56 6E 75 A0 D7 12 84 9A E2 55 15 5D 93 04 34 83 18 93 06 11 B3 B4 F1 15 3D 77 EE 59 70 F0 76 29 9C 54 8C 8A FF F5 31 57 20 50 48 AD E2 6D 40 93 0A F2 EC C9 6D 4F 77 E8 59 15 23 B7 67 FA 3C DB C4 5A 8A 21 03 39 C4 A5 56 CE A2 E0 DF A3 EE 81 9B 62 E4 63 F7 5D 87 A5 3C 2F BD 1B BC B8 EC 8F E2 E8 00 0C E3 72 35 FA 90 31 13 C7 B3 7D 9C 2A 8B 39 C5 4B INTEGER 65537 } Import it with this code: let u = URL(fileURLWithPath: "rsa-public-key.der") guard let keyBytes = try? Data(contentsOf: u) else { … handle error … } guard let privateKey = SecKeyCreateWithData(keyBytes as NSData, [ kSecAttrKeyType: kSecAttrKeyTypeRSA, kSecAttrKeyClass: kSecAttrKeyClassPublic, ] as NSDictionary, nil) else { … handle error … } print(privateKey) // prints: // <SecKeyRef algorithm id: 1, key type: RSAPublicKey, version: 4, block size: 2048 bits, exponent: {hex: 10001, decimal: 65537}, modulus: …, addr: …> Note You don’t need to include any other attributes in the dictionary you pass to SecKeyCreateWithData. Specifically, many folks think that they need to pass in the kSecAttrKeySizeInBits attribute. This isn’t the case; SecKeyCreateWithData will work out the key size from the key data. If you have an RSAPrivateKey structure like this: % xxd -p rsa-private-key.der 308204a30201000282010100cf243c324b262470131648614b62ee9c52af 43319c2498a7c16ba9790bb3a881f960f7b0303f8f49e86fedd6813be5fa 88839355d04426df0050dbb771eb683773b7dd929949695093f910c8dcdb 633674de986ada8d643e0e819b7cd5ab3bde4372103797472dc843a27116 99e21a4afddeed9f62810316903457342c345a35ebb2f06da019fed2afa5 6e78566e75a0d712849ae255155d9304348318930611b3b4f1153d77ee59 70f076299c548c8afff53157205048ade26d40930af2ecc96d4f77e85915 23b767fa3cdbc45a8a210339c4a556cea2e0dfa3ee819b62e463f75d87a5 3c2fbd1bbcb8ec8fe2e8000ce37235fa903113c7b37d9c2a8b39c54b0203 0100010282010044b694716a946089fd0aeb3fbb2e3a5108ecb2b186466d 8d58904a4ba92213c7e9ddcccc5974fc275c3fa4f9ff2ccb816c3f996462 0df9870827ca7af4034f32f5e40c505121151a71bbb161b041e68b6e0159 363901a63b1fbcc6c3866da3127bf51e84125ebe452c8a7a513102dc0dfc 61331a2826fbcb4452d88aaa0f43ccfe436e1554f95bdd883c41e7e8529f acd7556ba539af3e083e7143ddf8637f67b59eea494b02396ff5089a1964 48dc8f7eb236d2f92a3358d0d6f5af1443205400bbd2758d3ec7cb208c11 7d78d68409f987fd6e43a93a26961c10c05f85458821594d242f8106856c 393f3b971cae1bfc20319e37147b22d2d2179ed5844e8102818100f27c96 e84d6ff814c56996a0e143fa85106d74e2eaa848347d8681bbcc396d85fc b51d318f543ad25090fe087e0e1ee0202f2ee8674e58609c22cc56e305c5 c55b016d0ca45c847ac88b59dd8a597388b09d7d5f86e2cdf60cb7660d94 a5e4e6f539506a6aacdf67fb9458b016a63d72392129eff5faa210a1739d 948ef0453b02818100daaf65e651382baed753222ab53dfb2f79ef96c6bd ec1c2822e5b8405900cf9203b2a0e015d12042cc9e686bbf3e5d2d732ed7 45e2a1cc1787637b8f14727dd5da11261d3a7cbe3521296f269cdf2a16ea 2974a710b14f3e61484d2580fef9c5bf4965a7a9ee6055a8c27867609408 7ef1643e81ab17307ca40b79166b693f310281803ed463719ba6f87bc14f 039579e8d83fa42b084f478804f57cd4de469fbafd92eb10ae98c9cf8452 3c47e55aa3f6daaf2e07abbad211adba929a3da201bedc28afd4e5c191d0 db0ec969ba063a33c548d4a269fad7836ae467151a1f48b5d762b4857e3d a4985866a3fc2322b52babde2dc95709730dd6f2423327d0775cf0430281 8100c4f14336c99c6992bb2e8e4da20de0c21ff14a7b4f9d6cba24bb7754 d412ebdc96e1ef09fffbe72ee172239e2d8c2f83f8008e34cce663942904 c9c8d0644fb920fb62b4ddf06ba813666a487eec67ce5d31da717e920048 b079d9a855e4caf270d3dbedc416fec1060ba53d8c77a4b31617ee46fedb 127a9d8e0b8dca4bed710281800c2fe643bfc8c81b39f1a574c751d2c5ee 0ce836a772197350f2f0a6a4d5248790a0cdf0c25a69a8834d645ea3c96e e740d95adeea689259ac4ce36a7310c86c9c35441fdd96ff8cec89a65f8c 8666bbc2a42cd2a58e70b1e8b2269ed6307c5a2143cbd41de4682dea4a38 8a7c8d2f4088e9a2008fa986f9b0e92fa517ecc77b % % dumpasn1 -p -a rsa-private-key.der SEQUENCE { INTEGER 0 INTEGER 00 CF 24 3C 32 4B 26 24 70 13 16 48 61 4B 62 EE 9C 52 AF 43 31 9C 24 98 A7 C1 6B A9 79 0B B3 A8 81 F9 60 F7 B0 30 3F 8F 49 E8 6F ED D6 81 3B E5 FA 88 83 93 55 D0 44 26 DF 00 50 DB B7 71 EB 68 37 73 B7 DD 92 99 49 69 50 93 F9 10 C8 DC DB 63 36 74 DE 98 6A DA 8D 64 3E 0E 81 9B 7C D5 AB 3B DE 43 72 10 37 97 47 2D C8 43 A2 71 16 99 E2 1A 4A FD DE ED 9F 62 81 03 16 90 34 57 34 2C 34 5A 35 EB B2 F0 6D A0 19 FE D2 AF A5 6E 78 56 6E 75 A0 D7 12 84 9A E2 55 15 5D 93 04 34 83 18 93 06 11 B3 B4 F1 15 3D 77 EE 59 70 F0 76 29 9C 54 8C 8A FF F5 31 57 20 50 48 AD E2 6D 40 93 0A F2 EC C9 6D 4F 77 E8 59 15 23 B7 67 FA 3C DB C4 5A 8A 21 03 39 C4 A5 56 CE A2 E0 DF A3 EE 81 9B 62 E4 63 F7 5D 87 A5 3C 2F BD 1B BC B8 EC 8F E2 E8 00 0C E3 72 35 FA 90 31 13 C7 B3 7D 9C 2A 8B 39 C5 4B INTEGER 65537 INTEGER 44 B6 94 71 6A 94 60 89 FD 0A EB 3F BB 2E 3A 51 08 EC B2 B1 86 46 6D 8D 58 90 4A 4B A9 22 13 C7 E9 DD CC CC 59 74 FC 27 5C 3F A4 F9 FF 2C CB 81 6C 3F 99 64 62 0D F9 87 08 27 CA 7A F4 03 4F 32 F5 E4 0C 50 51 21 15 1A 71 BB B1 61 B0 41 E6 8B 6E 01 59 36 39 01 A6 3B 1F BC C6 C3 86 6D A3 12 7B F5 1E 84 12 5E BE 45 2C 8A 7A 51 31 02 DC 0D FC 61 33 1A 28 26 FB CB 44 52 D8 8A AA 0F 43 CC FE 43 6E 15 54 F9 5B DD 88 3C 41 E7 E8 52 9F AC D7 55 6B A5 39 AF 3E 08 3E 71 43 DD F8 63 7F 67 B5 9E EA 49 4B 02 39 6F F5 08 9A 19 64 48 DC 8F 7E B2 36 D2 F9 2A 33 58 D0 D6 F5 AF 14 43 20 54 00 BB D2 75 8D 3E C7 CB 20 8C 11 7D 78 D6 84 09 F9 87 FD 6E 43 A9 3A 26 96 1C 10 C0 5F 85 45 88 21 59 4D 24 2F 81 06 85 6C 39 3F 3B 97 1C AE 1B FC 20 31 9E 37 14 7B 22 D2 D2 17 9E D5 84 4E 81 INTEGER 00 F2 7C 96 E8 4D 6F F8 14 C5 69 96 A0 E1 43 FA 85 10 6D 74 E2 EA A8 48 34 7D 86 81 BB CC 39 6D 85 FC B5 1D 31 8F 54 3A D2 50 90 FE 08 7E 0E 1E E0 20 2F 2E E8 67 4E 58 60 9C 22 CC 56 E3 05 C5 C5 5B 01 6D 0C A4 5C 84 7A C8 8B 59 DD 8A 59 73 88 B0 9D 7D 5F 86 E2 CD F6 0C B7 66 0D 94 A5 E4 E6 F5 39 50 6A 6A AC DF 67 FB 94 58 B0 16 A6 3D 72 39 21 29 EF F5 FA A2 10 A1 73 9D 94 8E F0 45 3B INTEGER 00 DA AF 65 E6 51 38 2B AE D7 53 22 2A B5 3D FB 2F 79 EF 96 C6 BD EC 1C 28 22 E5 B8 40 59 00 CF 92 03 B2 A0 E0 15 D1 20 42 CC 9E 68 6B BF 3E 5D 2D 73 2E D7 45 E2 A1 CC 17 87 63 7B 8F 14 72 7D D5 DA 11 26 1D 3A 7C BE 35 21 29 6F 26 9C DF 2A 16 EA 29 74 A7 10 B1 4F 3E 61 48 4D 25 80 FE F9 C5 BF 49 65 A7 A9 EE 60 55 A8 C2 78 67 60 94 08 7E F1 64 3E 81 AB 17 30 7C A4 0B 79 16 6B 69 3F 31 INTEGER 3E D4 63 71 9B A6 F8 7B C1 4F 03 95 79 E8 D8 3F A4 2B 08 4F 47 88 04 F5 7C D4 DE 46 9F BA FD 92 EB 10 AE 98 C9 CF 84 52 3C 47 E5 5A A3 F6 DA AF 2E 07 AB BA D2 11 AD BA 92 9A 3D A2 01 BE DC 28 AF D4 E5 C1 91 D0 DB 0E C9 69 BA 06 3A 33 C5 48 D4 A2 69 FA D7 83 6A E4 67 15 1A 1F 48 B5 D7 62 B4 85 7E 3D A4 98 58 66 A3 FC 23 22 B5 2B AB DE 2D C9 57 09 73 0D D6 F2 42 33 27 D0 77 5C F0 43 INTEGER 00 C4 F1 43 36 C9 9C 69 92 BB 2E 8E 4D A2 0D E0 C2 1F F1 4A 7B 4F 9D 6C BA 24 BB 77 54 D4 12 EB DC 96 E1 EF 09 FF FB E7 2E E1 72 23 9E 2D 8C 2F 83 F8 00 8E 34 CC E6 63 94 29 04 C9 C8 D0 64 4F B9 20 FB 62 B4 DD F0 6B A8 13 66 6A 48 7E EC 67 CE 5D 31 DA 71 7E 92 00 48 B0 79 D9 A8 55 E4 CA F2 70 D3 DB ED C4 16 FE C1 06 0B A5 3D 8C 77 A4 B3 16 17 EE 46 FE DB 12 7A 9D 8E 0B 8D CA 4B ED 71 INTEGER 0C 2F E6 43 BF C8 C8 1B 39 F1 A5 74 C7 51 D2 C5 EE 0C E8 36 A7 72 19 73 50 F2 F0 A6 A4 D5 24 87 90 A0 CD F0 C2 5A 69 A8 83 4D 64 5E A3 C9 6E E7 40 D9 5A DE EA 68 92 59 AC 4C E3 6A 73 10 C8 6C 9C 35 44 1F DD 96 FF 8C EC 89 A6 5F 8C 86 66 BB C2 A4 2C D2 A5 8E 70 B1 E8 B2 26 9E D6 30 7C 5A 21 43 CB D4 1D E4 68 2D EA 4A 38 8A 7C 8D 2F 40 88 E9 A2 00 8F A9 86 F9 B0 E9 2F A5 17 EC C7 7B } Import it with this code: let u = URL(fileURLWithPath: "rsa-private-key.der") guard let keyBytes = try? Data(contentsOf: u) else { … handle error … } guard let privateKey = SecKeyCreateWithData(keyBytes as NSData, [ kSecAttrKeyType: kSecAttrKeyTypeRSA, kSecAttrKeyClass: kSecAttrKeyClassPrivate, ] as NSDictionary, nil) else { … handle error … } print(privateKey) // prints: // <SecKeyRef algorithm id: 1, key type: RSAPrivateKey, version: 4, block size: 2048 bits, addr: …> Finally, an oft-forgotten feature of SecKeyCreateWithData is that it can undo a SubjectPublicKeyInfo wrapper. So, if you have an RSA public key wrapped in a SubjectPublicKeyInfo like this: % xxd -p public-key-rsa.der 30820122300d06092a864886f70d01010105000382010f003082010a0282 010100bce736006d9b0a2a49508f32e8d66f2b26236263a476f5a2eaf6af 34f0055b12b3bea5f5a62f3aab82274c3e3b21d15cc741100c670dd7687d 9c7e5c012d95bf5177993087df441c9944d10dff0767abfd6e412df279e4 e518b905e5582f967b6b2a64eeaeef712c594268fbff9cc2e63833ebffb7 f00c61fd7224ae2328047e13bbb904899e9ad5c9f44cfff5cd9a2df5a5b6 29bec605d6ecdce5dacba40cb119695f7c3dbd19e6fcd86a13700dfe6818 d1894aca9172a1e857540641971f7d7c9533aee2047c16c1c4f125e830b2 7d5e80d445c2fe09fa5586ee0bb105800fd1e8489e44b2f123eeef1cceeb eb1ba2d094923944181c513208c1f37fca31e50203010001 % % dumpasn1 -p -a public-key-rsa.der SEQUENCE { SEQUENCE { OBJECT IDENTIFIER rsaEncryption (1 2 840 113549 1 1 1) NULL } BIT STRING, encapsulates { SEQUENCE { INTEGER 00 BC E7 36 00 6D 9B 0A 2A 49 50 8F 32 E8 D6 6F 2B 26 23 62 63 A4 76 F5 A2 EA F6 AF 34 F0 05 5B 12 B3 BE A5 F5 A6 2F 3A AB 82 27 4C 3E 3B 21 D1 5C C7 41 10 0C 67 0D D7 68 7D 9C 7E 5C 01 2D 95 BF 51 77 99 30 87 DF 44 1C 99 44 D1 0D FF 07 67 AB FD 6E 41 2D F2 79 E4 E5 18 B9 05 E5 58 2F 96 7B 6B 2A 64 EE AE EF 71 2C 59 42 68 FB FF 9C C2 E6 38 33 EB FF B7 F0 0C 61 FD 72 24 AE 23 28 04 7E 13 BB B9 04 89 9E 9A D5 C9 F4 4C FF F5 CD 9A 2D F5 A5 B6 29 BE C6 05 D6 EC DC E5 DA CB A4 0C B1 19 69 5F 7C 3D BD 19 E6 FC D8 6A 13 70 0D FE 68 18 D1 89 4A CA 91 72 A1 E8 57 54 06 41 97 1F 7D 7C 95 33 AE E2 04 7C 16 C1 C4 F1 25 E8 30 B2 7D 5E 80 D4 45 C2 FE 09 FA 55 86 EE 0B B1 05 80 0F D1 E8 48 9E 44 B2 F1 23 EE EF 1C CE EB EB 1B A2 D0 94 92 39 44 18 1C 51 32 08 C1 F3 7F CA 31 E5 INTEGER 65537 } } } Import it with this code: let u = URL(fileURLWithPath: "public-key-rsa.der") guard let keyBytes = try? Data(contentsOf: u) else { … handle error … } guard let privateKey = SecKeyCreateWithData(keyBytes as NSData, [ kSecAttrKeyType: kSecAttrKeyTypeRSA, kSecAttrKeyClass: kSecAttrKeyClassPublic, ] as NSDictionary, nil) else { … handle error … } print(privateKey) // prints: // <SecKeyRef algorithm id: 1, key type: RSAPublicKey, version: 4, block size: 2048 bits, exponent: {hex: 10001, decimal: 65537}, modulus: …, addr: …> Import SECG Keys with Security Framework If you’re working with Security framework, use SecKeyCreateWithData to import an SECG key. If you have a secp256r1 public key in X9.63 format: % xxd p256-public-key.dat 00000000: 0497 47e9 81aa b8ea 71a2 55cd 9a15 6285 ..G.....q.U...b. 00000010: 8c40 6006 f1e4 1826 0d31 e1a7 7f6c 2b35 .@`....&.1...l+5 00000020: a9a3 132f 232d b003 51d9 d800 3487 d4ee .../#-..Q...4... 00000030: 5284 7990 313d aa7c 721f 88d4 bb56 da91 R.y.1=.|r....V.. 00000040: c7 . Import it with this code: let u = URL(fileURLWithPath: "p256-public-key.dat") guard let keyBytes = try? Data(contentsOf: u) else { … handle error … } guard let privateKey = SecKeyCreateWithData(keyBytes as NSData, [ kSecAttrKeyType: kSecAttrKeyTypeECSECPrimeRandom, kSecAttrKeyClass: kSecAttrKeyClassPublic, ] as NSDictionary, nil) else { … handle error … } print(privateKey) // prints: // <SecKeyRef curve type: kSecECCurveSecp256r1, algorithm id: 3, key type: ECPublicKey, version: 4, block size: 256 bits, y: …, x: …, addr: …> Note I’m using secp256r1 as an example. The code in this section will work for the other SECG key types, secp384r1 and secp521r1. And if you have a secp256r1 private key in X9.63 format: % xxd p256-private-key.dat 00000000: 0497 47e9 81aa b8ea 71a2 55cd 9a15 6285 ..G.....q.U...b. 00000010: 8c40 6006 f1e4 1826 0d31 e1a7 7f6c 2b35 .@`....&.1...l+5 00000020: a9a3 132f 232d b003 51d9 d800 3487 d4ee .../#-..Q...4... 00000030: 5284 7990 313d aa7c 721f 88d4 bb56 da91 R.y.1=.|r....V.. 00000040: c798 6a7a 91cb b5f4 f816 36e8 1aaf f083 ..jz......6..... 00000050: 5a77 1dc6 6865 c407 a8e8 4469 cf6a b8a4 Zw..he....Di.j.. 00000060: 77 w Import it with this code: let u = URL(fileURLWithPath: "p256-private-key.dat") guard let keyBytes = try? Data(contentsOf: u) else { … handle error … } guard let privateKey = SecKeyCreateWithData(keyBytes as NSData, [ kSecAttrKeyType: kSecAttrKeyTypeECSECPrimeRandom, kSecAttrKeyClass: kSecAttrKeyClassPrivate, ] as NSDictionary, nil) else { … handle error … } print(privateKey) // prints: // <SecKeyRef curve type: kSecECCurveSecp256r1, algorithm id: 3, key type: ECPrivateKey, version: 4, block size: 256 bits, addr: …> Import SECG Keys with Apple CryptoKit Apple CryptoKit can import SECG keys in three different ways: X9.63 raw key bytes DER encoding PEM encoding If you have a secp256r1 public key in X9.63 format, import it with this code: let u = URL(fileURLWithPath: "p256-public-key.dat") guard let keyBytes = try? Data(contentsOf: u) else { … handle error … } guard let publicKey = try? P256.Signing.PublicKey(x963Representation: keyBytes) else { … handle error … } print(publicKey) // prints: // PublicKey(impl: CryptoKit.CoreCryptoNISTCurvePublicKeyImpl<CryptoKit.P256.CurveDetails>(keyBytes: […]])) Note I’m using secp256r1 as an example. The code in this section will work for the other SECG key types, secp384r1 and secp521r1. If you have a secp256r1 private key in X9.63 format import it with this code: let u = URL(fileURLWithPath: "p256-private-key.dat") guard let keyBytes = try? Data(contentsOf: u) else { … handle error … } guard let privateKey = try? P256.Signing.PrivateKey(x963Representation: keyBytes) else { … handle error … } print(privateKey) // prints: // PrivateKey(impl: CryptoKit.CoreCryptoNISTCurvePrivateKeyImpl<CryptoKit.P256.CurveDetails>(key: CryptoKit.SecureBytes(backing: CryptoKit.SecureBytes.Backing))) CryptoKit can also import a DER-encoded SECG key. For example, it can import the following using the init(derRepresentation:) initialiser: % xxd -p public-key-p256.der 3059301306072a8648ce3d020106082a8648ce3d030107034200042c21f3 7049d4464afbf01813c51a4e1ef7a8101d2aa12b6a889635bc7c37e9011b fdd54006fdebdaef0d86a6d662561347982c95276013d1c1cd2d7865aff0 23 % % dumpasn1 -p -a public-key-p256.der SEQUENCE { SEQUENCE { OBJECT IDENTIFIER ecPublicKey (1 2 840 10045 2 1) OBJECT IDENTIFIER prime256v1 (1 2 840 10045 3 1 7) } BIT STRING 04 2C 21 F3 70 49 D4 46 4A FB F0 18 13 C5 1A 4E 1E F7 A8 10 1D 2A A1 2B 6A 88 96 35 BC 7C 37 E9 01 1B FD D5 40 06 FD EB DA EF 0D 86 A6 D6 62 56 13 47 98 2C 95 27 60 13 D1 C1 CD 2D 78 65 AF F0 23 } % % xxd -p private-key-p256.der 308187020100301306072a8648ce3d020106082a8648ce3d030107046d30 6b0201010420986a7a91cbb5f4f81636e81aaff0835a771dc66865c407a8 e84469cf6ab8a477a144034200049747e981aab8ea71a255cd9a1562858c 406006f1e418260d31e1a77f6c2b35a9a3132f232db00351d9d8003487d4 ee52847990313daa7c721f88d4bb56da91c7 % % dumpasn1 -p -a private-key-p256.der SEQUENCE { INTEGER 0 SEQUENCE { OBJECT IDENTIFIER ecPublicKey (1 2 840 10045 2 1) OBJECT IDENTIFIER prime256v1 (1 2 840 10045 3 1 7) } OCTET STRING, encapsulates { SEQUENCE { INTEGER 1 OCTET STRING 98 6A 7A 91 CB B5 F4 F8 16 36 E8 1A AF F0 83 5A 77 1D C6 68 65 C4 07 A8 E8 44 69 CF 6A B8 A4 77 [1] { BIT STRING 04 97 47 E9 81 AA B8 EA 71 A2 55 CD 9A 15 62 85 8C 40 60 06 F1 E4 18 26 0D 31 E1 A7 7F 6C 2B 35 A9 A3 13 2F 23 2D B0 03 51 D9 D8 00 34 87 D4 EE 52 84 79 90 31 3D AA 7C 72 1F 88 D4 BB 56 DA 91 C7 } } } } Finally, CryptoKit can import a PEM-encoded SECG. For example, it can import the following using the init(pemRepresentation:) initialiser: % cat public-key-p256.pem -----BEGIN PUBLIC KEY----- MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAELCHzcEnURkr78BgTxRpOHveoEB0q oStqiJY1vHw36QEb/dVABv3r2u8NhqbWYlYTR5gslSdgE9HBzS14Za/wIw== -----END PUBLIC KEY----- % cat private-key-p256.pem -----BEGIN PRIVATE KEY----- MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgmGp6kcu19PgWNuga r/CDWncdxmhlxAeo6ERpz2q4pHehRANCAASXR+mBqrjqcaJVzZoVYoWMQGAG8eQY Jg0x4ad/bCs1qaMTLyMtsANR2dgANIfU7lKEeZAxPap8ch+I1LtW2pHH -----END PRIVATE KEY----- Mapping SECG Keys between Apple CryptoKit and Security Framework If you need to map an SECG key from Apple CryptoKit to Security framework, or vice versa, use the X9.63 format. Imagine that you’re working in Security framework but you need to import a PEM key. SecKeyCreateWithData will not accept an SECG key in PEM format; it requires that the key be in X9.63 format. CryptoKit can import a PEM key but you want to continue using your existing Security framework code. Fortunately there’s a way out of this bind: Import the PEM key using Apple CryptoKit. Get the X9.63 representation. Create the Security framework key from that. For example, the following routine imports a PEM secp256r1 private key and returns a SecKey object: func createSecKeyWithPEMSecp256r1Private(_ pem: String) throws -> SecKey { let privateKeyCK = try P256.Signing.PrivateKey(pemRepresentation: pem) let x963Data = privateKeyCK.x963Representation var errorQ: Unmanaged<CFError>? = nil guard let privateKeySF = SecKeyCreateWithData(x963Data as NSData, [ kSecAttrKeyType: kSecAttrKeyTypeECSECPrimeRandom, kSecAttrKeyClass: kSecAttrKeyClassPrivate, ] as NSDictionary, &errorQ) else { throw errorQ!.takeRetainedValue() } return privateKeySF } To go the other way, from Security framework to CryptoKit, call SecKeyCopyExternalRepresentation to get the X9.63 representation of the key and then create a CryptoKit value using the init(x963Representation:) initialiser. Importing Curve 25519 Keys Apple CryptoKit supports Curve 25519 keys. If you have the raw bytes of a Curve 25519 public key: % xxd curve25519-public-key.dat 00000000: 910b f46f 0c0d c836 878f a708 60fd de21 ...o...6....`..! 00000010: 9d5f 6265 0a83 a7c5 923d 2ab7 4b81 76c5 ._be.....=*.K.v. Import it with this code: let u = URL(fileURLWithPath: "curve25519-public-key.dat") guard let keyBytes = try? Data(contentsOf: u) else { … handle error … } guard let publicKey = try? Curve25519.Signing.PublicKey(rawRepresentation: keyBytes) else { … handle error … } print(publicKey) // prints: // PublicKey(baseKey: CryptoKit.Curve25519.Signing.CoreCryptoCurve25519PublicKeyImpl(keyBytes: […])) If you have the raw bytes of a Curve 25519 private key: % xxd curve25519-private-key.dat 00000000: 9fd9 0805 255b ae86 a6c3 035b 2de8 37e9 ....%[.....[-.7. 00000010: 29ea 792e a11f d466 e67e d0b2 65c0 a999 ).y....f.~..e... Import it with this code: let u = URL(fileURLWithPath: "curve25519-private-key.dat") guard let keyBytes = try? Data(contentsOf: u) else { … handle error … } guard let privateKey = try? Curve25519.Signing.PrivateKey(rawRepresentation: keyBytes) else { … handle error … } print(privateKey) // prints: // PrivateKey(baseKey: CryptoKit.Curve25519.Signing.CoreCryptoCurve25519PrivateKeyImpl(key: CryptoKit.SecureBytes(backing: CryptoKit.SecureBytes.Backing))) Revision History 2025-02-04 Added a link to Importing a PEM-based RSA Private Key and its Certificate. Made other minor editorial changes. 2021-05-23 First posted.
0
0
5.2k
Feb ’25
Cannot revoke the account of Sign in with Apple
Our service has ended and the app has been removed from the App store. This app supported Sign in with Apple, but even if I try to revoke the account from the iOS settings or account.apple.com on the web, but can't delete it and no error is displayed. Does anyone know the cause of this problem or have encountered it? I'm not sure if it's related, but this app was previously transferred from another organization.
0
0
253
Jan ’25
Help! My computer shut of while I was trying to save my PN Key File
I am trying to finish my very first app. I went to save the PN key file and my computer shut off. I went to Certificates, Identifiers, and profiles and it says that I have reached the maximum allowed. I dont know what to do. I cant do anything with my app this is so stupid how could they make it so something like this was even possible. I am totally screwed. Please help me!
1
0
275
Oct ’24