Swift-使用用户密码加密和解密字符串 [英] Swift - Encrypt and decrypt a string using a users password

查看:138
本文介绍了Swift-使用用户密码加密和解密字符串的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在Swift中使用密码对字符串进行加密,但不确定如何做到这一点.我需要像这样的东西

I'm trying to encrypt a String using a password in Swift but not sure how to do it. I need something that works like this

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

let decryptedMessage = decrypt(encryptedMessage, password)

任何建议将不胜感激.

谢谢

更新

基于以下想法,我有以下方法

Based on the idea below i have the following method

func testEnc() throws {
    
    let ivKey = "tEi1H3E1aj26XNro"
    let message = "Test Message"
    let password = "pass123"
    
    let aesKey = password.padding(toLength: 32, withPad: "0", startingAt: 0)
    
    let aes = try AES(key: aesKey, iv: ivKey)
    let cipherBytes: Array<UInt8> = try aes.encrypt(Array(message.utf8))
    
    let cipherData = NSData(bytes: cipherBytes, length: Int(cipherBytes.count))
    let cipherString = cipherData.base64EncodedString(options: .lineLength64Characters)
    //cipherString => beQ7u8hBGdFYqNP5z4gBGg==
    let decryptedCipherBytes = try aes.decrypt(Array(cipherString.utf8))
    let decryptedCipherData = NSData(bytes: decryptedCipherBytes, length: Int(cipherBytes.count))
    let decryptedCipherString = decryptedCipherData.base64EncodedString(options: .lineLength64Characters)
    
    assert(message == decryptedCipherString)
}

在线

    let decryptedCipherBytes = try aes.decrypt(Array(cipherString.utf8))

我遇到以下错误:

[CryptoSwift.AES.Error: dataPaddingRequired]
Conform 'CryptoSwift.AES.Error' to Debugging.Debuggable to provide more debug information.

您知道为什么它无法解密刚刚加密的数据吗?

Do you have any idea why it would not be able to decrypt the data that it has just encrypted?

谢谢

推荐答案

请参阅下面的更新部分.我已经删除了删节部分,以便为评论提供背景信息,并说明出于安全目的如何不这样做

Please see updated section below striked out section. I have left the striked out section to give context to the comments and to show how not to do for security purposes

我已经使用CryptoSwift解决了

I have worked it out using CryptoSwift

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)

}

更新

上述方法虽然可行,但并不安全; 请阅读此答案的注释以获取更多信息

The above methodology, while it will work, is insecure; please read comments on this answer for more information

基于评论和反馈,我编写了一个使用框架

Based on the comments and feedback, I have written a new example that uses the framework RNCryptor

要加密和解密消息,我使用以下两种方法.

To encryp and decrypt messages I use the following 2 methods.

    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 my use case I needed to be able to handle encryption and decryption based off a password that could be changed without having to re-encrypt everything.

我所做的是生成一个随机的32个字符串,并使用密码对其进行加密.如果用户更改了密码,则只需使用旧密码解密密钥,然后使用新密码重新加密.这样可以确保在解密所有现有内容的同时,仍然可以通过用户密码对其进行保护.

What I did is generated a random 32 character string and encrypted that with the password. If the user changes their password, they simply decrypt the key with the old password and re-encrypt it with the new password. This ensure that all existing content can be decrypted while still being secured by the user's password.

要生成加密密钥,请使用以下方法:

To generate the encryption key is use the following method:

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

注意:您只会为用户生成一次此加密密钥,因为它将被存储在用户可以使用其密码返回的某个地方.

Note: You would only generate this encryption key for the user once as it would then be stored somewhere where the user can return it using their password.

这篇关于Swift-使用用户密码加密和解密字符串的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