スクリプトのお勉強 技術

暗号モードによる処理時間の違いを測定してみた

投稿日:2019年6月5日 更新日:

はじめに

前回、AESで暗号化する実装をしてみた際、知らない暗号モードが増えたなと思いました。

なので、どの暗号モードを使用すべきかの、判定材料の一つとして、代表的な暗号モードの処理速度を簡単に計ってみようと思いました。

測定する暗号モード

測定する暗号モードは以下にしました。

  • CTR
  • GCM
  • OCB

選んだ理由を以下に説明します。

CTR

暗号のみを行う暗号モードで、一番取り回しが効いて、使いやすいと思ったため選びました。

GCM

暗号/認証を行う暗号モードです。SSL/TLSの暗号化にも、使われる暗号モードなので、比較的メジャーだと思います。

OCB

これも暗号/認証を行う暗号モードです。ただ、これの特許はアメリカが持っているそうです。
ただし、フリーソフトとして使用できるオープンライセンス、だそうですので、サンプルを作るのはいいですが、ちょっと仕事では使いにくいかなと思います。

GCMと明瞭な速度の違いとかがあるのか?という興味の元、測定してみます。

測定に使用したサンプルコード

サンプルコード

  • 各処理を1000000回回した処理時間を計測しています。
  • VM上で動作させたため、絶対的な処理時間そのものは、あまり意味がありません。あくまで相対的な処理時間として見てください。
  • 動作環境は前回と同じです。
from Cryptodome.Cipher import AES
from hashlib import sha256
import random


import time

def start_time():
    return time.time()


def end_time(start_time, message):
    end_time = time.time()

    # 経過時間を表示
    elapsed_time = end_time - start_time
    print("{} 経過時間(s):{}".format(message, elapsed_time))


def generate_random_secret_key(algorithm_func=sha256):
    return algorithm_func(str(random.random).encode('utf-8')).digest()


# CTR
def ctr_encrypt(secret_key, raw_data):
    crypto = AES.new(secret_key, AES.MODE_CTR)
    return dict(content=crypto.encrypt(raw_data),
                nonce=crypto.nonce)


def ctr_decrypt(secret_key, encrypted_data):
    """ encrypted_data = dict(content, nonce) """
    crypto = AES.new(secret_key, AES.MODE_CTR, nonce=encrypted_data['nonce'])
    return crypto.decrypt(encrypted_data['content'])


def ctr_encrypt_and_decrypt(secret_key, raw_data):
    encrypted_data = ctr_encrypt(secret_key, raw_data.encode())
    return ctr_decrypt(secret_key, encrypted_data)


# GCM
def gcm_encrypt(secret_key, raw_data):
    crypto = AES.new(secret_key, AES.MODE_GCM)
    content, tag = crypto.encrypt_and_digest(raw_data)
    return dict(content=content, nonce=crypto.nonce, tag=tag)


def gcm_decrypt(secret_key, encrypted_data):
    crypto = AES.new(secret_key, AES.MODE_GCM, nonce=encrypted_data['nonce'])
    return crypto.decrypt_and_verify(encrypted_data['content'], encrypted_data['tag'])


def gcm_encrypt_and_decrypt(secret_key, raw_data):
    encrypted_data = gcm_encrypt(secret_key, raw_data.encode())
    return gcm_decrypt(secret_key, encrypted_data)


# OCB
def ocb_encrypt(secret_key, raw_data):
    crypto = AES.new(secret_key, AES.MODE_OCB)
    content, tag = crypto.encrypt_and_digest(raw_data)
    return dict(content=content, nonce=crypto.nonce, tag=tag)


def ocb_decrypt(secret_key, encrypted_data):
    crypto = AES.new(secret_key, AES.MODE_OCB, nonce=encrypted_data['nonce'])
    return crypto.decrypt_and_verify(encrypted_data['content'], encrypted_data['tag'])


def ocb_encrypt_and_decrypt(secret_key, raw_data):
    encrypted_data = ocb_encrypt(secret_key, raw_data.encode())
    return ocb_decrypt(secret_key, encrypted_data)


if __name__ == "__main__":
    key = generate_random_secret_key()

    raw_data = 'raw_test_data'
    t = start_time()
    for i in range(100000):
        decrypted_data = ctr_encrypt_and_decrypt(key, raw_data)
    end_time(t, 'MODE_CTR')
    print(decrypted_data)

    t = start_time()
    for i in range(100000):
        decrypted_data = gcm_encrypt_and_decrypt(key, raw_data)
    end_time(t, 'MODE_GCM')
    print(decrypted_data)

    t = start_time()
    for i in range(100000):
        decrypted_data = ocb_encrypt_and_decrypt(key, raw_data)
    end_time(t, 'MODE_OCB')
    print(decrypted_data)

測定結果

モード 平均[s]
CTR 4.29
GCM 24.92
OCB 14.92

ということで、暗号+認証モードは、暗号のみのモードに比べて、5倍ほど処理時間がかかるようです。
OCBとGCMではOCBのほうが早いようです。

測定時出力

以下が測定時の出力です。なんとなく3回行ってみました。

$ python3 aes_encrypt_mode.py
MODE_CTR 経過時間(s):4.257887125015259
b'raw_test_data'
MODE_GCM 経過時間(s):23.77862286567688
b'raw_test_data'
MODE_OCB 経過時間(s):15.00019884109497
b'raw_test_data'
$ python3 aes_encrypt_mode.py
ODE_CTR 経過時間(s):4.250228404998779
b'raw_test_data'
MODE_GCM 経過時間(s):26.86670160293579
b'raw_test_data'
MODE_OCB 経過時間(s):15.084097862243652
b'raw_test_data'
$ python3 aes_encrypt_mode.py
MODE_CTR 経過時間(s):4.365018606185913
b'raw_test_data'
MODE_GCM 経過時間(s):24.15635585784912
b'raw_test_data'
MODE_OCB 経過時間(s):14.68250060081482
b'raw_test_data'

サンプルソース

ここに、上記のソース、及び関連のソースを置いてあります。

おわりに

思ったより暗号+認証モードは処理時間がかかるのが分かりました。

何かの参考にしてください。

-スクリプトのお勉強, 技術

執筆者:

関連記事

pipenv + Apache + Django起動設定

仕事でwebアプリケーションを作成しています。 Djangoで作成し、webサーバをApache、環境をpipenvで設定したpython3環境上で動かす予定です。 Apacheが起動するまでに、苦労 …

FastAPIでAPIを作ってみる(その1)

勉強として、FastAPIを使用して、実際にAPIを作成し、起動しようと思います。目標としては、本番運用用の設定まで行いたいと思います。 FastAPIとは FastAPIとは、Pythonによる、W …

seaborn + Pandas + Python によるグラフ描画(その1: 準備編)

グラフ描画してみよう 今現在の仕事で、グラフ描画する可能性があるので、少し練習してみようと思います。 題材について 突然ですが、私は確定拠出型年金に加入しています。証券会社はSBI証券 にしています。 …

@nifty auひかり タイプVからタイプGに変えてみた

家のインターネットはいままで、光回線ではありましたが、昔のVSDLのままでした。auひかりでいう、マンション タイプVというやつです。 それを近年、リモートワークが増えていることや、半導体需要がなんと …

WSL2にOpenCV + Pythonをインストールする

お手軽にやろうと思ってやってみました。作業手順自体を見ると、お手軽ではないかもしれません。 環境 インストールする/した環境は以下の通りです。 WSL2Ubuntu 20.04.2 LTSPython …

google オプトアウト Click here to opt-out.