Create and Encrypt Secret Key in iOS

I am encrypting my request & response in iOS to send it to server end ,
Request Format
{
Code Block
"encryptionFlag": "ENABLE",
"encryptedText": "Encrypted request",
"encryptedSecretKeyString": "Encrypted secret key"
}


Response Format
{
"encryptedResponse":"Encrypted respone"
"encryptedResponseSecretKey": "Encrypted secret key"

}

I have to figure out how to create Secret Key in iOS
Is SecKeyCreateRandomKey is the right method for this??
Please help!!
Sorry, but your question does not contain any info about your Request Format.
Please ask to your server side engineer and show the detailed description of each field of Request.
I am encrypting my request & response in iOS to send it to server end ,
I am not aware of creating "The secret Key" that is a random key to be generated while sending the requests and the request(Dictionary) will be encrypted with the Secret Key and then the Secret key has to be encrypted with the Server side Public Key which I have received as

Server Public Key
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCBdWolKbgXt3O5I33yETJvrmOlphJ5bM/8VmvYdJhUKN++xpwSzGZvgunqdWqu63yHVg/eznwTUi3fniWQ+nu6S1peU0JLh9FhfIcqpD4YbXJkGnFwLhNoKpB0moDbwS5X0Zr3ib+6YzhMtQoswP6qPZqOUgk3Xkd8DaWpyYXqNQIDAQAB

Request Format 
{
"encryptionFlag": "ENABLE",
"encryptedText": "Encrypted request",
"encryptedSecretKeyString": "Encrypted secret key"
}

Response Format

{
"encryptedResponse":"Encrypted respone"
"encryptedResponseSecretKey": "Encrypted secret key"

}

Encrypted Request is a Dictionary..
I hope I am Clear this time ...
Decryption Process I am clear with as helped by OOPer,
Encryption process is what I need help for.
Thanks!!

little Update to above question of mine "the secret key is AES 128bit key"
Thanks for further description.

creating "The secret Key" that is a random key to be generated

the secret key is AES 128bit key

Seems you need to create a random key of size 128-bit (16-byte).

AES keys can be an arbitrary bit sequence of the specified size. But if you want to generate a secure enough key, there's SecRandomCopyBytes.

You can use something like this:
Code Block
var secretKey: Data = Data(count: 16)
let status = secretKey.withUnsafeMutableBytes { bufPtr in
SecRandomCopyBytes(kSecRandomDefault, bufPtr.count, bufPtr.baseAddress!)
}
guard status == errSecSuccess else {
print("SecRandomCopyBytes")
exit(1) //<- Used while testing in Command Line Tool
}
print(secretKey as NSData)


You need to encrypt (AES) the request text using this secretKey as key, to get encryptedText.
(You may need to convert the request Dictionary to text before this encryption.)
You also need to encrypt (RSA) this secretKey using your Public Key as key and get encryptedSecretKeyString.
Thanks OOPer ,
I created the random key as you said,

Step 1 : create Secret Key :
Code Block
var secretKey: Data = Data(count: 16)
let status = secretKey.withUnsafeMutableBytes { bufPtr in
SecRandomCopyBytes(kSecRandomDefault, bufPtr.count, bufPtr.baseAddress!)
 }
 guard status == errSecSuccess else {
                print("SecRandomCopyBytes")
                exit(1)
        }
        print(secretKey as NSData)

Step 1 : Done

Step2 : encrypt Text with Secret Key
Code Block
 var txtEncrypt = try! aesCBCEncrypt(data: utf8str ?? Data.init(), keyData: secretKeyData)
 let strText = txtEncrypt.base64EncodedString() /*Output : eGiFQmRxY4yniKYe2KFvPnXIeMX697h2OGcc2MjIyS8g=*/
func aesCBCEncrypt(data:Data, keyData:Data) throws -> Data {
        let keyLength = keyData.count
        let validKeyLengths = [kCCKeySizeAES128, kCCKeySizeAES192, kCCKeySizeAES256]
        if (validKeyLengths.contains(keyLength) == false) {
            throw AESError.KeyError(("Invalid key length", keyLength))
        }
        let ivSize = kCCBlockSizeAES128;
        let cryptLength = size_t(ivSize + data.count + kCCBlockSizeAES128)
        var cryptData = Data(count:cryptLength)
        let status = cryptData.withUnsafeMutableBytes {ivBytes in
            SecRandomCopyBytes(kSecRandomDefault, kCCBlockSizeAES128, ivBytes)
        }
        if (status != 0) {
            throw AESError.IVError(("IV generation failed", Int(status)))
        }
        var numBytesEncrypted :size_t = 0
        let options   = CCOptions(kCCOptionPKCS7Padding)
        let cryptStatus = cryptData.withUnsafeMutableBytes {cryptBytes in
            data.withUnsafeBytes {dataBytes in
                keyData.withUnsafeBytes {keyBytes in
                    CCCrypt(CCOperation(kCCEncrypt),
                            CCAlgorithm(kCCAlgorithmAES),
                            options,
                            keyBytes, keyLength,
                            cryptBytes,
                            dataBytes, data.count,
                            cryptBytes+kCCBlockSizeAES128, cryptLength,
                            &numBytesEncrypted)
                }
            }
        }
        if UInt32(cryptStatus) == UInt32(kCCSuccess) {
            cryptData.count = numBytesEncrypted + ivSize
        }
        else {
            throw AESError.CryptorError(("Encryption failed", Int(cryptStatus)))
        }
        return cryptData;
    }

