web-dev-qa-db-fra.com

AES Encrypt and Decrypt

J'écris une application de Swift, j'ai besoin de la fonctionnalité AES Encrypt and Decrypt, j'ai reçu des données cryptées d'une autre solution .Net, mais je ne trouve rien pour le faire.

Voici mon cryptage .net:

 public static byte[] AES_Encrypt(byte[] bytesToBeEncrypted, byte[] passwordBytes)
    {
        byte[] encryptedBytes = null;

        byte[] saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };

        using (MemoryStream ms = new MemoryStream())
        {
            using (RijndaelManaged AES = new RijndaelManaged())
            {
                AES.KeySize = 256;
                AES.BlockSize = 128;

                var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000);
                AES.Key = key.GetBytes(AES.KeySize / 8);
                AES.IV = key.GetBytes(AES.BlockSize / 8);

                AES.Mode = CipherMode.CBC;

                using (var cs = new CryptoStream(ms, AES.CreateEncryptor(), CryptoStreamMode.Write))
                {
                    cs.Write(bytesToBeEncrypted, 0, bytesToBeEncrypted.Length);
                    cs.Close();
                }
                encryptedBytes = ms.ToArray();
            }
        }

        return encryptedBytes;
    }

J'ai besoin de décrypter la fonction dans Swift.

21
mehr

J'ai trouvé la solution, c'est une bonne bibliothèque.

Cryptage/décryptage AES 256 bits multiplate-forme.

