Apple CryptoKit

RSS for tag

Perform cryptographic operations securely and efficiently using Apple CryptoKit.

Apple CryptoKit Documentation

Pinned Posts

Posts under Apple CryptoKit tag

32 Posts
Sort by:
Post not yet marked as solved
1 Replies
669 Views
AES 128 CBC algorithm is not producing same results compared to Android code. We have all static strings for key, iv and salt, even then the IV we couldnt match and produce same output as android. This is the Android code, object AESEncyption { ​ fun encrypt(strToEncrypt: String) : String? { try { val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding") val factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1") val spec: KeySpec = PBEKeySpec(secretKey.toCharArray(), hex(salt), iterationCount, keySize) val key: SecretKey = SecretKeySpec(factory.generateSecret(spec).encoded, "AES") cipher.init(Cipher.ENCRYPT_MODE, key, IvParameterSpec(hex(iv))) ​ return base64(cipher.doFinal(strToEncrypt.toByteArray(Charsets.UTF_8))) } catch (e: Exception) { Log.i("Him","Error while encrypting: $e") } return null } ​ private fun base64(bytes: ByteArray?): String { return android.util.Base64.encodeToString(bytes, android.util.Base64.DEFAULT) } ​ /* fun base64(str: String?): ByteArray? { return Base64.decodeBase64(str) }*/ ​ fun hex(bytes: ByteArray?): String? { return Hex.encodeHexString(bytes) } ​ fun hex(str: String): ByteArray? { return try { Hex.decodeHex(str.toCharArray()) } catch (e: DecoderException) { throw IllegalStateException(e) } } } iOS code is let enc = try AES(key: keyVar2!.bytes, blockMode: CBC(iv: iv.base64FromHex.ivToUInt8Array), padding: .pkcs5).encrypt(value.bytes) let encryptedData = Data(enc)
Posted Last updated
.
Post not yet marked as solved
4 Replies
4.6k Views
I have a Build Phase which runs a script. The script is a swift file, which I have simplified to illustrate the crash, like so: #!/usr/bin/env xcrun --sdk macosx swift import Foundation import CryptoKit var sha256 = SHA256() // Do other stuff... All the Xcode 15 betas fail to build my app, instead throwing the error: Command PhaseScriptExecution failed with a nonzero exit code. The logs: JIT session error: Symbols not found: [ _$s9CryptoKit6SHA256VMa, _$s9CryptoKit6SHA256VACycfC ] Failed to materialize symbols: { (main, { _$s20PropertyListModifier6sha2569CryptoKit6SHA256Vvp, _main, __swift_FORCE_LOAD_$_swiftDarwin_$_PropertyListModifier, __swift_FORCE_LOAD_$_swiftIOKit_$_PropertyListModifier, ___swift_project_value_buffer, __swift_FORCE_LOAD_$_swiftFoundation_$_PropertyListModifier, ___swift_allocate_value_buffer, __swift_FORCE_LOAD_$_swiftObjectiveC_$_PropertyListModifier, __swift_FORCE_LOAD_$_swiftXPC_$_PropertyListModifier, __swift_FORCE_LOAD_$_swiftCoreFoundation_$_PropertyListModifier, __swift_FORCE_LOAD_$_swiftDispatch_$_PropertyListModifier }) } Does anyone know of a work-around or solution, or does this just look like nothing more than a bug in the betas, which I should "wait out"? It's had the same problem right from beta 1 to the current beta 5 so it's starting to look like it won't be fixed which is worrying me.
Posted
by Haggis.
Last updated
.
Post not yet marked as solved
0 Replies
707 Views
Hi guys, I need to use deterministic ECDSA (described in RFC 6979 article: https://www.rfc-editor.org/rfc/rfc6979) algorithm to calculate signature in iOS project. It is known that deterministic ECDSA is vulnerable to fault injection and side-channel attacks, so there is an updates for RFC 6979 described in following article (see section 4): https://www.ietf.org/archive/id/draft-mattsson-cfrg-det-sigs-with-noise-04.html#name-updates-to-rfc-6979-determi I tried to find any information related to deterministic ECDSA algorithm implementation and support in iOS ecosystem, but unfortunately found nothing Could you please provide me complete information whether the deterministic ECDSA with updates is implemented and provides by iOS API? Any guidance or information on this matter would be greatly appreciated. Looking forward for you soon. ))
Posted
by Hayk_KQ.
Last updated
.
Post not yet marked as solved
4 Replies
924 Views
I'm trying to implement client certificate authentication in the URLSessionDelegate.urlSession(:didReceive:completionHandler:) by using the URLCredential(identity:certificates:persistence:) and CryptoKit, but it appears this is currently not supported. On my client I generate a key and a CSR and after I sent that to the server, I receive an X.509 certificate which I store in the Keychain. I used to create the keys as SecKey objects, which were also stored in the Keychain; this works fine. Now I would like to use the CryptoKit keys, preferably the SecureEnclave.P256 ones. It appears that storing these keys, as suggested by Apple (generic passwords), does not create the SecIdentity I'm after that's needed to create the URLCredential, nor have I been able to transform a SecKey created in the Secure Enclave to a CryptoKit.SecureEnclave.P256 key. The SecKeyCopyExternalRepresentation function simply returns an error telling me that I cannot export Secure Enclave keys (which is weird, as CryptoKit's implementation does somewhat allow this). Also, the URLCredential.init does not allow you to add a private key directly, nor does the SecIdentity provide any way of manually creating it, by supplying the right keys and the right certificates. How can I use CryptoKit for client certificate authentication or how can I use CryptoKit or the older SecKey implementations to create SecIdentity or URLCredential objects that will work?
Posted
by Craz1k0ek.
Last updated
.
Post not yet marked as solved
0 Replies
809 Views
I am trying to build csr string from publickeyBits and signature from dongle. Below is the swift code portion for generating csr. public func buildCSRAndReturnStringUsingDongle(enrollmentId: String, password: String) -> String? { let tagPublic = "public" + enrollmentId self.dongle = DongleManager.getInstance() self.dongle?.generateKeyPair(enrollmentId: enrollmentId, password: password) let publicKeyFromDongle: String = (self.dongle?.getPublicKeyBits(enrollmentId: enrollmentId, password: password))! print("Public Key is: \n",publicKeyFromDongle) let keyDict: [NSString: Any] = [ kSecAttrKeyType: kSecAttrKeyTypeRSA, kSecAttrKeyClass: kSecAttrKeyClassPublic, kSecAttrKeySizeInBits: 2048 as Any, kSecAttrApplicationTag: tagPublic.data(using: .utf8), ] var error: Unmanaged<CFError>? let publicKeyFromDongleData = Data.init(base64Encoded: publicKeyFromDongle) guard let publicKeySecKey = SecKeyCreateWithData(publicKeyFromDongleData! as CFData, keyDict as CFDictionary, &error) else { print("Failed to create public key:", error!.takeRetainedValue()) return nil } let publickeyBits = KeyPairManager.getInstance().getPublicKeyBits(publicKey: publicKeySecKey, enrollmentId: enrollmentId).0 let certificationRequestInfo = buldCertificationRequestInfo(publickeyBits!) let bytes: [UInt8] = certificationRequestInfo.map { $0 } let certificationRequestStr = String(decoding: bytes, as: UTF8.self) let signaturedString = self.dongle?.sign(password: password, data : certificationRequestStr, enrollmentId: enrollmentId) var signature = [UInt8](repeating: 0, count: 256) var signatureLen: Int = signature.count let signatureData = signaturedString!.data(using: .hexadecimal) signatureData!.copyBytes(to: &signature, count: signatureData!.count) signatureLen = signatureData!.count print("signature length: " + String(signatureLen)) print("signature: "+signatureData!.base64EncodedString()) var certificationRequest = Data(capacity: 1024) certificationRequest.append(certificationRequestInfo) let shaBytes = keyAlgorithm.sequenceObjectEncryptionType certificationRequest.append(shaBytes, count: shaBytes.count) var signData = Data(capacity: 2049) let zero: UInt8 = 0 // Prepend zero signData.append(zero) signData.append(signature, count: signatureLen) appendBITSTRING(signData, into: &certificationRequest) enclose(&certificationRequest, by: sequenceTag) // Enclose into SEQUENCE let csrString = certificationRequest.base64EncodedString(options: NSData.Base64EncodingOptions(rawValue: 0)) .addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed) print(csrString) let head = "-----BEGIN CERTIFICATE REQUEST-----\n" let foot = "-----END CERTIFICATE REQUEST-----\n" var isMultiple = false var newCSRString = head //Check if string size is a multiple of 64 if csrString!.count % 64 == 0 { isMultiple = true } for (integer, character) in csrString!.enumerated() { newCSRString.append(character) if (integer != 0) && ((integer + 1) % 64 == 0) { newCSRString.append("\n") } if (integer == csrString!.count-1) && !isMultiple { newCSRString.append("\n") } } newCSRString += foot return newCSRString } I wrote a Wrapper where sign function is as of given below. We had a getPublicBits() function here and i think that is working properly. So, I skip this here. - (NSString*) sign: (NSString*)password data: (NSString*)data enrollmentId: (NSString*)enrollmentId { Dongle *d = (Dongle*)****; char * pass = strdup([password UTF8String]); char * signDataStr = strdup([data UTF8String]); char * enId = strdup([enrollmentId UTF8String]); NSData* data2 = [data dataUsingEncoding:NSUTF8StringEncoding]; char *signData = (char *)[data2 bytes]; NSString* signaturedString = [NSString stringWithCString:d->sign(pass, signData, enId).c_str() encoding:[NSString defaultCStringEncoding]]; return signaturedString; } I used signUtil method from safenet sdk's library. std::string Dongle::signUtil(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hPrivateKey, char* password, char* data) { //std::cout<<"data is: " << *data; CK_RV retCode = CKR_OK; int isPaddingRequired = 0; int isDataFromUser = 0; CK_MECHANISM mech; CK_BYTE pSigData[3000]; #ifndef PKCS11_V1 CK_ULONG usSigLen = sizeof(pSigData); #else CK_ULONG usSigLen = 0; #endif char *pInputData = 0; unsigned long ulInputDataLen = strlen(data); std::cout << "length: " << ulInputDataLen; CK_BYTE_PTR pInData = (CK_BYTE_PTR)data; std::cout << "Mechanism: [6]SHA256-RSA" <<std::endl; retCode = C_Login(hSession, CKU_USER, (CK_UTF8CHAR_PTR)password, strlen(password)); mech.mechanism = CKM_SHA256_RSA_PKCS; mech.pParameter = 0; mech.ulParameterLen = 0; isDataFromUser = 0; if( retCode == CKR_OK ) { if( isPaddingRequired ) { for(unsigned long ulLoop=ulInputDataLen; ulLoop<64; ++ulLoop) { pInData[ulLoop] = 0; } ulInputDataLen = 64; } } if (retCode == CKR_OK) { retCode = C_SignInit(hSession, &mech, hPrivateKey); } CK_ULONG usInLen = (CK_ULONG)ulInputDataLen; // get the signature length if(retCode == CKR_OK) { retCode = C_Sign(hSession, pInData, usInLen, (CK_BYTE_PTR)NULL_PTR, &usSigLen); } // get the signature if(retCode == CKR_OK) { retCode = C_Sign(hSession, pInData, usInLen, (CK_BYTE_PTR)pSigData, &usSigLen); } std::string returnSignature = ""; if( (retCode == CKR_OK) && usSigLen ) { std::cout << "Signed Data " << std::endl << "(hex) "; for(unsigned long ulLoop=0; ulLoop<usSigLen; ++ulLoop) { char pBuffer[25]; sprintf(pBuffer, "%02x", pSigData[ulLoop]); std::cout << pBuffer; returnSignature += pBuffer; } std::cout << std::endl; } // Release memory if( pInputData ) { delete pInputData; } return returnSignature; } I debug a lot and according to csr decoder, only the signature is invalid. public key and signature algorithm are valid.
Posted Last updated
.
Post marked as solved
11 Replies
2.0k Views
My end goal is to use eciesEncryptionCofactorX963SHA256AESGCM with a key generated on the Secure Enclave using CryptoKit, that requires Biometric Authentication. CryptoKit does not implement the ECIES encryption algorithms, so my goal was to fall back to the Security framework. The public key can be easily converted to a SecKey because it implements x963Representation which can then be imported as follows: let enclaveSecKey: SecKey = SecKeyCreateWithData(enclaveKey.x963Representation as CFData, [ kSecAttrKeyType: kSecAttrKeyTypeECSECPrimeRandom, kSecAttrKeyClass: kSecAttrKeyClassPublic, kSecAttrKeySizeInBits: 256 ] as [String: Any] as CFDictionary, nil), I have everything working except the code to decrypt with the private key. Naturally, the Secure Enclave does not expose the private key - as is its design - rather some kind of token? I did read the Keychain documentation which notes that it is not possible to simply obtain an x963Representation of the private key (as it's a custom representation returned by the Secure Enclave). However, my ultimate question is this: can one convert the Secure Enclave representation into something that can be used as a SecKey for encryption/decryption (without necessarily being stored in the Keychain - i.e., 'correct') as it seems both CryptoKit and Security have a means of representing the private key token returned by the Secure Enclave? (Or is one's only recourse to use the Security framework for generating and storing the keys too?) I have also tried this code to create a SecKey representation, having retrieved the GenericPasswordConvertible out of the keychain (note the use of kSecAttrTokenID: kSecAttrTokenIDSecureEnclave) with the aforementioned goal of loading the Secure Enclave's private token as a SecKey: let enclaveSecKey: SecKey = SecKeyCreateWithData(enclaveKey.rawRepresentation as CFData, [ kSecAttrKeyType: kSecAttrKeyTypeECSECPrimeRandom, kSecAttrKeyClass: kSecAttrKeyClassPrivate, kSecAttrTokenID: kSecAttrTokenIDSecureEnclave, kSecAttrAccessible: kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly, kSecUseAuthenticationContext: try await createAuthContext( reason: "Decrypt data", fallbackTitle: "Enter your device password to decrypt data", mustEvaluate: true ), kSecAttrIsPermanent: true, kSecAttrIsExtractable: false, kSecAttrSynchronizable: false, kSecAttrKeySizeInBits: 256, kSecAttrAccessControl: SecAccessControlCreateWithFlags( nil, kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly, [.biometryAny, .privateKeyUsage], &cfSecKeyCreateError )! ] as [String: Any] as CFDictionary, nil) This works, in and of itself, (i.e., it loads without error and cfSecKeyCreateError is nil, however when I try SecSecKeyCopyPublicKey I get a different, incorrect public key and - naturally, I suppose - if I attempt to decrypt data with the private key that fails with: Optional(Swift.Unmanaged<__C.CFErrorRef>(_value: Error Domain=NSOSStatusErrorDomain Code=-50 "ECIES: Failed to aes-gcm decrypt data (err -69)" UserInfo={numberOfErrorsDeep=0, NSDescription=ECIES: Failed to aes-gcm decrypt data (err -69)}))
Posted
by samjakob.
Last updated
.
Post not yet marked as solved
7 Replies
1.9k Views
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?
Posted
by jzilske.
Last updated
.
Post not yet marked as solved
5 Replies
3.2k Views
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
Posted
by Helie.
Last updated
.
Post not yet marked as solved
8 Replies
7.0k Views
We have the below Implementation in Android and the same has to be integrated into Swift. Key :- "d95acd54b4a821ff32c52825q931c194" IV :- "687b9509c25a34b8ad076346s8353d67" Here Both the Key and IV are 32 bits and below is the android code. public class AESEncryption { private static final String key = "d95acd54c6a821ff32c52825b931c194"; private static final String initVector = "687b9509c25a14b8ad076346d8353d67"; static byte[] bte = hexToBytes(initVector); public static String encrypt(String strToEncrypt) { try { CommonCode.showLog("log", bte.toString()); IvParameterSpec iv = new IvParameterSpec(bte); SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "AES"); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING"); CommonCode.showLog("IV after logs", iv.toString()); cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv); byte[] encrypted = cipher.doFinal(strToEncrypt.getBytes()); if (Build.VERSION.SDK_INT &gt;= Build.VERSION_CODES.O) { return Base64.getEncoder().encodeToString(encrypted).trim(); } else { return android.util.Base64.encodeToString(encrypted, android.util.Base64.DEFAULT).trim(); } } catch (Exception e) { CommonCode.showLog("Error while encrypting: ", e.toString()); } return null; } public static String decrypt(String strToDecrypt) { try { IvParameterSpec iv = new IvParameterSpec(bte); SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "AES"); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING"); cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv); if (android.os.Build.VERSION.SDK_INT &gt;= android.os.Build.VERSION_CODES.O) { return new String(cipher.doFinal(Base64.getDecoder().decode(strToDecrypt))); } else { return new String(cipher.doFinal(android.util.Base64.decode(strToDecrypt, android.util.Base64.DEFAULT))); } } catch (Exception e) { CommonCode.showLog("Error while decrypting: " , e.toString()); } return null; } } How can we mimic the above in Swift? Here in Android they are using static byte[] bte = hexToBytes(initVector); to convert the 32bit IV into 16 bit Bytes Array I Have Tried the same approach on Swift below are the code snippet [Contents.swift](https://developer.apple.com/forums/content/attachment/60fab4f2-1496-4003-9f37-c195de95e94a)
Posted Last updated
.
Post not yet marked as solved
1 Replies
759 Views
Hi All. I have a need to store encrypted data on device. The data is arriving from multiple services in our app in the form of one line of text at a time. This data has to be decrypted on a server, probably using Java. In Java, there is concept of a CipherStream. I'll init that stream with a private key and IV (nonce), and feed it data as I get it. Once done, I can close the stream, and I have an encrypted file. In IOS, I'm trying to emulate that process. However, the concept of SealedBox seems to be getting in the way. I can seal each piece of text, but decrypting those doesn't work. I believe this has to do with the way the data is produced by the box. I can decrypt each piece individually, but I can't find a way to feed this into a stream and ultimately seal the whole thing. I understand I can write the file plain text, and encrypt it at the end, but this leaves the data vulnerable for long periods of time. Anyone has any Ideas on how to solve this on IOS?
Posted
by SK-Arctop.
Last updated
.
Post not yet marked as solved
6 Replies
1.5k Views
My need is to efficiently detects if OS supports secure enclave. There seems to be one way to decide if the Secure Enclave is present: Create an elliptic curve encryption key in the Secure Enclave, If this fails, and the error has a code of -4 = errSecUnimplemented, then there is no Secure Enclave. My question, is there any way other approach to detect if system supports secure enclave?
Posted
by antonl1.
Last updated
.