So , thus Step2 is done .

Now, step 3 : encrypt Secret Key with server Public Key which i am getting stuck at as
server Public key is MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCBdWolKbgXt3O5I33yETJvrmOlphJ5bM/8VmvYdJhUKN++xpwSzGZvgunqdWqu63yHVg/eznwTUi3fniWQ+nu6S1peU0JLh9FhfIcqpD4YbXJkGnFwLhNoKpB0moDbwS5X0Zr3ib+6YzhMtQoswP6qPZqOUgk3Xkd8DaWpyYXqNQIDAQAB

Converted it to Data also :
let serverPublicKeyData = Data(base64Encoded: serverPublicKey)!

Next ,I want to convert it secKey to then encrypt it using SecKeyCreateEncryptedData but it is giving me error!!
I hope I am going right way?
Please help!!

convert it secKey

then encrypt it using SecKeyCreateEncryptedData

More accurately, encrypt secretKey with the SecKey as key using SecKeyCreateEncryptedData

Each step seems to be the right way to go. What sort of error have you got? Also, please show your code.
Thanks OOPer,

Code Block
let serverPublicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCBdWolKbgXt3O5I33yETJvrmOlphJ5bM/8VmvYdJhUKN++xpwSzGZvgunqdWqu63yHVg/eznwTUi3fniWQ+nu6S1peU0JLh9FhfIcqpD4YbXJkGnFwLhNoKpB0moDbwS5X0Zr3ib+6YzhMtQoswP6qPZqOUgk3Xkd8DaWpyYXqNQIDAQAB"
 let serverPublicKeyData = Data(base64Encoded: serverPublicKey)!
       

Here Public key data , now through following code try to get Public Sec Key.

Code Block
    let attributesPublic: [String: Any] = [
                             kSecAttrKeyType as String: kSecAttrKeyTypeRSA,
                             kSecAttrKeyClass as String: kSecAttrKeyClassPublic
                         ]
                 var errorPublic: Unmanaged<CFError>?
                let publicSecKey : SecKey = SecKeyCreateWithData(serverPublicKeyData as CFData, attributes as CFDictionary, &error)!
/*Error in the above line as we used as "!" so it is getting crash */
}

how will I get Public sec key ??
Please help!!
Forced unwrapping is sort of risky and you should better avoid it. But I cannot run it as it does not compile.
The line 6 should be let publicSecKey : SecKey = SecKeyCreateWithData(serverPublicKeyData as CFData, attributesPublic as CFDictionary, &errorPublic)!.

Please show the exact code you run.
Thanks OOPer , sorry my mistake , Correct code
Code Block
 let attributesPublic: [String: Any] = [
                             kSecAttrKeyType as String: kSecAttrKeyTypeRSA,
                             kSecAttrKeyClass as String: kSecAttrKeyClassPublic
                         ]
                 var errorPublic: Unmanaged<CFError>?
                 let publicSecKey : SecKey = SecKeyCreateWithData(serverPublicKeyData as CFData, attributesPublic as CFDictionary, &error)!

I am now able to get the Public Key through this , Thanks,

Step 4 : Encrypting secret key with this private Key :
Code Block
    var errorSecPublic: Unmanaged<CFError>?
         let SecKeyEncryptedData = SecKeyCreateEncryptedData(publicSecKey,
                                                       algorithm,
                                                       secretKeyDataEncryption as CFData,
                                                       &errorSecPublic) as Data?
             guard SecKeyEncryptedData != nil else {
               print("can not encrypt")
                 return
             }
             print(SecKeyEncryptedData! as NSData)
        let secKeyEncoded = SecKeyEncryptedData?.base64EncodedString()
        print(secKeyEncoded)