Ce projet contient la mise en oeuvre du cryptage AES 256 bits qui fonctionne sur toutes les plateformes (C #, iOS, Android). L'un des objectifs clés est de faire fonctionner AES sur toutes les plateformes avec une mise en œuvre simple.

Plateformes prises en charge: IOS, Android, Windows (C #).

https://github.com/Pakhee/Cross-platform-AES-encryption

0
mehr

CryptoSwift Exemple

Mis à jour vers Swift 2

import Foundation
import CryptoSwift

extension String {
    func aesEncrypt(key: String, iv: String) throws -> String{
        let data = self.dataUsingEncoding(NSUTF8StringEncoding)
        let enc = try AES(key: key, iv: iv, blockMode:.CBC).encrypt(data!.arrayOfBytes(), padding: PKCS7())
        let encData = NSData(bytes: enc, length: Int(enc.count))
        let base64String: String = encData.base64EncodedStringWithOptions(NSDataBase64EncodingOptions(rawValue: 0));
        let result = String(base64String)
        return result
    }

    func aesDecrypt(key: String, iv: String) throws -> String {
        let data = NSData(base64EncodedString: self, options: NSDataBase64DecodingOptions(rawValue: 0))
        let dec = try AES(key: key, iv: iv, blockMode:.CBC).decrypt(data!.arrayOfBytes(), padding: PKCS7())
        let decData = NSData(bytes: dec, length: Int(dec.count))
        let result = NSString(data: decData, encoding: NSUTF8StringEncoding)
        return String(result!)
    }
}

Usage:

let key = "bbC2H19lkVbQDfakxcrtNMQdd0FloLyw" // length == 32
let iv = "gqLOHUioQ0QjhuvI" // length == 16
let s = "string to encrypt"
let enc = try! s.aesEncrypt(key, iv: iv)
let dec = try! enc.aesDecrypt(key, iv: iv)
print(s) // string to encrypt
print("enc:\(enc)") // 2r0+KirTTegQfF4wI8rws0LuV8h82rHyyYz7xBpXIpM=
print("dec:\(dec)") // string to encrypt
print("\(s == dec)") // true

Assurez-vous que vous avez la bonne longueur de iv (16) et de la clé (32) pour éviter de frapper "La taille du bloc et le vecteur d'initialisation doivent avoir la même longueur!" Erreur.

29
yutelin

CryptoSwift Exemple

Mis à jour Swift 4. *

func aesEncrypt() throws -> String {
    let encrypted = try AES(key: KEY, iv: IV, padding: .pkcs7).encrypt([UInt8](self.data(using: .utf8)!))
    return Data(encrypted).base64EncodedString()
}

func aesDecrypt() throws -> String {
    guard let data = Data(base64Encoded: self) else { return "" }
    let decrypted = try AES(key: KEY, iv: IV, padding: .pkcs7).decrypt([UInt8](data))
    return String(bytes: Data(decrypted).bytes, encoding: .utf8) ?? "Could not decrypt"
}
21
Maksim Kniazev

Le code fourni par SHS ne fonctionnait pas pour moi, mais celui-ci semblait fonctionner (j'ai utilisé un en-tête de pontage: #import <CommonCrypto/CommonCrypto.h>):

extension String {

    func aesEncrypt(key:String, iv:String, options:Int = kCCOptionPKCS7Padding) -> String? {
        if let keyData = key.data(using: String.Encoding.utf8),
            let data = self.data(using: String.Encoding.utf8),
            let cryptData    = NSMutableData(length: Int((data.count)) + kCCBlockSizeAES128) {


            let keyLength              = size_t(kCCKeySizeAES128)
            let operation: CCOperation = UInt32(kCCEncrypt)
            let algoritm:  CCAlgorithm = UInt32(kCCAlgorithmAES128)
            let options:   CCOptions   = UInt32(options)



            var numBytesEncrypted :size_t = 0

            let cryptStatus = CCCrypt(operation,
                                      algoritm,
                                      options,
                                      (keyData as NSData).bytes, keyLength,
                                      iv,
                                      (data as NSData).bytes, data.count,
                                      cryptData.mutableBytes, cryptData.length,
                                      &numBytesEncrypted)

            if UInt32(cryptStatus) == UInt32(kCCSuccess) {
                cryptData.length = Int(numBytesEncrypted)
                let base64cryptString = cryptData.base64EncodedString(options: .lineLength64Characters)
                return base64cryptString


            }
            else {
                return nil
            }
        }
        return nil
    }

    func aesDecrypt(key:String, iv:String, options:Int = kCCOptionPKCS7Padding) -> String? {
        if let keyData = key.data(using: String.Encoding.utf8),
            let data = NSData(base64Encoded: self, options: .ignoreUnknownCharacters),
            let cryptData    = NSMutableData(length: Int((data.length)) + kCCBlockSizeAES128) {

            let keyLength              = size_t(kCCKeySizeAES128)
            let operation: CCOperation = UInt32(kCCDecrypt)
            let algoritm:  CCAlgorithm = UInt32(kCCAlgorithmAES128)
            let options:   CCOptions   = UInt32(options)

            var numBytesEncrypted :size_t = 0

            let cryptStatus = CCCrypt(operation,
                                      algoritm,
                                      options,
                                      (keyData as NSData).bytes, keyLength,
                                      iv,
                                      data.bytes, data.length,
                                      cryptData.mutableBytes, cryptData.length,
                                      &numBytesEncrypted)

            if UInt32(cryptStatus) == UInt32(kCCSuccess) {
                cryptData.length = Int(numBytesEncrypted)
                let unencryptedMessage = String(data: cryptData as Data, encoding:String.Encoding.utf8)
                return unencryptedMessage
            }
            else {
                return nil
            }
        }
        return nil
    }


}

De ma ViewController:

 let encoded = message.aesEncrypt(key: keyString, iv: iv)
 let unencode = encoded?.aesDecrypt(key: keyString, iv: iv)
9
user1094081

Il existe une bibliothèque Open Source intéressante "pure-Swift": 

Exemple avec AES decrypt (extrait du fichier README.md du projet):

import CryptoSwift
let setup = (key: keyData, iv: ivData)
let decryptedAES = Cipher.AES(setup).decrypt(encryptedData)
6
Roberto

J'utilisais CommonCrypto pour générer Hash via le code de MihaelIsaev/HMAC.Swift from Facile à utiliser. Implémentation Swift de CommonCrypto HMAC . Cette implémentation se fait sans utiliser Bridging-Header, avec la création du fichier Module.

Maintenant, pour utiliser AESEncrypt et Decrypt, j'ai directement ajouté les fonctions à l'intérieur de "extension String {" dans HAMC.Swift.

func aesEncrypt(key:String, iv:String, options:Int = kCCOptionPKCS7Padding) -> String? {
    if let keyData = key.dataUsingEncoding(NSUTF8StringEncoding),
        data = self.dataUsingEncoding(NSUTF8StringEncoding),
        cryptData    = NSMutableData(length: Int((data.length)) + kCCBlockSizeAES128) {

            let keyLength              = size_t(kCCKeySizeAES128)
            let operation: CCOperation = UInt32(kCCEncrypt)
            let algoritm:  CCAlgorithm = UInt32(kCCAlgorithmAES128)
            let options:   CCOptions   = UInt32(options)

            var numBytesEncrypted :size_t = 0

            let cryptStatus = CCCrypt(operation,
                algoritm,
                options,
                keyData.bytes, keyLength,
                iv,
                data.bytes, data.length,
                cryptData.mutableBytes, cryptData.length,
                &numBytesEncrypted)

            if UInt32(cryptStatus) == UInt32(kCCSuccess) {
                cryptData.length = Int(numBytesEncrypted)
                let base64cryptString = cryptData.base64EncodedStringWithOptions(.Encoding64CharacterLineLength)
                return base64cryptString
            }
            else {
                return nil
            }
    }
    return nil
}

func aesDecrypt(key:String, iv:String, options:Int = kCCOptionPKCS7Padding) -> String? {
    if let keyData = key.dataUsingEncoding(NSUTF8StringEncoding),
        data = NSData(base64EncodedString: self, options: .IgnoreUnknownCharacters),
        cryptData    = NSMutableData(length: Int((data.length)) + kCCBlockSizeAES128) {

            let keyLength              = size_t(kCCKeySizeAES128)
            let operation: CCOperation = UInt32(kCCDecrypt)
            let algoritm:  CCAlgorithm = UInt32(kCCAlgorithmAES128)
            let options:   CCOptions   = UInt32(options)

            var numBytesEncrypted :size_t = 0

            let cryptStatus = CCCrypt(operation,
                algoritm,
                options,
                keyData.bytes, keyLength,
                iv,
                data.bytes, data.length,
                cryptData.mutableBytes, cryptData.length,
                &numBytesEncrypted)

            if UInt32(cryptStatus) == UInt32(kCCSuccess) {
                cryptData.length = Int(numBytesEncrypted)
                let unencryptedMessage = String(data: cryptData, encoding:NSUTF8StringEncoding)
                return unencryptedMessage
            }
            else {
                return nil
            }
    }
    return nil
}

Les fonctions ont été prises à partir de RNCryptor . C'était un ajout facile dans les fonctions de hachage et dans un seul fichier "HMAC.Swift", sans utiliser d'en-tête Bridging. J'espère que cela sera utile aux développeurs de Swift ayant besoin du hachage et du cryptage/décryptage AES.

Exemple d'utilisation de AESDecrypt en tant que sous.

 let iv = "AA-salt-BBCCDD--" // should be of 16 characters.
 //here we are convert nsdata to String
 let encryptedString = String(data: dataFromURL, encoding: NSUTF8StringEncoding)
 //now we are decrypting
 if let decryptedString = encryptedString?.aesDecrypt("12345678901234567890123456789012", iv: iv) // 32 char pass key
 {                    
      // Your decryptedString
 }
4
SHS

CryptoSwift est un projet très intéressant mais pour le moment, il a quelques limitations de vitesse AES. Faites attention si vous avez besoin de faire une crypto sérieuse - il pourrait être intéressant de passer par la douleur de passerelle implémentant CommonCrypto.

BigUps à Marcin pour la mise en œuvre de pureSwift

3
ha100

Swift4:

let key = "ccC2H19lDDbQDfakxcrtNMQdd0FloLGG" // length == 32
let iv = "ggGGHUiDD0Qjhuvv" // length == 16
func encryptFile(_ path: URL) -> Bool{
    do{
        let data = try Data.init(contentsOf: path)
        let encodedData = try data.aesEncrypt(key: key, iv: iv)
        try encodedData.write(to: path)
        return true
    }catch{
        return false
    }
}

func decryptFile(_ path: URL) -> Bool{
    do{
        let data = try Data.init(contentsOf: path)
        let decodedData = try data.aesDecrypt(key: key, iv: iv)
        try decodedData.write(to: path)
        return true
    }catch{
        return false
    }
}

** Pod installer Crypto Swift ** 1. pod 'CryptoSwift' #add to PodFile 2. installation de pod

import CryptoSwift

extension Data {
    func aesEncrypt(key: String, iv: String) throws -> Data{
        let encypted = try AES(key: key.bytes, blockMode: CBC(iv: iv.bytes), padding: .pkcs7).encrypt(self.bytes)
        return Data(bytes: encypted)
    }

    func aesDecrypt(key: String, iv: String) throws -> Data {
        let decrypted = try AES(key: key.bytes, blockMode: CBC(iv: iv.bytes), padding: .pkcs7).decrypt(self.bytes)
        return Data(bytes: decrypted)
    }
}
0
August Lin

Vous pouvez utiliser CommonCrypto à partir d'iOS ou CryptoSwift en tant que bibliothèque externe. Il existe des implémentations avec les deux outils ci-dessous. Cela dit, la sortie de CommonCrypto avec AES doit être testée, car la documentation de CC n’indique pas clairement quel mode d’AES il utilise.

CommonCrypto dans Swift 4.2

 importer CommonCrypto 

 func encrypt (data: Data) -> Données {
 renvoyer cryptCC (données: données, clé: clé, opération: kCCEncrypt) 
 } 

 func decrypt (data: Data) -> Données {
 renvoyer cryptCC (données: données, clé: clé, opération: kCCDecrypt) 
 } 

 private func cryptCC (données: données, clé: opérations sur chaînes: int) -> données {

 guard key.count == kCCKeySizeAES128 sinon {
 fatalError ("La taille de la clé a échoué!") 
 } 

 var ivBytes: [UInt8] 
 var inBytes: [UInt8] 
 var outLength: Int 

 si opération == kCCEncrypt {
 ivBytes = [UInt8] (en répétant: 0, compte: kCCBlockSizeAES128) 
 guard kCCSuccess == SecRandomCopyBytes (kSecRandomDefault, ivBytes.count, & ivBytes) sinon {
 fatalError ("La création IV a échoué!") 
 } 

 inBytes = Array (data) 
 outLength = data.count + kCCBlockSizeAES128 

 } autre {
 ivBytes = Array (Array (data) .dropLast (data.count - kCCBlockSizeAES128)) 
 inBytes = Array (Array (data) .dropFirst (kCCBlockSizeAES128)) 
 outLength = inBytes.count 

 } 

 var outBytes = [UInt8] (en répétant: 0, count: outLength) 
 var bytesMutated = 0 

 guard kCCSuccess == CCCrypt (CCOperation (opération), CCAlgorithm (kCCAlgorithmAES128), CCOptions (kCCOptionPKCS7Padding), Array (clé), kCCKeySizeAES128, & ivBytes, & inBytes, inBytes, in out, fatalError ("Echec de l'opération de cryptographie\(opération)") 
 } 

 var outData = Data (octets: & outBytes, count: bytesMutated) 

 si opération == kCCEncrypt {
 ivBytes.append (contentsOf: Array (outData)) 
 outData = Data (octets: ivBytes) 
 } 
 renvoyer outData 

 } 


CryptoSwift v0.14 dans Swift 4.2


 enum Operation {
 case encrypt 
 cas décrypter 
 } 

 private let keySizeAES128 = 16 
 private let aesBlockSize = 16 

 func encrypt (data: Data, clé: String) -> Data {
 renvoyer crypt (données: données, clé: clé, opération: .encrypt) 
 } 

 func decrypt (data: Data, clé: String) -> Data {
 renvoyer crypt (données: données, clé: clé, opération: .decrypt) 
 } 

 private func crypt (données: données, clé: chaîne, opération: opération) -> données {

 guard key.count == keySizeAES128 sinon {
 fatalError ("La taille de la clé a échoué!") 
 } 
 var outData: Data? = nul 

 si opération == .encrypt {
 var ivBytes = [UInt8] (répétant: 0, compte: aesBlockSize) 
 guard 0 == SecRandomCopyBytes (kSecRandomDefault, ivBytes.count, & ivBytes) else {
 fatalError ("La création IV a échoué!") 
 } 

 faire {
 let aes = try AES (key: Array (key.data (using: .utf8)!), blockMode: CBC (iv: ivBytes)) 
 laissez crypté = essayez aes.encrypt (Array (data)) 
 ivBytes.append (contentsOf: crypté) 
 outData = Data (octets: ivBytes) 

 } capture {
 print ("Erreur de cryptage:\(erreur)") 
 } 

 } autre {
 let ivBytes = Array (Array (data) .dropLast (data.count - aesBlockSize)) 
 let inBytes = Array (Array (data) .dropFirst (aesBlockSize)) 

 faire {
 let aes = try AES (key: Array (key.data (using: .utf8)!), blockMode: CBC (iv: ivBytes)) 
 let decrypted = essayez aes.decrypt (inBytes) 
 outData = Data (octets: déchiffré) 

 } capture {
 print ("Erreur de déchiffrement:\(erreur)") 
 } 
 } 
 renvoyer outData! 

 } 

0
cenkarioz

Mise à jour Swift 4.2

Ici, par exemple, nous chiffrons une chaîne en chaîne encodée en base64. Et puis nous déchiffrons la même chose en une chaîne lisible. (Ce serait la même chose que notre chaîne d'entrée).

Dans mon cas, j'utilise ceci pour chiffrer une chaîne et l'intégrer au code QR. Ensuite, une autre partie l’analyse et le déchiffre. Donc, intermédiaire ne comprendra pas les codes QR. 

Étape 1: Crypter une chaîne "Crypter mon message 123"

Étape 2: Chaîne cryptée en base64: + yvNjiD7F9/JKmqHTc/Mjg == (identique imprimé en code QR)

Étape 3: Scannez et déchiffrez la chaîne "+ yvNjiD7F9/JKmqHTc/Mjg ==" 

Étape 4: Il en résulte un résultat final - "Crypter mon message 123"

Fonctions pour chiffrer et déchiffrer

func encryption(stringToEncrypt: String) -> String{
    let key = "MySecretPKey"
    //let iv = "92c9d2c07a9f2e0a"
    let data = stringToEncrypt.data(using: .utf8)
    let keyD = key.data(using: .utf8)
    let encr = (data as NSData?)!.aes128EncryptedData(withKey: keyD)
    let base64String: String = (encr as NSData?)!.base64EncodedString(options: NSData.Base64EncodingOptions(rawValue: 0))
    print(base64String)
    return base64String
}

func decryption(encryptedString:String) -> String{
    let key = "MySecretPKey"
    //let iv = "92c9d2c07a9f2e0a"
    let keyD = key.data(using: .utf8)
    let decrpStr = NSData(base64Encoded: encryptedString, options: NSData.Base64DecodingOptions(rawValue: 0))
    let dec = (decrpStr)!.aes128DecryptedData(withKey: keyD)
    let backToString = String(data: dec!, encoding: String.Encoding.utf8)
    print(backToString!)
    return backToString!
}

Utilisation:

    let enc = encryption(stringToEncrypt: "Encrypt My Message 123")
    let decryptedString = decryption(encryptedString: enc)
    print(decryptedString) 

Les classes de prise en charge des fonctions de chiffrement AES sont écrites en Objective-C. Donc, pour Swift, vous devez utiliser un en-tête de pont pour les prendre en charge.

Nom de classe: NSData + AES.h

#import <Foundation/Foundation.h>

@interface NSData (AES)

- (NSData *)AES128EncryptedDataWithKey:(NSData *)key;
- (NSData *)AES128DecryptedDataWithKey:(NSData *)key;
- (NSData *)AES128EncryptedDataWithKey:(NSData *)key iv:(NSData *)iv;
- (NSData *)AES128DecryptedDataWithKey:(NSData *)key iv:(NSData *)iv;

@end

Nom de classe: NSData + AES.m

#import "NSData+AES.h"
#import <CommonCrypto/CommonCryptor.h>

@implementation NSData (AES)

- (NSData *)AES128EncryptedDataWithKey:(NSData *)key
{
    return [self AES128EncryptedDataWithKey:key iv:nil];
}

- (NSData *)AES128DecryptedDataWithKey:(NSData *)key
{
    return [self AES128DecryptedDataWithKey:key iv:nil];
}

- (NSData *)AES128EncryptedDataWithKey:(NSData *)key iv:(NSData *)iv
{
    return [self AES128Operation:kCCEncrypt key:key iv:iv];
}

- (NSData *)AES128DecryptedDataWithKey:(NSData *)key iv:(NSData *)iv
{
    return [self AES128Operation:kCCDecrypt key:key iv:iv];
}

- (NSData *)AES128Operation:(CCOperation)operation key:(NSData *)key iv:(NSData *)iv
{

    NSUInteger dataLength = [self length];
    size_t bufferSize = dataLength + kCCBlockSizeAES128;
    void *buffer = malloc(bufferSize);

    size_t numBytesEncrypted = 0;
    CCCryptorStatus cryptStatus = CCCrypt(operation,
                                          kCCAlgorithmAES128,
                                          kCCOptionPKCS7Padding | kCCOptionECBMode,
                                          key.bytes,
                                          kCCBlockSizeAES128,
                                          iv.bytes,
                                          [self bytes],
                                          dataLength,
                                          buffer,
                                          bufferSize,
                                          &numBytesEncrypted);
    if (cryptStatus == kCCSuccess) {
        return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
    }
    free(buffer);
    return nil;
}

@end

J'espère que ça aide.

Merci!!!

0
Harjot Singh

Vous pouvez simplementcopier/collerces méthodes (Swift 4+) :

    class func encryptMessage(message: String, encryptionKey: String, iv: String) -> String? {
        if let aes = try? AES(key: encryptionKey, iv: iv),
            let encrypted = try? aes.encrypt(Array<UInt8>(message.utf8)) {
            return encrypted.toHexString()
        }
        return nil
    }

    class func decryptMessage(encryptedMessage: String, encryptionKey: String, iv: String) -> String? {
        if let aes = try? AES(key: encryptionKey, iv: iv),
            let decrypted = try? aes.decrypt(Array<UInt8>(hex: encryptedMessage)) {
            return String(data: Data(bytes: decrypted), encoding: .utf8)
        }
        return nil
    }

Exemple:

let encryptMessage = encryptMessage(message: "Hello World!", encryptionKey: "mykeymykeymykey1", iv: "myivmyivmyivmyiv")    
// Output of encryptMessage is: 649849a5e700d540f72c4429498bf9f4

let decryptedMessage = decryptMessage(encryptedMessage: encryptMessage, encryptionKey: "mykeymykeymykey1", iv: "myivmyivmyivmyiv")
// Output of decryptedMessage is: Hello World!

N'oubliez pas que encryptionKey & iv doit comporter 16 octets.


0
Dardan