Swift Language
AES暗号化
サーチ…
ランダムIV(Swift 3.0)のCBCモードでのAES暗号化
ivは、暗号化されたデータの前に付けられます
aesCBC128Encrypt
はランダムなIVを作成し、暗号化されたコードにプレフィックスを付けます。
aesCBC128Decrypt
は、復号化中に接頭辞付きのIVを使用します。
入力はデータ、キーはデータオブジェクトです。必要に応じてBase64などのエンコードされたフォームが、呼び出し元のメソッドに変換および/または変換する場合。
キーは、正確に128ビット(16バイト)、192ビット(24バイト)または256ビット(32バイト)の長さでなければなりません。別のキーサイズを使用すると、エラーがスローされます。
PKCS#7のパディングはデフォルトで設定されています。
この例では、Common Crypto
プロジェクトへのブリッジヘッダーが必要です。
#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を参照してください。
指定されたキーに基づいてスロー/キャッチおよび複数のキーサイズを使用するように更新されました。
ランダムIV(Swift 2.3)のCBCモードでのAES暗号化
ivは、暗号化されたデータの前に付けられます
aesCBC128EncryptはランダムなIVを作成し、暗号化されたコードにプレフィックスを付けます。 aesCBC128Decryptは、復号化中に接頭辞付きのIVを使用します。
入力はデータ、キーはデータオブジェクトです。必要に応じてBase64などのエンコードされたフォームが、呼び出し元のメソッドに変換および/または変換する場合。
キーは正確に128ビット(16バイト)でなければなりません。その他のキーサイズについては、Swift 3.0の例を参照してください。
PKCS#7のパディングはデフォルトで設定されています。
この例ではCommon Cryptoが必要ですプロジェクトへのブリッジヘッダーが必要です。#import <CommonCrypto / CommonCrypto.h> Security.frameworkをプロジェクトに追加します。
ノートのSwift 3の例を参照してください。
これは実例コードであり、実動コードではありません。
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;
}
使用例:
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))")
出力例:
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>
PKCS7パディングを使用したECBモードでのAES暗号化
IVに関するAppleのドキュメントから、
このパラメータは、ECBモードが使用されている場合、またはストリーム暗号アルゴリズムが選択されている場合は無視されます。
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
}