Как получить доступ к основному ключу SymmetricKey в CryptoKit?

Я возиться с новой платформой Apple CryptoKit на Xcode 11.0 beta 2. Я хочу создать SymmetricKey, а затем получить необработанные байты ключа. Я хотел бы использовать эти байты для создания того же ключа, а затем проверить, чтобы убедиться, что ключи равны. Из того, что я могу понять из документации, единственный способ получить доступ к необработанным байтам ключа - использовать метод withUnsafeBytes(_:). У меня есть детская площадка со следующим кодом:

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)")
}

Выход этого Are they equal? false так что, к сожалению, ключи не совпадают. Предполагая, что я могу получить эти ключи для совпадения, я также не уверен, как конвертировать rawKeyBytes в строку, чтобы просмотреть его в моей выходной Playground. В целом, я просто не очень знаком с UnsafeRawBufferPointer или ContiguousBytes.

3 ответа

Нет смысла сравнивать один ключ с другим, как ты сказал. Если вы хотите извлечь ключ, используйте следующие простые строки:

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

Или удалить base64EncodedString() только для Data отправить на сервер или положить в связку ключей.

С уважением

Мне пришлось сделать то же самое, и в итоге я сделал несколько расширений, чтобы упростить процесс:

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()
        }
    }
}

И протестировал это так:

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)")
}

Я не верю, что вы можете использовать load на Data именно так. Но в любом случае то, что вы хотите, выглядит так:

let key1 = SymmetricKey(size: .bits256)
let key2 = key1.withUnsafeBytes { SymmetricKey(data: Data($0)) }
print("Are they equal? \(key1 == key2)")

Как правило, опасно получить доступ к значению внутри его собственного withUnsafeBytes блок (например, доступ key1 внутри key1.withUnsafeBytes). Я не могу вспомнить, запрещено ли это в данном конкретном случае, но, как правило, этого следует избегать, поскольку это приводит к нарушениям монопольного доступа.

Мне кажется, что следующее работает

import CryptoKit
import Foundation

let key1 = SymmetricKey(size: .bits256)
key1.withUnsafeBytes { ptr in
    let rawKeyBytes = Data(bytes: ptr.baseAddress!, count: ptr.count)
    let key2 = SymmetricKey(data: rawKeyBytes)
    print("Are they equal? \(key1 == key2)")
}
Другие вопросы по тегам