6
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

アプリ内に保存するデータを暗号化する(iOS)

Last updated at Posted at 2018-05-18

#最初に...
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にプロジェクトをあげます。

6
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?