Swift encrypt the symmetric key itself

143 Views Asked by At

So we hace this security where we want to encrypt the AES generated Symmetric key itself.

Basically this flow: Backend send us key -> we create a symmetric key -> we encrypt data with symmetric key -> we encrypt symmetric key with backend key -> we send everything back.

This is my attempt, but i expect something goes wrong here. But don't know what. Thanks in advance.

        guard let publicKeyData = Data(base64Encoded: publicKey) else {
            throw EncryptionError.invalidPublicKey
        }

        // Convert the recipient's public key data into a SecKey
        let keyAttributes: [CFString: Any] = [
            kSecAttrKeyType: kSecAttrKeyTypeRSA,
            kSecAttrKeyClass: kSecAttrKeyClassPublic,
            kSecAttrKeySizeInBits: 2048 // Adjust key size as needed
        ]

        guard let key = SecKeyCreateWithData(publicKeyData as CFData, keyAttributes as CFDictionary, nil) else {
            throw EncryptionError.invalidPublicKey
        }

        // Convert the SymmetricKey to Data
        var secretKeyData = Data(count: secretKey.bitCount / 8)
        _ = secretKeyData.withUnsafeMutableBytes { secretKeyDataBuffer in
                secretKey.withUnsafeBytes { secretKeyBuffer in
                    secretKeyDataBuffer.copyBytes(from: secretKeyBuffer)
                }
            }

        // Encrypt the symmetric key using the recipient's public key
        var error: Unmanaged<CFError>?
        guard let encryptedData = SecKeyCreateEncryptedData(
            key,
            .rsaEncryptionOAEPSHA1AESGCM,
            secretKeyData as CFData,
            &error
        ) else {
            if let error = error {
                throw error.takeRetainedValue()
            }
            throw EncryptionError.encryptionFailed
        }

        // Encode the encrypted symmetric key as base64 and return it
        return (encryptedData as Data).base64EncodedString()
    }

Edit: This is how we encrypt the message:

        let iv = AES.GCM.Nonce()

        do {
            let sealedBox = try AES.GCM.seal(jsonData, using: secretKey, nonce: iv)
            let encryptedMessage = sealedBox.combined!
            return encryptedMessage.base64EncodedString()
        } catch {
            throw error
        }
    }
    ```
1

There are 1 best solutions below

1
user20325868 On

It would be better to use CryptoKit. Is there a reason you're not?
Example:

import CryptoKit

guard let publicKeyData = Data(base64Encoded: publicKey) else {
        throw EncryptionError.invalidPublicKey
    }

    let key = Symmetric(size: .bits256)

// encrypt the keys data as extracted in your question.
    let encryptedContent = try ChaChaPoly.seal(publicKeyData, using: key).combined
    let sealedBox = try ChaChaPoly.SealedBox(combined: encryptedContent)
    
    let nonce = sealedBox.nonce
    let ciphertext = sealedBox.ciphertext
    let tag = sealedBox.tag
    
    assert(sealedBox.combined == nonce + ciphertext + tag)
    return sealedBox.combined