Trusted Design

Fernetの使い方

概要

Fernetはpyca/cryptographyの共通鍵暗号を実装しています。とにかく簡単に暗号/復号の処理を実現できるようになっています。FeernetはAES128ビットCBCモードで実現されており,鍵長やアルゴリズムは選ぶことができません。

Fernetで暗号化を実行すると,平文はトークンと呼ばれるオブジェクトになります。復号するときは,トークンをそのまま復号メソッドに適用します。

Fernetの面白いところは,時刻を設定することができることです。復号時に時刻を設定すると,その時刻より古い暗号文は復号することができません。これによって,時間制限のある暗号を運用することができます。

Fernetのクラス

class cryptography.fernet.Fernet(key)
メソッド 概要
generate_key() Fernetで利用する鍵を生成します。暗/復号を行うには,この鍵を利用する必要があります。
encrypt(data) Fernetの鍵を利用してdataを暗号化します。トークンと呼ばれる暗号文を取得することができます。
decrypt(token, ttl=None) 暗号文であるトークンを復号します。オプションでttlを指定すると,タイムスタンプの評価を行うことができます。
extract_timestamp(token) トークンのタイムスタンプを取得することができます

鍵の危殆化に備えて,鍵のローテーションを行うことができるMultiFernetがあります。メソッドに鍵のlistを渡して,複数の鍵を利用可能にします。

class cryptography.fernet.MultiFernet(fernets)
メソッド 概要
rotate(msg) Fernetで持っている鍵を使って,msgを再暗号化します。

復号時にエラーになった場合は,エラーが発生します。

class cryptography.fernet.InfalidToken

Fernetの仕様

Fernetの仕様については,特に知らなくても利用する分には困りません。鍵やトークンのフォーマットをここでは紹介します。

鍵のフォーマット

鍵は普通のビット列です。実際にはBase64エンコードされています。

SigningKey || EncryptionKey

このように,署名用の鍵と暗号用の鍵が単純に連結されています。署名用の鍵は,トークンに付加するHMACを生成するために利用します。

トークンのフォーマット

Fernetで暗号化処理を行うと,次のフォーマットのトークンを取得することができます。

Version || Timestamp || IV || CipherText || HMAC
  • バージョン:0x80固定
  • タイムスタンプ:暗号処理を実行した時刻。1970年1月1日UTCから現在までの経過秒数です。
  • IV:128ビットの初期化ベクトル。乱数で生成されます。
  • 暗号文:暗号文本体。
  • HMAC:バージョン,タイムスタンプ,IV,暗号文のSHA256 HMAC。

通常,トークンはいじらずにそのままの保持しておいて,復号もFernetを使えば問題ありませんが,復号処理をFernet以外で行いたい場合は,EncryptionKeyとCipherTextを取り出して,AES128ビットCBCモードであることを伝えて相手に渡せば,相手は復号できることになります。

上の仕様で書いたように,Fernet tokenにはタイムスタンプが含まれています。このタイムスタンプは,Base64をデコードすれば取得することができるため,攻撃者は暗号文は復号できなくても,暗号文が生成された時刻は取得することができます。