18
17

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アプリでAESでの暗号化のためCryptoSwiftを使用した

Last updated at Posted at 2018-09-27

動機

iOSアプリでテキストをAESで暗号化→暗号化したテキストをサーバーサイドへ送信。
その後、暗号化したテキストをサーバーサイドから取得して、iOSアプリで復号して表示といった流れを実装する必要があった。

AESとは

ざっくり書くと

  • 暗号化のやり方の一つ
  • 2018年現在のアメリカで標準として採用されているやり方
  • 共通鍵暗号方式
  • 鍵長が128ビット、192ビット、256ビットから選ぶことができる
  • WPA2で標準で採用されているやり方
  • WPAで使われる場合もある

https://wa3.i-3-i.info/word15121.html
https://techbooster.org/android/application/6629/

鍵、初期化ベクトルについては
https://qiita.com/asksaito/items/1793b8d8b3069b0b8d68

検証環境

ソース

抜粋しています

EncryptionUtil.swift
import Foundation
import CryptoSwift

struct EncryptionUtil {
    
    // ----- encryption -----
    // key:鍵
    // iv:初期化ベクトル
    // target:暗号化する文字列
    static func encrypt(key: String, iv: String, target:String) -> String? {

        do {
            let aes = try AES(key: key, iv: iv)
            let cipherArray = try aes.encrypt(Array(target.utf8))

            // [UInt8]をbase64Stringに変換して返す
            let data = NSData(bytes: cipherArray, length: cipherArray.count)
            let base64Data = data.base64EncodedData(options: [])
            let base64String = String(data: base64Data as Data, encoding: String.Encoding.utf8)
            return base64String
        } catch {
            return nil
        }
    }
    
    // ----- decryption -----
    // key:鍵
    // iv:初期化ベクトル
    // base64:復号する文字列、base64エンコードされている
    static func decrypt(key: String, iv: String, base64:String) -> String? {
        
        do {
            let aes = try AES(key: key, iv: iv)

            // 対象をbase64Decodeしてから、[UInt8]に変換する
            // base64 -> Data
            let aData = base64.data(using: String.Encoding.utf8)! as Data
            // Decode base64
            let dData = NSData(base64Encoded: aData, options: [])
            guard let data = dData else {
                return nil
            }
            // dataのバイト数と同じ大きさの配列を作る。
            var aBuffer = Array<UInt8>(repeating: 0, count: data.length)
            // aBufferにバイナリデータを格納。
            data.getBytes(&aBuffer, length: data.length)
            
            let decrypted = try aes.decrypt(aBuffer)
            let string = String(data: Data(bytes: decrypted), encoding: .utf8)
            return string
        } catch {
            return nil
        }
    }

    // ----- Initialization Vector -----
    static func getInitializationVector() -> String {
        let s = randomString(length: 16)
        return s
    }
    
    static func randomString(length: Int) -> String {
        let letters : NSString = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
        let l = UInt32(letters.length)
        
        var randomString = ""
        
        for _ in 0 ..< length {
            let rand = arc4random_uniform(l)
            var nextChar = letters.character(at: Int(rand))
            randomString += NSString(characters: &nextChar, length: 1) as String
        }
        
        return randomString
    }
    
}

テスト

テストコードで確認

hogehoge_iosTests.swift
import XCTest
@testable import hogehoge_ios

class hogehoge_iosTests: XCTestCase {
    
    override func setUp() {
        super.setUp()
    }
    
    override func tearDown() {
        super.tearDown()
    }
    
    func testEncryptionUtil() {
        // 鍵(128ビット)
        let key = "keykeykeykeykeyk"
        // 初期化ベクトル
        let iv = EncryptionUtil.getInitializationVector()
        
        let text = "abcdeあいうえおアイウエオ東京都中央区1234567890@+-:"
        let encrypted = EncryptionUtil.encrypt(key:key, iv:iv, target:text)
        XCTAssertNotNil(encrypted)
        XCTAssertFalse(encrypted! == text)

        let decrypted = EncryptionUtil.decrypt(key: key, iv: iv, base64: encrypted!)
        XCTAssertTrue(decrypted! == text)
    }
}

所感

AESでの暗号化、復号はCryptoSwiftのおかげで簡易であった。
だが暗号化文字列のサーバーサイドとのやり取りのため、[UInt8]とbase64エンコード文字列との相互変換が必要であり、そのあたりはCryptoSwiftに記述されていなくて(まあそうか)、工夫が必要だった。

お読み頂きありがとうございました。

18
17
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
18
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?