Zoeken…


AES-codering in CBC-modus met een willekeurige IV (Swift 3.0)

De iv wordt voorafgegaan door de gecodeerde gegevens

aesCBC128Encrypt maakt een willekeurige IV en wordt voorafgegaan door de gecodeerde code.
aesCBC128Decrypt gebruikt de prefix IV tijdens het decoderen.

Ingangen zijn de gegevens en sleutel zijn gegevensobjecten. Als een gecodeerde vorm zoals Base64 indien nodig wordt geconverteerd naar en / of van in de aanroepende methode.

De sleutel moet exact 128 bits (16 bytes), 192 bits (24 bytes) of 256 bits (32 bytes) lang zijn. Als een andere sleutelgrootte wordt gebruikt, wordt een fout gegenereerd.

Opvulling PKCS # 7 is standaard ingesteld.

Dit voorbeeld vereist Common Crypto
Het is noodzakelijk om een overbruggingskop naar het project te hebben:
#import <CommonCrypto/CommonCrypto.h>
Voeg het Security.framework aan het project.

Dit is bijvoorbeeld geen productiecode.

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;
}

Voorbeeld gebruik:

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)")
}

Voorbeelduitvoer:

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>

Opmerkingen:
Een typisch probleem met de voorbeeldcode van de CBC-modus is dat deze het maken en delen van de willekeurige IV overlaat aan de gebruiker. Dit voorbeeld omvat het genereren van de IV, voorafgegaan door de gecodeerde gegevens en gebruikt de vooraf bepaalde IV tijdens het ontsleutelen. Dit bevrijdt de toevallige gebruiker van de details die nodig zijn voor de CBC-modus .

Voor de veiligheid moeten de gecodeerde gegevens ook authenticatie hebben, deze voorbeeldcode voorziet niet in dat deze klein is en betere interoperabiliteit voor andere platforms mogelijk maakt.

Ook ontbreekt de sleutelafleiding van de sleutel uit een wachtwoord, er wordt gesuggereerd dat PBKDF2 wordt gebruikt als tekstwachtwoorden worden gebruikt als sleutelmateriaal.

Zie RNCryptor voor robuuste, productieklare multi-platform coderingscode.

Bijgewerkt om gooien / vangen en meerdere sleutelgroottes te gebruiken op basis van de geleverde sleutel.

AES-codering in CBC-modus met een willekeurige IV (Swift 2.3)

De iv wordt voorafgegaan door de gecodeerde gegevens

aesCBC128Encrypt maakt een willekeurige IV en wordt voorafgegaan door de gecodeerde code. aesCBC128Decrypt gebruikt de prefix IV tijdens het decoderen.

Ingangen zijn de gegevens en sleutel zijn gegevensobjecten. Als een gecodeerde vorm zoals Base64 indien nodig wordt geconverteerd naar en / of van in de aanroepende methode.

De sleutel moet exact 128 bits (16 bytes) zijn. Zie het voorbeeld van Swift 3.0 voor andere sleutelgroottes.

Opvulling PKCS # 7 is standaard ingesteld.

Dit voorbeeld vereist Common Crypto Het is noodzakelijk om een bridging header naar het project te hebben: #import <CommonCrypto / CommonCrypto.h> Voeg Security.framework toe aan het project.

Zie Swift 3-voorbeeld voor notities.

Dit is bijvoorbeeld geen productiecode.