Step 4 is also went well ... able to get encrypted secret kay , I think going right way , But issue is
when I am trying to extract the encrypted text , using same steps we did yesterday , but it is failing at retrieving the encrypted Secret Key i.e Step 3 of yesterday's decrypting code process , may be have not encrypted secret key properly.
i.e in following code
Code Block
let algorithm: SecKeyAlgorithm = .rsaEncryptionOAEPSHA1
   guard SecKeyIsAlgorithmSupported(privateSecKey, .decrypt, algorithm) else {
   print("can not decrypt")
    return
   }
      var errorSec: Unmanaged<CFError>?
    let SecKeyDecryptedData = SecKeyCreateDecryptedData(privateSecKey,
                                                  algorithm,
                                                  SecretKeyData as CFData,
                                                  &errorSec) as Data?
        guard SecKeyDecryptedData != nil else {
          print("can not decrypt") /* failing in this */
            return
        }
        print(SecKeyDecryptedData! as NSData)

AS, private sec key is the same as retrieved yesterday have not changed , only encrypted secret key have changed as of generated new one after encryption today.
Please help!!!
My side encrypted text generated is : "xLJSdTqGj/ViCgwMATPMy1hvusHU3pCPpTIo7DlGfjs="
and encrypted Secret key is :

"U9j90pWZHS9TGdEtJmLMThKjjKobcXh9M8Op69kZHdHa8U4GSpRoIw1PRSnms3WdntvreLVMRv8zzSkodg3CnHyRha1tW6PCYQfxTtj5fFpMNZG8K7mWCruIvXm3gWQHJIuUcnqE6LHke6vBzUdFY/i2pWQmHPQIbhcgwPEQoyM="
Your Correct code does not compile.

Use of unresolved identifier 'error'

I really doubt if you tried the code, if your response is reliable.

Thanks OOPer,
I am really Sorry, I am doing the code but there was error type already declared somewhere else in the code , so it was compiling at my end.

Code Block
 let attributesPublic: [String: Any] = [
                             kSecAttrKeyType as String: kSecAttrKeyTypeRSA,
                             kSecAttrKeyClass as String: kSecAttrKeyClassPublic
                         ]
                 var errorPublic: Unmanaged<CFError>?
                 let publicSecKey : SecKey = SecKeyCreateWithData(serverPublicKeyData as CFData, attributesPublic as CFDictionary, &errorPublic)!

Hi OOPer,
Previous message is step 3...
Step 4 ,Encrypting secret key using public key :

Code Block
/* Step 4 */
           let algorithmPub: SecKeyAlgorithm = .rsaEncryptionOAEPSHA1
           guard SecKeyIsAlgorithmSupported(publicSecKey, .decrypt, algorithmPub) else {
           print("can not ecrypt using the algorithm")
            return
           }
        var errorSecPublic: Unmanaged<CFError>?
         let SecKeyEncryptedData = SecKeyCreateEncryptedData(publicSecKey,
                                                       algorithmPub,
                                                       secretKeyDataEncryption as CFData,
                                                       &errorSecPublic) as Data?
             guard SecKeyEncryptedData != nil else {
               print("can not encrypt")
                 return
             }
             print(SecKeyEncryptedData! as NSData)
        let secKeyEncoded = SecKeyEncryptedData?.base64EncodedString()
        print(secKeyEncoded)


Hi ,OOPer,
Now , Next trying to decrypt the encrypted text and encrypted secret key using the process already discovered yesterday.

So I put all the steps covered yesterday working fine till step 3 i.e getting encrypted secret key from private key

Code Block
   /* Step 3 */
   let algorithm: SecKeyAlgorithm = .rsaEncryptionOAEPSHA1
   guard SecKeyIsAlgorithmSupported(privateSecKey, .decrypt, algorithm) else {
   print("can not decrypt")
    return
   }
    var errorSec: Unmanaged<CFError>?
    let SecKeyDecryptedData = SecKeyCreateDecryptedData(privateSecKey,
                                                  algorithm,
                                                  SecretKeyData as CFData,
                                                  &errorSec) as Data?
        guard SecKeyDecryptedData != nil else {
          print("can not decrypt") /*Failing in this line*/
            return
        }
        print(SecKeyDecryptedData! as NSData)


Can not move forward to decrypted text step.
Please help!!

/**_*

Replying again with all these steps , as there was some issue in that

correct code post___** */
Thanks OOPer , I am just Stuck with one thing , else everything is sorted.

I have been able to create encrypted Secret Key through following method :

Code Block
let algorithmPub: SecKeyAlgorithm = .rsaEncryptionOAEPSHA1
           guard SecKeyIsAlgorithmSupported(publicSecKey, .encrypt, algorithmPub) else {
           print("can not ecrypt using the algorithm")
            return
           }
        var errorSecPublic: Unmanaged<CFError>?
         let SecKeyEncryptedData = SecKeyCreateEncryptedData(publicSecKey,
                                                       algorithmPub,
                                                       secretKeyDataEncryption as CFData,
                                                       &errorSecPublic) as Data?
             guard SecKeyEncryptedData != nil else {
               print("can not encrypt")
                 return
             }
             print(SecKeyEncryptedData! as NSData)
        let secKeyEncoded = SecKeyEncryptedData?.base64EncodedString()
        print(secKeyEncoded as Any)

Code Block
  let EncrytedsecretKey =
    """
F0bm76F4uyk+e8Ds9ZDEkaUEzD3+BE3of8ncxfuBJz1YIsoEJzeXAGnGPu+Vcs99XyLitGPcD3O7k6+mWnhFiPQAOrDzr+3h6TgkVlimxBA3Srxi1lbkJrcy4/j6iNHAAlAL3LNaUxB9ph6DGkPDVKSV79jqyOZbsqPsaFyp/XU=
      """
let privateKeyString  = """
    MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAJitrKyHsfJtNHcr0dXvv0hV8iq0/2cefgXlgVg4HGj1Z5036ZuKCZONx3pFJ9fsKM2kDovEWsUA2hGHQvaGfzjkt19p6PmN8r56VnTXDrxHQOLXPAE3T7eQSA/g7IqfqT1ILkGX/80J2jqNRGJhDKsZ3IcWa1T4lVsqLAoiNNPNAgMBAAECgYAKYFNJ7nbziOR17O534bFYUy8AJAjvkyzxbaWav0V/BJ6kGravsXPxKUOTVbvdetlTEIFEknWwydwIMO8mHgHrWtprRI7COkV1l46UgObgXTQp/Nwfqukki2TenbbAo/Ja72+CMycOy3IzvW2+Qd0ZwFHheUmLE4lF7fHssSMJwQJBAOAc8ph+hR64jvJIydjYzoZUm7K0HMnPZQA/bDpRJ6CeR8EPZ7/xIXQxaWTN5RzNEb/RY96KkyZ0xWDpAmiBb8UCQQCuZs3lpWFodos0lnVW/WoDVdng7qE8Xqwx68kXhueclgBYbJR9SYd14AqKbrDJvt+8dtw5qKOkIEVdNuxrqcxpAkEAmd+mPUeZFNe45edOF0H8wsRyxobdwT5RZZMmNwAjiidCsu5l2Kaxxnpql5i6d0Thq+cTf+d7UwsXvgsd6Sz91QJABGYZaWJre4wJ5NCqsv//TYg7z52VOYWVyEiPMOW5L8zkw1YxxJs3LHTzLxytntkOoZ1J3rZvMjOSLFC3U9vbiQJAHTbMYvxt3yKnYvksUINkOB+3sMHuUDdWZlgZ2POnWA+gP93gPogB0/547aR6f/WSBGDA0nWnE4uUU2I1Eu08rQ==
    """
 let SecretKeyData : Data =  Data(base64Encoded: EncrytedsecretKey)!
let privatekeyData : Data = Data(base64Encoded: privateKeyString)!
/*Creating Private Sec Key*/
    let privateKeyStripped  =  try! stripHeaderIfAny(keyData: privatekeyData)
        let attributes: [String: Any] = [
                         kSecAttrKeyType as String: kSecAttrKeyTypeRSA,
                         kSecAttrKeyClass as String: kSecAttrKeyClassPrivate
                     ]
             var error: Unmanaged<CFError>?
             let privateSecKey : SecKey = SecKeyCreateWithData(privateKeyStripped as CFData, attributes as CFDictionary, &error)!
/*Decrypt encrypted secret key using private key*/
  let algorithm: SecKeyAlgorithm = .rsaEncryptionOAEPSHA1
   guard SecKeyIsAlgorithmSupported(privateSecKey, .decrypt, algorithm) else {
   print("can not decrypt")
    return
   }
    var errorSec: Unmanaged<CFError>?
    let SecKeyDecryptedData = SecKeyCreateDecryptedData(privateSecKey,
                                                  algorithm,
                                                  SecretKeyData as CFData,
                                                  &errorSec) as Data?
        guard SecKeyDecryptedData != nil else {
          print("can not decrypt") /*Error in this line*/
            return
        }
        print(SecKeyDecryptedData! as NSData)

Now, when trying to decrypt the 128 bytes secretKeyData , I am getting an error , Please help,
All the process for decrypting is the same as discussed earlier.
Error : ""RSAdecrypt wrong input (err -27)" UserInfo={NSDescription=RSAdecrypt wrong input (err -27)"
Please help!!


I do not understand why you are trying to decrypt something.
You were under the way of creating a Request in Format:
Code Block
{
"encryptionFlag": "ENABLE",
"encryptedText": "Encrypted request",
"encryptedSecretKeyString": "Encrypted secret key"
}

There's no decrypted something. Or have you finished creating a Request?
Create and Encrypt Secret Key in iOS
 
 
Q