it-swarm.com.de

Swift - Verschlüsseln und entschlüsseln Sie eine Zeichenfolge mit einem Benutzerkennwort

Ich versuche, einen String mit einem Kennwort in Swift zu verschlüsseln, bin mir aber nicht sicher, wie er das tun soll. Ich brauche etwas, das wie folgt funktioniert

let password = "password"
let message = "messageToEncrypt"
let encryptedMessage = encrypt(message, password)
...

let decryptedMessage = decrypt(encryptedMessage, password)

Jeder Rat wäre sehr dankbar.

Vielen Dank 

UPDATE<- Dieser Abschnitt wurde jetzt entfernt

UPDATE 2

Ok ich habe jetzt folgendes:

 func testEnc() throws {

    let ivKey = "tEi1H3E1aj26XNro"
    let message = "Test Message"
    let password = "pass123"

    let aesKey = password.padding(toLength: 32, withPad: "0", startingAt: 0)

    do {
        let messageArray = Array(message.utf8)
        let encrypted = try AES(key: aesKey, iv: ivKey, blockMode: .CBC, padding: .pkcs7).encrypt(messageArray)
        let encryptedString = String.init(bytes: encrypted, encoding: .utf8)
        let decrypted = try AES(key: aesKey, iv: ivKey, blockMode: .CBC, padding: .pkcs7).decrypt(encrypted)
        let decryptedString = String.init(bytes: decrypted, encoding: .utf8)
        assert(message == decryptedString)
    } catch {
        print(error)
    }
}

In dem obigen Code wird die Nachricht korrekt verschlüsselt und erneut entschlüsselt.

decryptedString gibt den gleichen Wert zurück wie message, was perfekt ist. Ich muss jedoch den verschlüsselten Wert speichern. Im obigen Code gibt encryptedString immer nil zurück. Klassifiziert ein AES-verschlüsselter Array<UInt8> nicht als Byte-String?

4
Matthew Cawley

Bitte beachten Sie den aktualisierten Abschnitt unter dem durchgestrichenen Abschnitt. Ich habe den durchgestrichenen Abschnitt verlassen, um den Kommentaren einen Kontext zu geben und zu zeigen, wie man aus Sicherheitsgründen nicht vorgeht

Ich habe es mit CryptoSwift ausgearbeitet

func testEnc() throws {

    //has to be 16 characters
    //ivKey is only hardcoded for use of this example
    let ivKey = "tEi1H3E1aj26XNro"
    let message = "Test Message"
    let password = "pass123"

    //key has to be 32 characters so we pad the password
    let aesKey = password.padding(toLength: 32, withPad: "0", startingAt: 0)

    let encrypted = try message.encryptToBase64(cipher: AES(key: aesKey, iv: ivKey, blockMode: .CBC, padding: .pkcs7))
    //returns: beQ7u8hBGdFYqNP5z4gBGg==

    let decrypted = try encrypted?.decryptBase64ToString(cipher: AES(key: aesKey, iv: ivKey, blockMode: .CBC, padding: .pkcs7))
    //returns: Test Message
    assert(message == decrypted)

}

[~ # ~] Update [~ # ~]

Die obige Methode funktioniert zwar, ist aber unsicher. Bitte lesen Sie die Kommentare zu dieser Antwort für weitere Informationen

Basierend auf den Kommentaren und Rückmeldungen habe ich ein neues Beispiel geschrieben, das das Framework RNCryptor verwendet

Um Nachrichten zu ver- und entschlüsseln, verwende ich die folgenden 2 Methoden.

    func encryptMessage(message: String, encryptionKey: String) throws -> String {
        let messageData = message.data(using: .utf8)!
        let cipherData = RNCryptor.encrypt(data: messageData, withPassword: encryptionKey)
        return cipherData.base64EncodedString()
    }

    func decryptMessage(encryptedMessage: String, encryptionKey: String) throws -> String {

        let encryptedData = Data.init(base64Encoded: encryptedMessage)!
        let decryptedData = try RNCryptor.decrypt(data: encryptedData, withPassword: encryptionKey)
        let decryptedString = String(data: decryptedData, encoding: .utf8)!

        return decryptedString
    }

In meinem Anwendungsfall musste ich in der Lage sein, die Ver- und Entschlüsselung anhand eines Kennworts durchzuführen, das geändert werden konnte, ohne alles neu verschlüsseln zu müssen.

Was ich getan habe, ist eine zufällige 32-stellige Zeichenfolge generiert und diese mit dem Passwort verschlüsselt. Wenn der Benutzer sein Kennwort ändert, entschlüsselt er den Schlüssel einfach mit dem alten Kennwort und verschlüsselt ihn erneut mit dem neuen Kennwort. Dadurch wird sichergestellt, dass alle vorhandenen Inhalte entschlüsselt werden können, während sie weiterhin durch das Kennwort des Benutzers geschützt sind.

Verwenden Sie die folgende Methode, um den Verschlüsselungsschlüssel zu generieren:

func generateEncryptionKey(withPassword password:String) throws -> String {
    let randomData = RNCryptor.randomData(ofLength: 32)
    let cipherData = RNCryptor.encrypt(data: randomData, withPassword: password)
    return cipherData.base64EncodedString()
}

Hinweis: Sie würden diesen Verschlüsselungsschlüssel für den Benutzer nur einmal generieren, da er dann an einem Ort gespeichert wird, an dem der Benutzer ihn mit seinem Kennwort zurückgeben kann.

10
Matthew Cawley

Eine der beliebtesten Bibliotheken ist CryptoSwift (mehr als 4000 Sterne!). Es bietet eine Vielzahl von kryptografischen Funktionen, die Sie interessieren könnten. 

Für Ihre Frage gehe ich davon aus, dass Sie eine AES-basierte Verschlüsselung durchführen möchten und die Nachricht klein ist (weiter unten gibt es ein Beispiel für größere Dateien usw.). Verwenden Sie die oben erwähnte Bibliothek, den Code (von der Seite der Bibliothek selbst entnommen - bitte nach unten scrollen):

do {
    let aes = try AES(key: "passwordpassword", iv: "drowssapdrowssap") 
    let ciphertext = try aes.encrypt(Array("Nullam quis risus eget urna mollis ornare vel eu leo.".utf8))
} catch { }

Eine der Fragen ist, wie man IV (Initialisierungsvektor) erhält. In diesem Beispiel ist die IV einfach das Gegenteil des Passworts, was in realen Anwendungen möglicherweise keine gute Idee ist. Das Prinzip ist, dass die IV nicht geheim sein muss. Es muss nur zufällig und wenn möglich einzigartig sein. So können Sie die IV mit der Datei in einer Datenbank mit dem Chiffretext speichern.

1
mgeek