Eu tenho o seguinte código:
public extension SymmetricKey {
init?(base64Encoded base64EncodedKeyString: String) {
guard let keyData = Data(base64Encoded: base64EncodedKeyString) else { return nil }
self.init(data: keyData)
}
var base64: String {
self.withUnsafeBytes { body in
Data(body).base64EncodedString()
}
}
init?(pass: String) {
guard let passHash = passToHash(pass: pass) else { return nil }
self.init(base64Encoded: passHash)
}
}
fileprivate func passToHash(pass: String) -> String? {
guard let passData = pass.data(using: .utf8) else { return nil }
let hashed = SHA256.hash(data: passData)
return hashed.compactMap { String(format: "%02x", $0) }.joined()
}
o problema é que se eu tentar usar SymmetricKey
verei erro:
A operação não pôde ser concluída. (CryptoKit.CryptoKitError erro 1.)
Este erro significa tamanho de chave incorreto.
Se eu tentar comparar SymmetricKey
os gerados da maneira padrão e do meu init personalizado, verei a diferença:
5994471abb01112afcc18159f6cc74b4f511b99806da59b3caf5a9c173cacfc5 //from password
cfyk1v2dRIlVKHlpy8qBH71v4BXGSUHPUS3wLn1gzj0= //.bits256
O que estou fazendo de errado? Por que os hashes parecem diferentes?
Primeiro, esta é uma função de derivação de chave muito insegura. Nenhum esquema sério de criptografia deveria usar isso. Para criar uma chave a partir de uma senha, você deve usar uma PBKDF (função de derivação de chave baseada em senha), como PBKDF2.
Para fins de compatibilidade, pode ser necessário implementar esse esquema quebrado, então vou me aprofundar nisso aqui.
As chaves são fundamentalmente dados. Você criou uma String codificada em hexadecimal e depois a codificou em Base64. Isso torna os dados resultantes duas vezes maiores do que deveriam. O que você quis dizer foi isso:
Infelizmente, o CryptoKit da Apple não inclui nenhum PBKDF adequado. É uma estrutura muito limitada que fornece primitivas apenas para alguns casos de uso muito específicos. Algumas estruturas populares que fornecem as ferramentas necessárias são CryptoSwift e IDZSwiftCommonCrypto . A abordagem mais geral é usar o CommonCryptor da Apple, mas não é particularmente divertido no Swift.
Aqui está um exemplo, no entanto.
Chamar isso requer passar um sal. A escolha do sal depende um pouco do seu caso de uso. Uma situação comum é usar um salt aleatório (digamos, 16 bytes) para cada criptografia e, em seguida, passar o salt junto com os dados criptografados para que o receptor possa descriptografá-los. Aqui está uma maneira de criar esse tipo de dados aleatórios:
Você também pode obter funções que fazem essas coisas nas estruturas mencionadas. Muito pouco sobre como fazer criptografia em Swift é divertido.