AWS KMSを使って暗号化、復号化を行います。
データキーによる暗号化も出来るのですが、今回はマスターキーを使った暗号化をやります。
環境
XCode 9.4.1
Swift 4.1
手順
CognitoでPool idを作成
CognitoはKMSというよりもAWS SDKそのものを使うために必要です。
「IDプールの管理」をクリックします。
「新しいIDプールの作成」をクリック
IDプール名を入力し、「認証されていないIDに対しアクセスを有効にする」にチェックを入れます。
「プールの作成」ボタンを押すとIDプールが作成されます。
ここのプールIDが後々必要になります。
KMSでマスターキーを作成
IAMを開きます。
マスターキーを作る前にCognitoのロールに対し権限を追加します。
Cognitoの2つのロールに対しAWSKeyManagementServicePowerUserを付加しました。
いよいよマスターキー作成です。
KMSは単独のサービスではなく、IAMの中の「暗号化キー」にあります。
ここで一つ注意があります。
上記画面はリージョンが米国東部になっていますので、必ず東京に変更してから操作を始めてください。
手順に従い進めます。
この辺りは適当に
マスターキーの管理ユーザーを指定します。
キーの使用許可ユーザーを指定します。
私はここに、管理ユーザーと先程のCognitoの2ロールを指定しました。
プレビューして完了です。
このARNを後で使います。
Cocoapodでインストール
# Uncomment the next line to define a global platform for your project
# platform :ios, '9.0'
target 'awskmsTest' do
# Comment the next line if you're not using Swift and don't want to use dynamic frameworks
use_frameworks!
# Pods for awskmsTest
pod 'AWSKMS'
end
Cognitoによる初期化
import AWSCore
import AWSKMS
let credentialsProvider = AWSCognitoCredentialsProvider(regionType:.APNortheast1,identityPoolId:"YOUR_POOL_ID")
let configuration = AWSServiceConfiguration(region:.APNortheast1, credentialsProvider:credentialsProvider)
AWSServiceManager.default().defaultServiceConfiguration = configuration
暗号化、復号化
let str = "本日は晴天なり"
let client = AWSKMS.default()
let encrypt = AWSKMSEncryptRequest()
let data_ = str.data(using: .utf8)!
var encryptData:Data?
encrypt?.plaintext = data_
encrypt?.keyId = "YOUR KEY ID"
client.encrypt(encrypt!).continueWith { (task: AWSTask<AWSKMSEncryptResponse>) -> Any? in
let response = task.result
print(task.error ?? "(nil)")
print("Encrypted data")
print(response?.ciphertextBlob?.base64EncodedString() ?? "(nil)")
encryptData = response?.ciphertextBlob
return nil
} .waitUntilFinished()
let decrypt = AWSKMSDecryptRequest()
decrypt?.ciphertextBlob = encryptData!
client.decrypt(decrypt!).continueWith { (task: AWSTask<AWSKMSDecryptResponse>) -> Any? in
let response = task.result
print(task.error ?? "(nil)")
print("Decrypted data")
print(String(data: (response?.plaintext)!, encoding: .utf8) ?? "(nil)")
return nil
} .waitUntilFinished()
パケットキャプチャで確認
Charles使って中身を確認してみます。
これはencryptのjsonなんですが、Plaintextの「本日は晴天なり」もそのまま送っているのではないようです。
byte列を16進化しただけであればF以降の文字は出ませんし。
node.jsのソースを見てbase64エンコードと気付きました。失礼しました。
エラー、トラブル等
An error occurred (NotFoundException) when calling the Encrypt operation: Invalid arn
リージョンを全て合わせておかないとエラーになるようです。
今回は全て東京で合わせましたが、最初は米国東部で作ってしまったため発見までに時間がかかりました。
コードからマスターキーの生成が出来ない
ロールに対し権限を付与しているにも関わらず、権限が無いとのことで作成できませんでした。
この辺りは追加で調査が必要です。
おまけ:Lambdaに暗号化データを送って復号化する方法
こちらは参考記事がありました。
https://qiita.com/na0AaooQ/items/cfd9f2babd2ce604049b
https://qiita.com/Yuki_BB3/items/5a95bcef2e6d6156e749
参考
https://github.com/aws/aws-sdk-ios/issues/681
http://techtipshoge.blogspot.com/2017/08/kms.html
https://teratail.com/questions/97100