func aesCBC128Encrypt(data data:[UInt8], keyData:[UInt8]) -> [UInt8]? {
    let keyLength   = size_t(kCCKeySizeAES128)
    let ivLength    = size_t(kCCBlockSizeAES128)
    let cryptDataLength = size_t(data.count + kCCBlockSizeAES128)
    var cryptData = [UInt8](count:ivLength + cryptDataLength, repeatedValue:0)

    let status = SecRandomCopyBytes(kSecRandomDefault, Int(ivLength), UnsafeMutablePointer<UInt8>(cryptData));
    if (status != 0) {
        print("IV Error, errno: \(status)")
        return nil
    }

    var numBytesEncrypted :size_t = 0
    let cryptStatus = CCCrypt(CCOperation(kCCEncrypt),
                              CCAlgorithm(kCCAlgorithmAES128),
                              CCOptions(kCCOptionPKCS7Padding),
                              keyData, keyLength,
                              cryptData,
                              data, data.count,
                              &cryptData + ivLength, cryptDataLength,
                              &numBytesEncrypted)

    if UInt32(cryptStatus) == UInt32(kCCSuccess) {
        cryptData.removeRange(numBytesEncrypted+ivLength..<cryptData.count)
    }
    else {
        print("Error: \(cryptStatus)")
        return nil;
    }

    return cryptData;
}

func aesCBC128Decrypt(data data:[UInt8], keyData:[UInt8]) -> [UInt8]? {
    let clearLength = size_t(data.count)
    var clearData   = [UInt8](count:clearLength, repeatedValue:0)

    let keyLength   = size_t(kCCKeySizeAES128)
    let ivLength    = size_t(kCCBlockSizeAES128)

    var numBytesDecrypted :size_t = 0
    let cryptStatus = CCCrypt(CCOperation(kCCDecrypt),
                              CCAlgorithm(kCCAlgorithmAES128),
                              CCOptions(kCCOptionPKCS7Padding),
                              keyData, keyLength,
                              data,
                              UnsafePointer<UInt8>(data) + ivLength, data.count - ivLength,
                              &clearData, clearLength,
                              &numBytesDecrypted)

    if UInt32(cryptStatus) == UInt32(kCCSuccess) {
        clearData.removeRange(numBytesDecrypted..<clearLength)

    } else {
        print("Error: \(cryptStatus)")
        return nil;
    }

    return clearData;
}

Voorbeeld gebruik:

let clearData = toData("clearData0123456")
let keyData   = toData("keyData890123456")

print("clearData:   \(toHex(clearData))")
print("keyData:     \(toHex(keyData))")
let cryptData = aesCBC128Encrypt(data:clearData, keyData:keyData)!
print("cryptData:   \(toHex(cryptData))")
let decryptData = aesCBC128Decrypt(data:cryptData, keyData:keyData)!
print("decryptData: \(toHex(decryptData))")

Voorbeelduitvoer:

clearData:   <636c6561 72446174 61303132 33343536>
keyData:     <6b657944 61746138 39303132 33343536>
cryptData:   <9fce4323 830e3734 93dd93bf e464f72a a653a3a5 2c40d5ea e90c1017 958750a7 ff094c53 6a81b458 b1fbd6d4 1f583298>
decryptData: <636c6561 72446174 61303132 33343536>

AES-codering in ECB-modus met PKCS7-vulling

Uit Apple-documentatie voor IV,

Deze parameter wordt genegeerd als de ECB-modus wordt gebruikt of als een algoritme voor stroomcodering is geselecteerd.

func AESEncryption(key: String) -> String? {
        
        let keyData: NSData! = (key as NSString).data(using: String.Encoding.utf8.rawValue) as NSData!
        
        let data: NSData! = (self as NSString).data(using: String.Encoding.utf8.rawValue) as NSData!
        
        let 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(kCCOptionECBMode + kCCOptionPKCS7Padding)
        
        var numBytesEncrypted :size_t = 0
        
        
        let cryptStatus = CCCrypt(operation,
                                  algoritm,
                                  options,
                                  keyData.bytes, keyLength,
                                  nil,
                                  data.bytes, data.length,
                                  cryptData.mutableBytes, cryptData.length,
                                  &numBytesEncrypted)
        
        if UInt32(cryptStatus) == UInt32(kCCSuccess) {
            cryptData.length = Int(numBytesEncrypted)
            
            var bytes = [UInt8](repeating: 0, count: cryptData.length)
            cryptData.getBytes(&bytes, length: cryptData.length)
            
            var hexString = ""
            for byte in bytes {
                hexString += String(format:"%02x", UInt8(byte))
            }
            
            return hexString
        }
        
        return nil
    }


Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow