Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I access the underlying key of a SymmetricKey in CryptoKit?

I am messing about with Apple's new CryptoKit framework on Xcode 11.0 beta 2. I want to create a SymmetricKey, then obtain the raw bytes of the key. I would like to use those bytes to create the same key, then check to make sure the keys are equal. From what I can understand in the documentation, the only way to get access to the raw bytes of a key is by using the withUnsafeBytes(_:) method. I have a Playground with the following code:

import Foundation
import CryptoKit

let key1 = SymmetricKey(size: .bits256)
key1.withUnsafeBytes { body in
  let rawKeyBytes = body.load(as: Data.self)
  let key2 = SymmetricKey(data: rawKeyBytes)
  print("Are they equal? \(key1 == key2)")
}

The output of this is Are they equal? false, so unfortunately the keys do not match. Assuming I could get these keys to match, I'm also not sure how to convert rawKeyBytes into a string in order to view it in my Playground output. Overall I'm just not very familiar with UnsafeRawBufferPointer or ContiguousBytes.

like image 878
Eugene Avatar asked Jun 30 '19 21:06

Eugene


2 Answers

There's no sense to compare one key to another like you said. If you want to extract the key, use this simple lines:

let keyb64 = key.withUnsafeBytes {
    return Data(Array($0)).base64EncodedString()
}

Or remove base64EncodedString() only for Data to send to a server or put in the keychain.

Best regards

like image 113
Julio César Fernández Muñoz Avatar answered Nov 18 '22 04:11

Julio César Fernández Muñoz


I had to do this same thing and ended up making some extensions to streamline the process:

import CryptoKit
import Foundation

extension SymmetricKey {

    // MARK: Custom Initializers

    /// Creates a `SymmetricKey` from a Base64-encoded `String`.
    ///
    /// - Parameter base64EncodedString: The Base64-encoded string from which to generate the `SymmetricKey`.
    init?(base64EncodedString: String) {
        guard let data = Data(base64Encoded: base64EncodedString) else {
            return nil
        }

        self.init(data: data)
    }

    // MARK: - Instance Methods

    /// Serializes a `SymmetricKey` to a Base64-encoded `String`.
    func serialize() -> String {
        return self.withUnsafeBytes { body in
            Data(body).base64EncodedString()
        }
    }
}

And tested this like so:

import CryptoKit

func symmetricKeyTest() {
    let symmetricKey = SymmetricKey(size: .bits256)
    let serializedSymmetricKey = symmetricKey.serialize()

    guard let deserializedSymmetricKey = SymmetricKey(base64EncodedString: serializedSymmetricKey) else {
        print("deserializedSymmetricKey was nil.")
        return
    }

    print("Keys match: \(symmetricKey == deserializedSymmetricKey)")
}
like image 8
rlziii Avatar answered Nov 18 '22 05:11

rlziii