CarotDAVの暗号化について

Last modified on Mar 31 2017.

CarotDAVの暗号化についての仕様です。

概要

CarotDAVで用いられている暗号化の仕様をまとめたものです。

リソース名の暗号化

ここではCarotDAVが生成する暗号化リソースの名称の暗号化について説明します。

暗号化手順

リソース名は以下のように暗号化されます。

  1. UTF-8エンコード

    リソース名はUTF-8でエンコードされたbyte列(resource_string)に変換されます。 この時、URIのパーセントエンコードなどは全てデコードされた状態とします。

  2. 暗号化

    resource_stringが暗号化アルゴリズムのブロック長以内の場合、0パディングした上で暗号化され、暗号化byte列(cipher_octet)になります。 ブロック長を超える場合はCipher Text Stealing (CTS) モードで暗号化されます。

  3. 変形Base64エンコード

    暗号化されたcipher_octetは変形Base64エンコードされます(base64_string)。 Base64との違いは「+」を「_」に、「/」を「-」に、末尾の「=」を省略することです。 これはmodified Base64 for URLと呼ばれている物とは異なります

  4. ヘッダー付与

    暗号化ファイルを識別するためのヘッダーをbase64_stringの前に付与し、暗号化リソース名(encrypt_resource_string)とします。

復号は逆の手順で行います。 ブロック長以内の場合は復号後、末尾に0がパディングされているので、末尾の0を削除します。

ヘッダー

ヘッダーはリソースが暗号化されてるかを示す、使われにくい文字列です。 現状では"^_"、":D"、";)"、"T-T"、"orz"、"ノシ"、"(´・ω・)"の7種類から使用者が選びます。

暗号化アルゴリズム

暗号化アルゴリズムは下記を用います。

アルゴリズム
AES
鍵長
256bit
ブロック長
128bit
鍵/初期化ベクター生成
PBKDF2 HMAC-SHA1

saltには「CarotDAV Encryption 1.0 」の24byteを用います(全ての空白含む)。 iterationは1024回。 PBKDF2の出力の最初の32byteをAESの鍵に、次の16byteを初期化ベクターとします。

効率

Base64はおおよそ約133%、CTSは100%のため、encrypt_resource_stringはresource_stringのおおよそ133%の長さになりますが、 URIでは非アスキー文字がパーセントエンコーディングされる為、 転送の際には暗号化したほうが効率よくなる場合があります。

例えば漢字・ひらがな等、UTF-8で3byte必要な文字列からなる名称の場合、 UTF-8とパーセントエンコーディングで「文字数 x 3 x 3」byte必要になりますが、 暗号化ファイル名では「ヘッダー(2byte) + 文字数 x 3 x 4/3」byteとなり、かなり小さくなります。

問題点

大文字・小文字を保存できないファイルシステムの場合は復号できない。

modified Base64 for URLを使うべきだった。

今後バージョンを変える際にバージョンの認識が簡単ではない。

パスワードが同じであるかぎりAESの暗号化鍵が同一となり、同じファイルを暗号化した時に同一の暗号文になるため、辞書攻撃への耐性が低い。 しかし同じ内容のコンテンツが同じ暗号文にならない手法はストレージの最適化等の際に問題になる可能性があるため為見送った。

コンテンツの暗号化

ここではCarotDAVが生成する暗号化リソースのファイル構造について説明します。

ファイル構造

暗号化されたファイルは先頭から順に以下のような構造になります。

ヘッダー(64byte)

リソースの先頭には「CarotDAV Encryption 1.0 」の24byteがあります。 のこりの40byteは未使用です。

これはリソースが暗号化されてるかどうか、その暗号化フォーマットのバージョン番号を示します。 現在は「CarotDAV Encryption 1.0 」しかありません。

暗号化byte列(任意長)

元のファイルをCipher Block Chaining(CBC)モードで暗号化した暗号化byte列です。 長さはブロック長の整数倍になります。

パディング(1~ブロック長)

元のファイルの長さを計算するためのパディングです。 以下の式で計算します。

((元のファイルの長さ - 1) Mod ブロック長 ) +1

これにより、暗号化ファイルの長さは元のファイルの長さにブロック長と128byteを足した値になります。

ハッシュ(64byte)

ハッシュは「元のファイル」のハッシュを16進表記したものです。 大文字・小文字は区別しません。 ハッシュ関数としてSHA-256を用います。

復号後このハッシュと照合し、一致しない場合はファイル破損を通知します。

暗号化アルゴリズム

暗号化アルゴリズムは下記を用います。

アルゴリズム
AES
鍵長
256bit
ブロック長
128bit
鍵/初期化ベクター生成
PBKDF2 HMAC-SHA1

saltには「CarotDAV Encryption 1.0 」の24byteを用います(全ての空白含む)。 iterationは1024回。 PBKDF2の出力の最初の32byteをAESの鍵に、次の16byteを初期化ベクターとします。

問題点

CTSモードを使えばパディングを用意する必要はなかった。

パスワードが同じであるかぎりAESの暗号化鍵が同一となり、同じファイルを暗号化した時に同一の暗号文になるため、辞書攻撃への耐性が低い。 しかし同じ内容のコンテンツが同じ暗号文にならない手法はストレージの最適化等の際に問題になる可能性があるため為見送った。

更新履歴

2017/3/31
  • PBKDF2の疑似乱数生成関数および繰り返し回数について追記。
  • 暗号化鍵が同一となる問題に関して追記。
  • typo修正。
2014/11/12
  • 公開

参考資料

RFC3548

Base64が定義される。

Wikipedia: modified Base64 for URL

ファイル名、URIに含むときによく用いられるBase64の変種。CarotDAVでは採用していない。

FIPS PUB 197

AESの定義

RFC2898

PKCS#5。PBKDF2が定義される。

Wikipedia: Ciphertext stealing

CTSモードの解説

Wikipedia: Block cipher mode of operation

CBCモードの解説

FIPS PUB 180-4

SHA256の定義。