#最初に...
2回目の投稿です。去年の12月に投稿した際
次回はSwift4で同じことをする予定です・・・。
と言っておりましたが、気づいたらこんな時期に。
宣言通りSwift4でAES暗号をやります。
Androidと同様にOpenSourceのライブラリは未使用です。
##下準備
今回はCommonCryptoを使用します。
基本、"/usr/include"にあるのですが、ない場合は
Commnad Line Toolsをインストールで解決すると思います。
https://qiita.com/mym/items/8bc079b7d0f5f55c49dc
上記URLをご確認ください。
また、Swift4からCommonCryptoを使用する場合はmodule.modulemapを作成する必要があります。
適当な位置に(今回はプロジェクト直下に作成しました)module.modulemapを作成します。
そのファイルに以下を記載します。
module CommonCrypto {
header "/usr/include/CommonCrypto/CommonCrypto.h"
export *
}
その後、Project->BuildSettings->Swift Compiler-Search paths->Import Pathsに
module.modulemapのパスを追加してください。
(私の場合は${SRCROOT})
##実際のソース
AES鍵作成
let key = Data.init(count: kCCKeySizeAES128)
let addquery: [String: Any] = [kSecClass as String: kSecClassKey,
kSecAttrApplicationTag as String: alias,
kSecValueData as String: key as Any]
_ = SecItemAdd(addquery as CFDictionary, nil)
AES鍵取得
let getquery: [String: Any] = [kSecClass as String: kSecClassKey,
kSecAttrApplicationTag as String: alias,
kSecReturnData as String: true]
var item: AnyObject?
SecItemCopyMatching(getquery as CFDictionary, &item)
return item as? Data
暗号化
let keyData = getSaveKey()
let textData = plainStr.data(using: .utf8)!
let ivData = iv.data(using: .utf8)!
let cryptLength = size_t(textData.count + kCCKeySizeAES128)
var cryptData = Data(count:cryptLength)
let keyLength = size_t(kCCKeySizeAES128)
let algoritm = CCAlgorithm(kCCAlgorithmAES)
let options = CCOptions(kCCModeCBC | kCCOptionPKCS7Padding)
var numBytesEncrypted: Int = 0
let cryptStatus = keyData?.withUnsafeBytes {keyBytes in
textData.withUnsafeBytes {dataBytes in
ivData.withUnsafeBytes {iv in
cryptData.withUnsafeMutableBytes {cryptPointer in
CCCrypt(CCOperation(kCCEncrypt), algoritm,
options,
keyBytes, keyLength,
iv,
dataBytes, textData.count,
cryptPointer, cryptLength,
&numBytesEncrypted)
}
}
}
}
if cryptStatus == CCCryptorStatus(kCCSuccess) {
cryptData.count = numBytesEncrypted
} else {
return ""
}
return (cryptData.base64EncodedString())
復号
let keyData = getSaveKey()
let textData = Data(base64Encoded: encryptStr)!
let ivData = iv.data(using: .utf8)!
let cryptLength = size_t(textData.count + kCCKeySizeAES128)
var cryptData = Data(count:cryptLength)
let keyLength = size_t(kCCKeySizeAES128)
let algoritm = CCAlgorithm(kCCAlgorithmAES)
let options = CCOptions(kCCModeCBC | kCCOptionPKCS7Padding)
var numBytesEncrypted: Int = 0
let cryptStatus = keyData?.withUnsafeBytes {keyBytes in
textData.withUnsafeBytes {dataBytes in
ivData.withUnsafeBytes {iv in
cryptData.withUnsafeMutableBytes {cryptPointer in
CCCrypt(CCOperation(kCCDecrypt), algoritm,
options,
keyBytes, keyLength,
iv,
dataBytes, textData.count,
cryptPointer, cryptLength,
&numBytesEncrypted)
}
}
}
}
if cryptStatus == CCCryptorStatus(kCCSuccess) {
cryptData.count = numBytesEncrypted
} else {
return ""
}
return String.init(data: cryptData, encoding: .utf8)!
呼び出し
let service:KeySrv = KeySrv()
let str:String = "5000兆円"
service.generateAesKey()
NSLog("暗号前:%@", str)
let encrypt = service.encryptString(plainStr: str)
NSLog("暗号後:%@", encrypt)
NSLog("復号後:%@", service.decryptString(encryptStr: encrypt))
let fake = "OPnpyT3z4PCc368AB3eZ8w=="
NSLog("fake復号後:%@", service.decryptString(encryptStr: fake))
結果
暗号前:5000兆円
暗号後:HPnpyT3z4PCc368AB3eZ8w==
復号後:5000兆円
fake復号後:
##最後に
ご覧いただき、ありがとうございます。
次回は、鍵は安全な所に保存されるとリファレンスで確認していたが
一部端末にて安全な所に保存されていないというケースが発生したのでそれを記事して
スマホの鍵操作シリーズは終わりにします。
また、後ほど時間ある時にgithubにプロジェクトをあげます。