シリアル化インターフェース—その危険なドキュメント

提供:Dev Guides
Itsdangerous/docs/1.1.x/serializer
移動先:案内検索

シリアル化インターフェース

署名インターフェイスは文字列にのみ署名します。 他のタイプに署名するために、SerializerクラスはPythonのjsonモジュールと同様のdumps / loadsインターフェースを提供します。このインターフェースは、オブジェクトを文字列にシリアル化してから、 。

dumps()を使用して、データをシリアル化して署名します。

from itsdangerous.serializer import Serializer
s = Serializer("secret-key")
s.dumps([1, 2, 3, 4])
b'[1, 2, 3, 4].r7R9RhGgDPvvWl3iNzLuIIfELmo'

loads()を使用して署名を検証し、データを逆シリアル化します。

s.loads('[1, 2, 3, 4].r7R9RhGgDPvvWl3iNzLuIIfELmo')
[1, 2, 3, 4]

デフォルトでは、データはJSONにシリアル化されます。 simplejsonがインストールされている場合は、組み込みのjsonモジュールよりも優先されます。 この内部シリアライザーは、サブクラス化することで変更できます。

署名の経過時間を記録して検証するには、タイムスタンプによる署名を参照してください。 URLで安全に使用できる形式にシリアル化するには、 URL Safe Serialization を参照してください。

すべてのクラスはsalt引数も受け入れます。 通常、暗号化でソルトについて考える場合、レインボーテーブルのルックアップを防ぐ方法として、ソルトは結果の署名された文字列と一緒に格納されるものであると予想されるため、名前は誤解を招く可能性があります。 このような塩は通常公開されています。

itsDangerousでは、元のDjango実装と同様に、saltは異なる目的を果たします。 名前空間として説明できます。 秘密鍵がないと攻撃者の助けにならないため、開示しても重要ではありません。

署名したいリンクが2つあるとしましょう。 システムには、ユーザーアカウントをアクティブ化できるアクティブ化リンクがあり、ユーザーのアカウントを電子メールで送信する有料アカウントにアップグレードできるアップグレードリンクがあります。 どちらの場合も、署名するのがユーザーIDだけの場合、ユーザーはアクティベーションリンクのURLの可変部分を再利用して、アカウントをアップグレードできます。 これで、署名する情報をそこに追加することができます(意図:アップグレードまたはアクティブ化など)が、さまざまなソルトを使用することもできます。

from itsdangerous.url_safe import URLSafeSerializer
s1 = URLSafeSerializer("secret-key", salt="activate")
s1.dumps(42)
'NDI.MHQqszw6Wc81wOBQszCrEE_RlzY'
s2 = URLSafeSerializer("secret-key", salt="upgrade")
s2.dumps(42)
'NDI.c0MpsD6gzpilOAeUPra3NShPXsE'

2番目のシリアライザーは、ソルトが異なるため、最初のシリアライザーでダンプされたデータをロードできません。

s2.loads(s1.dumps(42))
Traceback (most recent call last):
  ...
itsdangerous.exc.BadSignature: Signature "MHQqszw6Wc81wOBQszCrEE_RlzY" does not match

同じソルトのシリアライザーのみがデータをロードできます。

s2.loads(s2.dumps(42))
42

失敗への対応

例外には、署名チェックが失敗した場合にペイロードを検査できる便利な属性があります。 この時点で誰かがあなたのデータを改ざんしていることがわかっているので、これは特に注意して行う必要がありますが、デバッグの目的には役立つ可能性があります。

from itsdangerous.serializer import Serializer
from itsdangerous.exc import BadSignature, BadData

s = URLSafeSerializer("secret-key")
decoded_payload = None

try:
    decoded_payload = s.loads(data)
    # This payload is decoded and safe
except BadSignature as e:
    if e.payload is not None:
        try:
            decoded_payload = s.load_payload(e.payload)
        except BadData:
            pass
        # This payload is decoded but unsafe because someone
        # tampered with the signature. The decode (load_payload)
        # step is explicit because it might be unsafe to unserialize
        # the payload (think pickle instead of json!)

属性を調べて何が正確に間違っているのかを突き止めたくない場合は、loads_unsafe()を使用することもできます。

sig_okay, payload = s.loads_unsafe(data)

返されるタプルの最初の項目は、署名が正しいかどうかを示すブール値です。


API