web-dev-qa-db-ja.com

swiftでのAES暗号化

SwiftでAES暗号化を実装しようとしています。 AndroidおよびC#は正常に動作しています。Swiftで実装する必要があります。 現在のコード for AndroidとC#の後にこれが続きます。

使ってみた

  1. CryptoSwift
  2. クロスプラットフォームAES暗号化

しかし、どれも機能しません。サーバーで暗号化された文字列を送信しても、解読されていません。

どんな助けでも大歓迎です

22
Ankita Shah

Iv、PKCS5Padding(実際にはPKCS#7)パディング、および16バイト(128ビット)キーを使用したCBCモードのAESと思われる同じパラメーターを使用してください。

PKCS#5パディングと PKCS#7 パディングは基本的に同じです。歴史的な理由により、AESで使用するためにPKCS#5パディングが指定されている場合がありますが、実際のパディングはPKCS#7です。

キー、iv、暗号化されたデータのエンコーディングがすべて一致していることを確認してください。それらが同一であることを確認するために、両方のプラットフォームで16進ダンプします。暗号化機能の使用は難しくありません。すべての入力パラメーターが正しい場合、出力も正しくなります。

これをより安全にするには、ivをランダムバイトにし、復号化中に使用するために暗号化データの前に追加する必要があります。

Cross platform AES暗号化は256ビットキーを使用するため、そのままでは機能しません。

例:

スイフト2

// operation: kCCEncrypt or kCCDecrypt
func testCrypt(data data:[UInt8], keyData:[UInt8], ivData:[UInt8], operation:Int) -> [UInt8]? {
    let cryptLength  = size_t(data.count+kCCBlockSizeAES128)
    var cryptData    = [UInt8](count:cryptLength, repeatedValue:0)

    let keyLength             = size_t(kCCKeySizeAES128)
    let algoritm: CCAlgorithm = UInt32(kCCAlgorithmAES128)
    let options:  CCOptions   = UInt32(kCCOptionPKCS7Padding)

    var numBytesEncrypted :size_t = 0

    let cryptStatus = CCCrypt(CCOperation(operation),
                              algoritm,
                              options,
                              keyData, keyLength,
                              ivData,
                              data, data.count,
                              &cryptData, cryptLength,
                              &numBytesEncrypted)

    if UInt32(cryptStatus) == UInt32(kCCSuccess) {
        cryptData.removeRange(numBytesEncrypted..<cryptData.count)

    } else {
        print("Error: \(cryptStatus)")
    }

    return cryptData;
}

let message       = "Don´t try to read this text. Top Secret Stuff"
let messageData   = Array(message.utf8)
let keyData       = Array("12345678901234567890123456789012".utf8)
let ivData        = Array("abcdefghijklmnop".utf8)
let encryptedData = testCrypt(data:messageData,   keyData:keyData, ivData:ivData, operation:kCCEncrypt)!
let decryptedData = testCrypt(data:encryptedData, keyData:keyData, ivData:ivData, operation:kCCDecrypt)!
var decrypted     = String(bytes:decryptedData, encoding:NSUTF8StringEncoding)!

print("message:       \(message)");
print("messageData:   \(NSData(bytes:messageData,   length:messageData.count))");
print("keyData:       \(NSData(bytes:keyData,       length:keyData.count))");
print("ivData:        \(NSData(bytes:ivData,        length:ivData.count))");
print("encryptedData: \(NSData(bytes:encryptedData, length:encryptedData.count))");
print("decryptedData: \(NSData(bytes:decryptedData, length:decryptedData.count))");
print("decrypted:     \(String(bytes:decryptedData,encoding:NSUTF8StringEncoding)!)");

出力:

メッセージ:このテキストを読もうとしないでください。トップシークレットスタッフ
 messageData:446f6ec2 b4742074 72792074 6f207265 61642074 68697320 74657874 2e20546f 70205365 63726574 20537475 6666 
 keyData:31323334 35363738 39303132 33343536 373836 669.iv.6d 6696 ____。テキスト。トップシークレットスタッフ

[UInt8]タイプのSwift 3

func testCrypt(data:[UInt8], keyData:[UInt8], ivData:[UInt8], operation:Int) -> [UInt8]? {
    let cryptLength  = size_t(data.count+kCCBlockSizeAES128)
    var cryptData    = [UInt8](repeating:0, count:cryptLength)

    let keyLength             = size_t(kCCKeySizeAES128)
    let algoritm: CCAlgorithm = UInt32(kCCAlgorithmAES128)
    let options:  CCOptions   = UInt32(kCCOptionPKCS7Padding)

    var numBytesEncrypted :size_t = 0

    let cryptStatus = CCCrypt(CCOperation(operation),
                              algoritm,
                              options,
                              keyData, keyLength,
                              ivData,
                              data, data.count,
                              &cryptData, cryptLength,
                              &numBytesEncrypted)

    if UInt32(cryptStatus) == UInt32(kCCSuccess) {
        cryptData.removeSubrange(numBytesEncrypted..<cryptData.count)

    } else {
        print("Error: \(cryptStatus)")
    }

    return cryptData;
}

DataタイプのSwift 3および4

func testCrypt(data:Data, keyData:Data, ivData:Data, operation:Int) -> Data {
    let cryptLength  = size_t(data.count + kCCBlockSizeAES128)
    var cryptData = Data(count:cryptLength)

    let keyLength             = size_t(kCCKeySizeAES128)
    let options   = CCOptions(kCCOptionPKCS7Padding)


    var numBytesEncrypted :size_t = 0

    let cryptStatus = cryptData.withUnsafeMutableBytes {cryptBytes in
        data.withUnsafeBytes {dataBytes in
            ivData.withUnsafeBytes {ivBytes in
                keyData.withUnsafeBytes {keyBytes in
                    CCCrypt(CCOperation(operation),
                              CCAlgorithm(kCCAlgorithmAES),
                              options,
                              keyBytes, keyLength,
                              ivBytes,
                              dataBytes, data.count,
                              cryptBytes, cryptLength,
                              &numBytesEncrypted)
                }
            }
        }
    }

    if UInt32(cryptStatus) == UInt32(kCCSuccess) {
        cryptData.removeSubrange(numBytesEncrypted..<cryptData.count)

    } else {
        print("Error: \(cryptStatus)")
    }

    return cryptData;
}

let message     = "Don´t try to read this text. Top Secret Stuff"
let messageData = message.data(using:String.Encoding.utf8)!
let keyData     = "12345678901234567890123456789012".data(using:String.Encoding.utf8)!
let ivData      = "abcdefghijklmnop".data(using:String.Encoding.utf8)!

let encryptedData = testCrypt(data:messageData,   keyData:keyData, ivData:ivData, operation:kCCEncrypt)
let decryptedData = testCrypt(data:encryptedData, keyData:keyData, ivData:ivData, operation:kCCDecrypt)
var decrypted     = String(bytes:decryptedData, encoding:String.Encoding.utf8)!

廃止されたドキュメントセクションの例:

ランダムなIVを使用したCBCモードでのAES暗号化(Swift 3 +)

Ivは暗号化されたデータの前に付けられます

aesCBC128Encryptは、ランダムなIVを作成し、暗号化されたコードの前に付けます。
aesCBC128Decryptは、復号化中に接頭辞付きIVを使用します。

入力はデータであり、キーはデータオブジェクトです。 Base64などのエンコードされたフォームが必要な場合、呼び出し元メソッドとの間で変換します。

キーの長さは、正確に128ビット(16バイト)、192ビット(24バイト)、または256ビット(32バイト)でなければなりません。別のキーサイズを使用すると、エラーがスローされます。

PKCS#7 padding はデフォルトで設定されています。

この例では、共通暗号が必要です
プロジェクトへのブリッジングヘッダーが必要です。
#import <CommonCrypto/CommonCrypto.h>
プロジェクトにSecurity.frameworkを追加します。

これは例であり、量産コードではありません。

enum AESError: Error {
    case KeyError((String, Int))
    case IVError((String, Int))
    case CryptorError((String, Int))
}

// The iv is prefixed to the encrypted data
func aesCBCEncrypt(data:Data, keyData:Data) throws -> Data {
    let keyLength = keyData.count
    let validKeyLengths = [kCCKeySizeAES128, kCCKeySizeAES192, kCCKeySizeAES256]
    if (validKeyLengths.contains(keyLength) == false) {
        throw AESError.KeyError(("Invalid key length", keyLength))
    }

    let ivSize = kCCBlockSizeAES128;
    let cryptLength = size_t(ivSize + data.count + kCCBlockSizeAES128)
    var cryptData = Data(count:cryptLength)

    let status = cryptData.withUnsafeMutableBytes {ivBytes in
        SecRandomCopyBytes(kSecRandomDefault, kCCBlockSizeAES128, ivBytes)
    }
    if (status != 0) {
        throw AESError.IVError(("IV generation failed", Int(status)))
    }

    var numBytesEncrypted :size_t = 0
    let options   = CCOptions(kCCOptionPKCS7Padding)

    let cryptStatus = cryptData.withUnsafeMutableBytes {cryptBytes in
        data.withUnsafeBytes {dataBytes in
            keyData.withUnsafeBytes {keyBytes in
                CCCrypt(CCOperation(kCCEncrypt),
                        CCAlgorithm(kCCAlgorithmAES),
                        options,
                        keyBytes, keyLength,
                        cryptBytes,
                        dataBytes, data.count,
                        cryptBytes+kCCBlockSizeAES128, cryptLength,
                        &numBytesEncrypted)
            }
        }
    }

    if UInt32(cryptStatus) == UInt32(kCCSuccess) {
        cryptData.count = numBytesEncrypted + ivSize
    }
    else {
        throw AESError.CryptorError(("Encryption failed", Int(cryptStatus)))
    }

    return cryptData;
}

// The iv is prefixed to the encrypted data
func aesCBCDecrypt(data:Data, keyData:Data) throws -> Data? {
    let keyLength = keyData.count
    let validKeyLengths = [kCCKeySizeAES128, kCCKeySizeAES192, kCCKeySizeAES256]
    if (validKeyLengths.contains(keyLength) == false) {
        throw AESError.KeyError(("Invalid key length", keyLength))
    }

    let ivSize = kCCBlockSizeAES128;
    let clearLength = size_t(data.count - ivSize)
    var clearData = Data(count:clearLength)

    var numBytesDecrypted :size_t = 0
    let options   = CCOptions(kCCOptionPKCS7Padding)

    let cryptStatus = clearData.withUnsafeMutableBytes {cryptBytes in
        data.withUnsafeBytes {dataBytes in
            keyData.withUnsafeBytes {keyBytes in
                CCCrypt(CCOperation(kCCDecrypt),
                        CCAlgorithm(kCCAlgorithmAES128),
                        options,
                        keyBytes, keyLength,
                        dataBytes,
                        dataBytes+kCCBlockSizeAES128, clearLength,
                        cryptBytes, clearLength,
                        &numBytesDecrypted)
            }
        }
    }

    if UInt32(cryptStatus) == UInt32(kCCSuccess) {
        clearData.count = numBytesDecrypted
    }
    else {
        throw AESError.CryptorError(("Decryption failed", Int(cryptStatus)))
    }

    return clearData;
}

使用例:

let clearData = "clearData0123456".data(using:String.Encoding.utf8)!
let keyData   = "keyData890123456".data(using:String.Encoding.utf8)!
print("clearData:   \(clearData as NSData)")
print("keyData:     \(keyData as NSData)")

var cryptData :Data?
do {
    cryptData = try aesCBCEncrypt(data:clearData, keyData:keyData)
    print("cryptData:   \(cryptData! as NSData)")
}
catch (let status) {
    print("Error aesCBCEncrypt: \(status)")
}

let decryptData :Data?
do {
    let decryptData = try aesCBCDecrypt(data:cryptData!, keyData:keyData)
    print("decryptData: \(decryptData! as NSData)")
}
catch (let status) {
    print("Error aesCBCDecrypt: \(status)")
}

出力例:

clearData:   <636c6561 72446174 61303132 33343536>
keyData:     <6b657944 61746138 39303132 33343536>
cryptData:   <92c57393 f454d959 5a4d158f 6e1cd3e7 77986ee9 b2970f49 2bafcf1a 8ee9d51a bde49c31 d7780256 71837a61 60fa4be0>
decryptData: <636c6561 72446174 61303132 33343536>

ノート:
CBCモードのサンプルコードの典型的な問題の1つは、ランダムIVの作成と共有をユーザーに任せることです。この例には、IVの生成が含まれ、暗号化されたデータの接頭辞が付けられ、復号化中に接頭辞のIVが使用されます。これにより、カジュアルユーザーは CBCモード に必要な詳細から解放されます。

セキュリティのために、暗号化されたデータにも認証が必要です。このサンプルコードでは、小さくして他のプラットフォームとの相互運用性を高めるために認証を提供していません。

また、パスワードからのキーのキー派生もありません。 PBKDF2 を使用することをお勧めします。テキストパスワードはキー情報として使用されます。

プロダクション対応の堅牢なマルチプラットフォーム暗号化コードについては、 RNCryptor を参照してください。

35
zaph

Swift 4.2

@ingcontiのコードをリファクタリングしました。

import Foundation
import CommonCrypto

struct AES {

    // MARK: - Value
    // MARK: Private
    private let key: Data
    private let iv: Data


    // MARK: - Initialzier
    init?(key: String, iv: String) {
        guard key.count == kCCKeySizeAES128 || key.count == kCCKeySizeAES256, let keyData = key.data(using: .utf8) else {
            debugPrint("Error: Failed to set a key.")
            return nil
        }

        guard iv.count == kCCBlockSizeAES128, let ivData = iv.data(using: .utf8) else {
            debugPrint("Error: Failed to set an initial vector.")
            return nil
        }


        self.key = keyData
        self.iv  = ivData
    }


    // MARK: - Function
    // MARK: Public
    func encrypt(string: String) -> Data? {
        return crypt(data: string.data(using: .utf8), option: CCOperation(kCCEncrypt))
    }

    func decrypt(data: Data?) -> String? {
        guard let decryptedData = crypt(data: data, option: CCOperation(kCCDecrypt)) else { return nil }
        return String(bytes: decryptedData, encoding: .utf8)
    }

    func crypt(data: Data?, option: CCOperation) -> Data? {
        guard let data = data else { return nil }

        let cryptLength = [UInt8](repeating: 0, count: data.count + kCCBlockSizeAES128).count
        var cryptData   = Data(count: cryptLength)

        let keyLength = [UInt8](repeating: 0, count: kCCBlockSizeAES128).count
        let options   = CCOptions(kCCOptionPKCS7Padding)

        var bytesLength = Int(0)

        let status = cryptData.withUnsafeMutableBytes { cryptBytes in
            data.withUnsafeBytes { dataBytes in
                iv.withUnsafeBytes { ivBytes in
                    key.withUnsafeBytes { keyBytes in
                    CCCrypt(option, CCAlgorithm(kCCAlgorithmAES), options, keyBytes, keyLength, ivBytes, dataBytes, data.count, cryptBytes, cryptLength, &bytesLength)
                    }
                }
            }
        }

        guard UInt32(status) == UInt32(kCCSuccess) else {
            debugPrint("Error: Failed to crypt data. Status \(status)")
            return nil
        }

        cryptData.removeSubrange(bytesLength..<cryptData.count)
        return cryptData
    }
}

このように使用します

let password = "UserPassword1!"
let key128   = "1234567890123456"                   // 16 bytes for AES128
let key256   = "12345678901234561234567890123456"   // 32 bytes for AES256
let iv       = "abcdefghijklmnop"                   // 16 bytes for AES128

let aes128 = AES(key: key128, iv: iv)
let aes256 = AES(key: key256, iv: iv)

let encryptedPassword128 = aes128?.encrypt(string: password)
aes128?.decrypt(data: encryptedPassword128)

let encryptedPassword256 = aes256?.encrypt(string: password)
aes256?.decrypt(data: encryptedPassword256)

結果

enter image description here

7
Den

私の2セント:

データ用のSwift 4/xcode 9拡張:

extension Data{

    func aesEncrypt( keyData: Data, ivData: Data, operation: Int) -> Data {
        let dataLength = self.count
        let cryptLength  = size_t(dataLength + kCCBlockSizeAES128)
        var cryptData = Data(count:cryptLength)

        let keyLength = size_t(kCCKeySizeAES128)
        let options = CCOptions(kCCOptionPKCS7Padding)


        var numBytesEncrypted :size_t = 0

        let cryptStatus = cryptData.withUnsafeMutableBytes {cryptBytes in
            self.withUnsafeBytes {dataBytes in
                ivData.withUnsafeBytes {ivBytes in
                    keyData.withUnsafeBytes {keyBytes in
                        CCCrypt(CCOperation(operation),
                                CCAlgorithm(kCCAlgorithmAES),
                                options,
                                keyBytes, keyLength,
                                ivBytes,
                                dataBytes, dataLength,
                                cryptBytes, cryptLength,
                                &numBytesEncrypted)
                    }
                }
            }
        }

        if UInt32(cryptStatus) == UInt32(kCCSuccess) {
            cryptData.removeSubrange(numBytesEncrypted..<cryptData.count)

        } else {
            print("Error: \(cryptStatus)")
        }

        return cryptData;
    }

}




    func testAES() -> Bool {

        let message     = "secret message"
        let key         = "key890123456"
        let ivString     = "abcdefghijklmnop"   // 16 bytes for AES128

        let messageData = message.data(using:String.Encoding.utf8)!
        let keyData     = key.data(using: .utf8)!
        let ivData      = ivString.data(using: .utf8)!

        let encryptedData = messageData.aesEncrypt( keyData:keyData, ivData:ivData, operation:kCCEncrypt)
        let decryptedData = encryptedData.aesEncrypt( keyData:keyData, ivData:ivData, operation:kCCDecrypt)
        let decrypted     = String(bytes:decryptedData, encoding:String.Encoding.utf8)!

        return message == decrypted

    }
5
ingconti

@zaphの素晴らしい答えに基づいて、私はこれを作成します:Playground

スイフト5

import Foundation
import CommonCrypto

protocol Cryptable {
    func encrypt(_ string: String) throws -> Data
    func decrypt(_ data: Data) throws -> String
}

struct AES {
    private let key: Data
    private let ivSize: Int         = kCCBlockSizeAES128
    private let options: CCOptions  = CCOptions(kCCOptionPKCS7Padding)

    init(keyString: String) throws {
        guard keyString.count == kCCKeySizeAES256 else {
            throw Error.invalidKeySize
        }
        self.key = Data(keyString.utf8)
    }
}

extension AES {
    enum Error: Swift.Error {
        case invalidKeySize
        case generateRandomIVFailed
        case encryptionFailed
        case decryptionFailed
        case dataToStringFailed
    }
}

private extension AES {

    func generateRandomIV(for data: inout Data) throws {

        try data.withUnsafeMutableBytes { dataBytes in

            guard let dataBytesBaseAddress = dataBytes.baseAddress else {
                throw Error.generateRandomIVFailed
            }

            let status: Int32 = SecRandomCopyBytes(
                kSecRandomDefault,
                kCCBlockSizeAES128,
                dataBytesBaseAddress
            )

            guard status == 0 else {
                throw Error.generateRandomIVFailed
            }
        }
    }
}

extension AES: Cryptable {

    func encrypt(_ string: String) throws -> Data {
        let dataToEncrypt = Data(string.utf8)

        let bufferSize: Int = ivSize + dataToEncrypt.count + kCCBlockSizeAES128
        var buffer = Data(count: bufferSize)
        try generateRandomIV(for: &buffer)

        var numberBytesEncrypted: Int = 0

        do {
            try key.withUnsafeBytes { keyBytes in
                try dataToEncrypt.withUnsafeBytes { dataToEncryptBytes in
                    try buffer.withUnsafeMutableBytes { bufferBytes in

                        guard let keyBytesBaseAddress = keyBytes.baseAddress,
                            let dataToEncryptBytesBaseAddress = dataToEncryptBytes.baseAddress,
                            let bufferBytesBaseAddress = bufferBytes.baseAddress else {
                                throw Error.encryptionFailed
                        }

                        let cryptStatus: CCCryptorStatus = CCCrypt( // Stateless, one-shot encrypt operation
                            CCOperation(kCCEncrypt),                // op: CCOperation
                            CCAlgorithm(kCCAlgorithmAES),           // alg: CCAlgorithm
                            options,                                // options: CCOptions
                            keyBytesBaseAddress,                    // key: the "password"
                            key.count,                              // keyLength: the "password" size
                            bufferBytesBaseAddress,                 // iv: Initialization Vector
                            dataToEncryptBytesBaseAddress,          // dataIn: Data to encrypt bytes
                            dataToEncryptBytes.count,               // dataInLength: Data to encrypt size
                            bufferBytesBaseAddress + ivSize,        // dataOut: encrypted Data buffer
                            bufferSize,                             // dataOutAvailable: encrypted Data buffer size
                            &numberBytesEncrypted                   // dataOutMoved: the number of bytes written
                        )

                        guard cryptStatus == CCCryptorStatus(kCCSuccess) else {
                            throw Error.encryptionFailed
                        }
                    }
                }
            }

        } catch {
            throw Error.encryptionFailed
        }

        let encryptedData: Data = buffer[..<(numberBytesEncrypted + ivSize)]
        return encryptedData
    }

    func decrypt(_ data: Data) throws -> String {

        let bufferSize: Int = data.count - ivSize
        var buffer = Data(count: bufferSize)

        var numberBytesDecrypted: Int = 0

        do {
            try key.withUnsafeBytes { keyBytes in
                try data.withUnsafeBytes { dataToDecryptBytes in
                    try buffer.withUnsafeMutableBytes { bufferBytes in

                        guard let keyBytesBaseAddress = keyBytes.baseAddress,
                            let dataToDecryptBytesBaseAddress = dataToDecryptBytes.baseAddress,
                            let bufferBytesBaseAddress = bufferBytes.baseAddress else {
                                throw Error.encryptionFailed
                        }

                        let cryptStatus: CCCryptorStatus = CCCrypt( // Stateless, one-shot encrypt operation
                            CCOperation(kCCDecrypt),                // op: CCOperation
                            CCAlgorithm(kCCAlgorithmAES128),        // alg: CCAlgorithm
                            options,                                // options: CCOptions
                            keyBytesBaseAddress,                    // key: the "password"
                            key.count,                              // keyLength: the "password" size
                            dataToDecryptBytesBaseAddress,          // iv: Initialization Vector
                            dataToDecryptBytesBaseAddress + ivSize, // dataIn: Data to decrypt bytes
                            bufferSize,                             // dataInLength: Data to decrypt size
                            bufferBytesBaseAddress,                 // dataOut: decrypted Data buffer
                            bufferSize,                             // dataOutAvailable: decrypted Data buffer size
                            &numberBytesDecrypted                   // dataOutMoved: the number of bytes written
                        )

                        guard cryptStatus == CCCryptorStatus(kCCSuccess) else {
                            throw Error.decryptionFailed
                        }
                    }
                }
            }
        } catch {
            throw Error.encryptionFailed
        }

        let decryptedData: Data = buffer[..<numberBytesDecrypted]

        guard let decryptedString = String(data: decryptedData, encoding: .utf8) else {
            throw Error.dataToStringFailed
        }

        return decryptedString
    }
}

do {
    let aes = try AES(keyString: "FiugQTgPNwCWUY,VhfmM4cKXTLVFvHFe")

    let stringToEncrypt: String = "please encrypt meeee"
    print("String to encrypt:\t\t\t\(stringToEncrypt)")

    let encryptedData: Data = try aes.encrypt(stringToEncrypt)
    print("String encrypted (base64):\t\(encryptedData.base64EncodedString())")

    let decryptedData: String = try aes.decrypt(encryptedData)
    print("String decrypted:\t\t\t\(decryptedData)")

} catch {
    print("Something went wrong: \(error)")
}

出力:

output

また、それに基づいてSwift Packageを作成しました:

https://github.com/backslash-f/aescryptable ✌????

4
backslash-f

CryptoSwiftを使用しました。

まず、ポッドファイルにcryptoSwiftをインストールします。次に、View ControllerにCryptoSwiftをインポートします。

私が使用したコードは次のとおりです。

_let value = "xyzzy".  // This is the value that we want to encrypt
let key = "abc".      // This is the key 

let EncryptedValue = try! value.aesEncrypt(key: key)
let DecryptedValue = try! EncryptedValue.aesDecrypt(key: key)
_

次に、ストリング拡張を使用します。

_extension String {

    func aesEncrypt(key: String) throws -> String {

        var result = ""

        do {

            let key: [UInt8] = Array(key.utf8) as [UInt8]
            let aes = try! AES(key: key, blockMode: .ECB, padding: .pkcs5) // AES128 .ECB pkcs7
            let encrypted = try aes.encrypt(Array(self.utf8))

            result = encrypted.toBase64()!

            print("AES Encryption Result: \(result)")

        } catch {

            print("Error: \(error)")
        }

        return result
    }

    func aesDecrypt(key: String) throws -> String {

        var result = ""

        do {

            let encrypted = self
            let key: [UInt8] = Array(key.utf8) as [UInt8]
            let aes = try! AES(key: key, blockMode: .ECB, padding: .pkcs5) // AES128 .ECB pkcs7
            let decrypted = try aes.decrypt(Array(base64: encrypted))

            result = String(data: Data(decrypted), encoding: .utf8) ?? ""

            print("AES Decryption Result: \(result)")

        } catch {

            print("Error: \(error)")
        }

        return result
    }
}
_

これでは、暗号化のresult = encrypted.toBase64()!の代わりにresult = encrypted.toStringHex()!のように暗号化するためにivとencrypted.toBase64()を使用していません。

let decrypted = try aes.decrypt(Array(base64: encrypted))の代わりに復号化let decrypted = try aes.decrypt(Array(Hex: encrypted))で同様

1
Ayush Bansal

RNCryptorという名前のNiceライブラリが見つかりましたSwift AES暗号化/復号化用の言語。

インストールは、CocoapodsまたはCarthageを使用して実行できます。暗号化と復号化のサンプルコードを次に示します。

// Encryption
let data = "sample data string".data(using: String.Encoding.utf8)
let password = "Secret password"
let encryptedData = RNCryptor.encrypt(data: data, withPassword: password)

// Decryption
do {
    let originalData = try RNCryptor.decrypt(data: encryptedData, withPassword: password)
    // ...
} catch {
    print(error)
}
0
Alex Andrews

バイトの配列を文字列に変換できない人向け

String(data: Data(decrypted), encoding: .utf8)

これは私の例の文字列拡張です

extension String {

    func decryptAES(key: String, iv: String) -> String {
        do {
            let encrypted = self
            let key = Array(key.utf8)
            let iv = Array(iv.utf8)
            let aes = try AES(key: key, blockMode: CTR(iv: iv), padding: .noPadding)
            let decrypted = try aes.decrypt(Array(hex: encrypted))
            return String(data: Data(decrypted), encoding: .utf8) ?? ""
        } catch {
            return "Error: \(error)"
        }
    }
}