Как получить доступ к основному ключу 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)")
}