Post not yet marked as solved
I am slightly confused as to how I am supposed to maintain persistent access to a SecureEnclave.P256.Signing.PrivateKey. Do I have to persist the key myself (using its dataRepresentation property and code along the lines of Storing CryptoKit Keys in the Keychain or is there another persistent reference to the key inside the Secure Enclave that I can use later?
Post not yet marked as solved
General:
Apple Platform Security support document
Security Overview
Cryptography:
DevForums tags: Security, Apple CryptoKit
Security framework documentation
Apple CryptoKit framework documentation
Common Crypto man pages — For the full list of pages, run:
% man -k 3cc
For more information about man pages, see Reading UNIX Manual Pages.
On Cryptographic Key Formats DevForums post
SecItem attributes for keys DevForums post
CryptoCompatibility sample code
Keychain:
DevForums tags: Security
Security > Keychain Items documentation
On Mac Keychains DevForums post
Smart cards and other secure tokens:
DevForums tag: CryptoTokenKit
CryptoTokenKit framework documentation
Mac-specific frameworks:
DevForums tags: Security Foundation, Security Interface
Security Foundation framework documentation
Security Interface framework documentation
Related:
Networking Resources — This covers high-level network security, including HTTPS and TLS.
Network Extension Resources — This covers low-level network security, including VPN and content filters.
Code Signing Resources
Notarisation Resources
Trusted Execution Resources — This includes Gatekeeper.
App Sandbox Resources
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
Post not yet marked as solved
Can't seem to get CryptoKit to import. Is there some other configuration setting, etc. I need to fix? I though all you need to do in a playground is the import statement.
My code looks like this:
import UIKit
import CryptoKit
let string = "Hello world"
let data = Data(string.utf8)
let digest = SHA256.hash(data: data)
let hash = digest.compactMap { String(format: "%02x", $0)}.joined()
print("The hash is \(hash)")
Basically, I can't use any method from CryptoKit although when I was typing the import statement, soon as I typed 'Cr' I was prompted with the fill of 'CryptoKit'. It also working in an IoS project in Swift. So I know it's there. Just won't work in the playground. I get the following error message:
error: Couldn't lookup symbols:
static CryptoKit.HashFunction.hash<τ_0_0 where τ_1_0: Foundation.DataProtocol>(data: τ_1_0) -> τ_0_0.Digest
static CryptoKit.HashFunction.hash<τ_0_0 where τ_1_0: Foundation.DataProtocol>(data: τ_1_0) -> τ_0_0.Digest
static CryptoKit.HashFunction.hash<τ_0_0 where τ_1_0: Foundation.DataProtocol>(data: τ_1_0) -> τ_0_0.Digest
static CryptoKit.HashFunction.hash<τ_0_0 where τ_1_0: Foundation.DataProtocol>(data: τ_1_0) -> τ_0_0.Digest
static CryptoKit.HashFunction.hash<τ_0_0 where τ_1_0: Foundation.DataProtocol>(data: τ_1_0) -> τ_0_0.Digest
Appreciate any insights.
Thanks
Post not yet marked as solved
Hi,
I want to use the iOs Secure Enclave to create a "Primary Device" Mechanism. It would work like this.
Device Creates Enclave Key Pair and Sends the Public Key to the Server (Preferably Node JS)
The Server encrypts a random message with the Public Key and sends it to the Device. I can be sure the Device is the only one able to decipher that string, because the private key is safe in the Secure Enclave
Now the client would decrypt the message and send the result to the server which can compare it to the original message.
When de- and encrypting Data in the ios ecosystem the process is straightforward. I Encrypt Data using SecKeyCreateEncryptedData and Decrypt using SecKeyCreateDecryptedData passing Public Key and CipherText Objects.
Now my question is: how can I export the public Key to have my Node JS Backend encrypt Messages which will be decryptable again with the SecureEnclave.
Post not yet marked as solved
Hello,
I'm working with Cryptokit and I'm currently unable to export a P256 ECDSA signature data to base64Encoding and convert it back to derRepresentation.
Here is my code:
let privateKey = P256.Signing.PrivateKey()
//Generated successfully
/* For example pemRepresentation:
-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgK+lUhkqFo637XuvJ
Q6YiqZx04c33UUyWnLnpwfTwrtChRANCAARy55pVFhjgq3jKnQTx7s1XDIaNm20m
29ZEiBJnvzYfQGUQ+4ldzJYm34z8W2X/waqTqXsY4/oSO1sDFSQ6XwrG
-----END PRIVATE KEY-----
*/
let publicKey = privateKey.publicKey
//Picked up successfully
/* For example pemRepresentation:
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEcueaVRYY4Kt4yp0E8e7NVwyGjZtt
JtvWRIgSZ782H0BlEPuJXcyWJt+M/Ftl/8Gqk6l7GOP6EjtbAxUkOl8Kxg==
-----END PUBLIC KEY-----
*/
//Basic message to test, "something" here
let messageDigest = "something".data(using: .utf8)!
let signature = try privateKey.signature(for: messageDigest)
//Successfully generated
//Now from the PublicKey, let's check the signature for the message
let isValidSignature = publicKey.isValidSignature(signature, for: messageDigest)
//Successfully Return true
//So far everything works fine
//Now lets try to export the derRepresentation of the signature we just created to a base64EncodedString and try to use it later
let signDataDerRepresentation = signature.derRepresentation
//Here the signDataDerRepresentation is 70 bytes length
//Here we get the signature derRepresentation to base64EncodedString, perfect to export
let signDataDerRepresentationBase64String = signature.derRepresentation.base64EncodedString()
/*
"MEQCIGVC/zOGKEauy9AetVViTZiMTtFIeNtW9xALMTu6aIjSAiB+QPz9nGwzy51k3p3osu9OY6oQXkuLHTPoSWxPorg8GA=="
*/
//Here the signDataDerRepresentationBase64String is 96 bytes length
//Now when I try to create a signature from a derRepresentation it works fine when I use the original derRepresentation data:
let signature1 = try! P256.Signing.ECDSASignature(derRepresentation: signDataDerRepresentation)
//signature1 is created
//But when I try to create exactly the same signature from the base64EncodedString, an exception is throw
//Convert base64String to Data
let signDataDerRepresentationBase64StringData = signDataDerRepresentationBase64String.data(using: .utf8)!
do {
//Try to create a signature from the base64EncodedData of de the derRepresentation
let signature2 = try P256.Signing.ECDSASignature(derRepresentation: signDataDerRepresentationBase64StringData)
//Here it fails, signature2 is not created
}catch{
//It fails with error: invalidASN1Object
print("Signature failed \(error)")
/*
Signature failed invalidASN1Object
*/
}
So now, I would like to know how to convert de derRepresentation of the signature I created into a base64EncodedString to the derRepresentation the
ECDSASignature(derRepresentation:) func is looking for to create a signature from derRepresentation?
I don't understand how I can convert my base64 String into that derRepresentation this func is looking for, I can't find the doc :
/// An ECDSA (Elliptic Curve Digital Signature Algorithm) Signature
@available(iOS 13.0, macOS 10.15, watchOS 6.0, tvOS 13.0, *)
extension P256.Signing {
public struct ECDSASignature : ContiguousBytes {
/// Returns the raw signature.
/// The raw signature format for ECDSA is r || s
public var rawRepresentation: Data
/// Initializes ECDSASignature from the raw representation.
/// The raw signature format for ECDSA is r || s
/// As defined in https://tools.ietf.org/html/rfc4754
public init<D>(rawRepresentation: D) throws where D : DataProtocol
/// Initializes ECDSASignature from the DER representation.
public init<D>(derRepresentation: D) throws where D : DataProtocol
/// Calls the given closure with the contents of underlying storage.
///
/// - note: Calling `withUnsafeBytes` multiple times does not guarantee that
/// the same buffer pointer will be passed in every time.
/// - warning: The buffer argument to the body should not be stored or used
/// outside of the lifetime of the call to the closure.
public func withUnsafeBytes<R>(_ body: (UnsafeRawBufferPointer) throws -> R) rethrows -> R
/// A DER-encoded representation of the signature
public var derRepresentation: Data { get }
}
}
Thank you for your help.
Hélie
Post not yet marked as solved
Why does Cryptokit distinguish between private EC keys used for signing and key agreement? I noticed you can transform those keys into each other but for what purpose are they different? After all its an BigInt in both cases.
Post not yet marked as solved
I am trying to add my smart card PIV cert to ssh-agent.
In macOS 10.15 Catalina, it was as simple as:
ssh-add -s /usr/lib/ssh-keychain.dylib
But in macOS 11.1 Big Sur, the ssh-agent debug output says:
failed PKCS#11 add of "/usr/lib/ssh-keychain.dylib": realpath: No such file or directory
I am aware that macOS 11 caches system libraries ... but I believe that /usr/lib/ssh-keychain.dylib is in the cache.
Any help would be greatly appreciated!
I have a project that use secure enclave to encrypt my data, this project minimum supports from iOS 11.
To make sure the stability of my project, I run test, it has a loop to add, get, delete key in secure enclave for 100 iterations.
I found that the secure enclave always failed to add/get key from secure enclave when using iOS device that is iOS 12.x.
It returns error message - The operation couldn’t be completed. (OSStatus error -26276 - Key generation failed, error -26276)
error code -26276 is errSecInternal - An internal error occured in the Security framework.
I tested 23 devices, there are 5 out of 6 failed on iOS 12.x devices, the remaining devices with iOS 11.x, 13.x, 14.x, 15.x do not face this issue.
Why it only happens on iOS 12.x device?
Post not yet marked as solved
Hello,
I recently implemented the Cryptotokenkit for IOS in order to sign mails (via Apple Mail app). This part went relatively smooth.
I found in the Mail settings the parameter under S/MIME that enable Signing mails.
Now that this step is complete I also wanted to implement mail deciphering. I tried to run some tests but I met the following message when opening encrypted mail:
This message is encrypted. Install a profile containing your encryption identity to decrypt this message
I'm sure I've encrypted the mail for me. and I'm also sure the identity is saved and usable inside the Cryptotokenkit I implemented.
My questions are:
is it possible to use the Cryptotokenkit for mail deciphering? (I assume that since I can sign mail via Cryptotokenkit I can also do mail deciphering, right ?).
If the first question's answer is yes. then how do you enable the Cryptotokenkit to do mail deciphering? (I thought the option was close to the one for enabling signing mails but I only found mail encryption)
Post not yet marked as solved
I want to perform RSA encryption&Decryption using
SecKeyCreateEncryptedData()
Method allows public key as SecKey, My back end Java code has been set as encryption using private key & decryption using public key.
Here is a java code...
@SuppressLint("NewApi")
public static String encryptSecretKeyByPrivateKey(String data, String privatekeyPath) throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException {
byte[] plaintext = data.getBytes();
PrivateKey privateKey = getPrivatekey(privatekeyPath);
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
byte[] encryptedByte = cipher.doFinal(plaintext);
return Base64.getEncoder().encodeToString(encryptedByte);
}
public static PrivateKey getPrivatekey(String key) throws NoSuchAlgorithmException, InvalidKeySpecException {
PrivateKey privateKey = null;
KeyFactory keyFactory = null;
byte[] encoded = DatatypeConverter.parseBase64Binary(key);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encoded);
keyFactory = KeyFactory.getInstance("RSA");
privateKey = keyFactory.generatePrivate(keySpec);
return privateKey;
}
Can I achieve the same in swift with the help of SecKeyEncrypt() or SecKeyCreateEncryptedData() ?
Post not yet marked as solved
Does swift have default support for SHA3-256 hashing algorithm for all devices iOS 12 and above?
Post not yet marked as solved
good morning,
I saw one of your old post on decrypting on swift. can you guide me on how you achieved it. any sources will be very welcomed.
thank you
Post not yet marked as solved
let privateKey = Curve25519.KeyAgreement.PrivateKey() let publicKey = privateKey.publicKey
than what I do next?
my requirement keys are like
Public Key:
-——BEGIN PUBLIC KEY-----MIIBMTCB6gYHKoZIzj0CATCB3gIBATArBgcqhkjOPQEBAiB/////////////////////////////////////////7TBEBCAqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqYSRShRAQge0Je0Je0Je0Je0Je0Je0Je0Je0Je0Je0JgtenHcQyGQEQQQqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq0kWiCuGaG4oIa04B7dLHdI0UySPU1+bXxhsinpxaJ+ztPZAiAQAAAAAAAAAAAAAAAAAAAAFN753qL3nNZYEmMaXPXT7QIBCANCAARMyjhxmqctNgQJS5yef637I1SMM+Yg9PZ6VKF83hgCDH13bayEHj8I1nEPVO5pfyqATxOcOQS110iA9QJTEpsI-----END PUBLIC KEY-----
Private Key:
-----BEGIN PRIVATE KEY-----MIICRwIBADCB6gYHKoZIzj0CATCB3gIBATArBgcqhkjOPQEBAiB/////////////////////////////////////////7TBEBCAqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqYSRShRAQge0Je0Je0Je0Je0Je0Je0Je0Je0Je0Je0JgtenHcQyGQEQQQqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq0kWiCuGaG4oIa04B7dLHdI0UySPU1+bXxhsinpxaJ+ztPZAiAQAAAAAAAAAAAAAAAAAAAAFN753qL3nNZYEmMaXPXT7QIBCASCAVMwggFPAgEBBCAOeSuzq+O1tPlhPZj4KZdfAq5Z0+yca15ukbUuwsyJQKCB4TCB3gIBATArBgcqhkjOPQEBAiB/////////////////////////////////////////7TBEBCAqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqYSRShRAQge0Je0Je0Je0Je0Je0Je0Je0Je0Je0Je0JgtenHcQyGQEQQQqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq0kWiCuGaG4oIa04B7dLHdI0UySPU1+bXxhsinpxaJ+ztPZAiAQAAAAAAAAAAAAAAAAAAAAFN753qL3nNZYEmMaXPXT7QIBCKFEA0IABG56w6jtAyb2T6oguKNN6HvLPQdT0Mms8gCepW51pobrDT/WfXJKfFr5fRuNalS+YkDQggoc7xtpYFin0ELidYw=-----END PRIVATE KEY-----
Post not yet marked as solved
I want to generate a Curve25519 key pair with ECDH for the encryption and decryption. I'm using the CryptoKit to generates a keypair.
But, I failed to generate a keypair with the ECDH algorithm.
func generateKeys() -> (publicKey: String, privateKey: String){
let privateKey = Curve25519.KeyAgreement.PrivateKey()
let publicKey = privateKey.publicKey
let publicKeyString = "-----BEGIN PUBLIC KEY-----\(publicKey.rawRepresentation.base64EncodedString())-----END PUBLIC KEY-----"
print(publicKeyString)
let privateKeyString = "-----BEGIN PRIVATE KEY-----\(privateKey.rawRepresentation.base64EncodedString(options: .lineLength64Characters))-----END PRIVATE KEY-----\r\n"
print(privateKeyString)
return (publicKeyString, [rivateKeyString)
}
Output:
-----BEGIN PUBLIC KEY-----WSOOXYN/FaCOn4SAlvrW3q4IYueiS8Io+WqL64T2QQA=-----END PUBLIC KEY-----
-----BEGIN PRIVATE KEY-----AAlH4v1vcnmjEKVJrhbarMqCrcNWYZgFwnhReduEokk=-----END PRIVATE KEY-----
Here is one of the Java code using bouncycastle
{
"privateKey": "-----BEGIN PRIVATE KEY-----MIICRwIBADCB6gYHKoZIzj0CATCB3gIBATArBgcqhkjOPQEBAiB/////////////////////////////////////////7TBEBCAqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqYSRShRAQge0Je0Je0Je0Je0Je0Je0Je0Je0Je0Je0JgtenHcQyGQEQQQqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq0kWiCuGaG4oIa04B7dLHdI0UySPU1+bXxhsinpxaJ+ztPZAiAQAAAAAAAAAAAAAAAAAAAAFN753qL3nNZYEmMaXPXT7QIBCASCAVMwggFPAgEBBCAOeSuzq+O1tPlhPZj4KZdfAq5Z0+yca15ukbUuwsyJQKCB4TCB3gIBATArBgcqhkjOPQEBAiB/////////////////////////////////////////7TBEBCAqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqYSRShRAQge0Je0Je0Je0Je0Je0Je0Je0Je0Je0Je0JgtenHcQyGQEQQQqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq0kWiCuGaG4oIa04B7dLHdI0UySPU1+bXxhsinpxaJ+ztPZAiAQAAAAAAAAAAAAAAAAAAAAFN753qL3nNZYEmMaXPXT7QIBCKFEA0IABG56w6jtAyb2T6oguKNN6HvLPQdT0Mms8gCepW51pobrDT/WfXJKfFr5fRuNalS+YkDQggoc7xtpYFin0ELidYw=-----END PRIVATE KEY-----",
"errorInfo": null,
"KeyMaterials": {
"cryptoAlg": "ECDH",
"curve": "curve25519",
"params": "",
"DHPublicKey": {
"expiry": "2021-12-15T11:29:20.848Z",
"Parameter": "",
"KeyValue": "-----BEGIN PUBLIC KEY-----MIIBMTCB6gYHKoZIzj0CATCB3gIBATArBgcqhkjOPQEBAiB/////////////////////////////////////////7TBEBCAqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqYSRShRAQge0Je0Je0Je0Je0Je0Je0Je0Je0Je0Je0JgtenHcQyGQEQQQqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq0kWiCuGaG4oIa04B7dLHdI0UySPU1+bXxhsinpxaJ+ztPZAiAQAAAAAAAAAAAAAAAAAAAAFN753qL3nNZYEmMaXPXT7QIBCANCAARuesOo7QMm9k+qILijTeh7yz0HU9DJrPIAnqVudaaG6w0/1n1ySnxa+X0bjWpUvmJA0IIKHO8baWBXp9BC4mMW-----END PUBLIC KEY-----"
}
}
}
Can anyone guide me for the same keys like java?
Post not yet marked as solved
Hi there
TL;DR : I have a Data object which contains data that is already hashed. I need a Digest object, how should I proceed ?
I am developing an OSX Smart Card Token Extension to handle certificates linked to private keys in the Secure Enclave (using CryptoKit).
So far my first tests are pretty successful as my extension already answered to various signature requests successfully... until now.
So far I was receiving signature requests for ecdsaSignatureMessageX962SHA256 algorithm.
All I had to do with was something like this:
func tokenSession(_ session: TKTokenSession, sign dataToSign: Data, keyObjectID: Any, algorithm: TKTokenKeyAlgorithm) throws -> Data {
if let privateKey = try? SecureEnclave.P256.Signing.PrivateKey.init(dataRepresentation: keyObjectID as! Data) {
let rawsignature = try? privateKey.signature(for: dataToSign)
return rawsignature!.derRepresentation
}
}
Now I receive requests for ecdsaSignatureDigestX962SHA256 signatures. I noticed that there is a
public func signature<D>(for digest: D) throws -> P256.Signing.ECDSASignature where D : Digest
function that can be called but in the tokenSession i am only given Data...
Looking at SHA256Digest documentation I can't find anything to create the digest from bytes. It seems that it can only be the result of a SHA256.hash operation.
I thought of using older API like SecKeyCreateSignature but I don't think I can retrieve a SecKey from a private key generated with CryptoKit SecureEnclave.P256.Signing.PrivateKey.init
I feel like I may be missing something really simple...
Post not yet marked as solved
As I read the apple documentation on secure enclave and key chain, extraction of private key is not allowed. following is the reference:
"Can’t import preexisting keys. You must create keys directly inside the Secure Enclave. Not having a mechanism to transfer key data into or out of the Secure Enclave is fundamental to its security."
Link: https://developer.apple.com/documentation/security/certificate_key_and_trust_services/keys/storing_keys_in_the_secure_enclave
But after loading the key using "SecItemCopyMatching" and then passing the object into "SecKeyCopyAttributes" gives us a dictionary of key value pairs. I believe that the private key was part of the value for key "toid" of that dictionary.
is my understanding correct or, am I missing something?
I couldn't find the documentation describing the meaning of the key value pairs of the dictionary returned by "SecKeyCopyAttributes". I'll appreciate if somebody can guide me to that documentation.
Note: I am creating EC key pair.
Post not yet marked as solved
Hi,
for some of our users the app crashes when we try to get the EdDSA signature using the private key.
We use the following method from CryptoKit in the Curve25519.Signing.PrivateKey extension:
public func signature<D>(for data: D) throws -> Data where D : DataProtocol
The data that we want to sign is a string that is converted using the algorithm SHA256
Our implementation looks something like this:
func foo(text: String) throws -> String {
var algorithm = SHA256()
algorithm.update(data: text.data(using: .utf8)!)
guard self.hasPrivateKey else {
// Error handling
}
do {
let signature = try self.privateKey.signature(for: algorithm.finalize()) // App crashes here if not using do-catch statement
// signature will be used and transformed to return String...
} catch {
// Error handling
}
}
I would appreciate any hints on how to solve or inspect this.
Many thanks.
Post not yet marked as solved
I have used Apple API - Apple CryptoKit | Apple Developer Documentation in my project .
While Archieving the Project , I gives out an error ,And build Fails .
The Same Project works well in Xcode 12_4 .
Only after I updated my Xcode to Xcode13. This Error Started Occurring .
Xcode12_4 - Catalina Mac
Xcode 13 - BigSur Mac.
Whether It may be due to Bigsur ?
Does Any other reproduces this Error?
Can Anyone Help me in this?
Post not yet marked as solved
So, I've been trying to inter-operate with CryptoKit, and my backend running on Linux, and it appears that the documentation here is incorrect. It claims that the data is first digested with SHA256, but my testing seems to say that the convenience Data functions is actually done with SHA512
import CryptoKit
import Foundation
typealias Key = P521.Signing.PrivateKey
func verify1() throws {
let key = Key()
let data = "1 2 3 4 5 6 7 8 9 0".data(using: .ascii)!
let digest = SHA256.hash(data: data)
let signature = try key.signature(for: digest)
let verified = key.publicKey.isValidSignature(signature, for: data)
print("verified \(verified)")
}
func verify2() throws {
let key = Key()
let data = "1 2 3 4 5 6 7 8 9 0".data(using: .ascii)!
let digest = SHA512.hash(data: data)
let signature = try key.signature(for: digest)
let verified = key.publicKey.isValidSignature(signature, for: data)
print("verified \(verified)")
}
func main() {
do {
try verify1()
try verify2()
}
catch {
print(error.localizedDescription)
}
}
main()
(My Generic-Fu was insufficient to avoid the copy paste)
When the above is run on my machine I get:
% swift test.swift
verified false
verified true
Is my diagnosis correct?
Post not yet marked as solved
I am trying to use the HMAC function in a swift package but it does not work it only works in standard view controller style packages.
let hash = HMAC<Insecure.SHA1>.authenticationCode(for: counterData, using: SymmetricKey(data: secret))