オートインクリメントの次の数を推測しづらくする
1, 2, 3 ... という連番は欲しいが次の値を予測されたくないという場合に使います
内部的に連番のほうが都合良いが、公開時に順番を推定されたくないみたいな状況で必要になりました
例えばなんらかのアカウントを作ってもらいWEB上で公開した際に、あるアカウントがあるアカウントよりも前に受付していた事が連番から推測できてしまうのは都合が悪いとか、そういう時でしょうか
連番をそのままIDにしていた場合も同様に有効かと思います
1, 2, 3 ...という連番に対になる文字列IDを作成し解決します、文字列IDは重複しないようにします
例
0 123b96289d60a4406c550344a9467d74
1 633a6e85bdb2f38d125926262ff130e7
2 dbfda7e1043de7cd0e6b5fc1b5fe58cc
3 25b3353632481f4bd9cc66bedc8515c2
4 67ffdb572ef73bec7ab1b6bc04548e60
5 4b115c6476fdb8205910e653ecb1b256
6 4c9573cc046b7f37779d29e7ede02c89
7 4574acb57236c314642c24e73ef5dc7f
8 14d909a39cc8e9ef91fff8084c22a6bd
9 a697cf2af85a935914215124eeb6dec7
ソースコード
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
import os
def encrypt(key, counter) -> bytes:
cipher = Cipher(algorithms.AES(key), modes.ECB())
encryptor = cipher.encryptor()
# ECBモードなので16バイト単位にしなければいけない
counter_bytes = counter.to_bytes(16, byteorder='big')
encrypted = encryptor.update(counter_bytes)
return encrypted
# 使用例
# key = os.urandom(16) # ランダムな鍵
# 以下のバイト列は実装毎に作り直しが必要、各々実装する際に作り直すこと
key16 = b'gp\x8c\xdc\x86\xf2\x9e\x1b\x123\x86\xafD/\x13`'
key24 = b'\xd7v\xd2\xd6Q\xec\xaeZ\xb3]z4\r8\x9e\x8c\xa1\xde\xb6\xc9T\xd3\x0b\xa5'
key32 = b'\xe5\xb1#\x81N\xfe\xe5%\xa63\xbe#\xbc[7`\r\xcc\x02\x07[\xc7\xbf`H\x9c\xe9\x19\xff\xeb\xdc\xa6'
key = key16 # 16, 24 ,32, のどれでも良い
for i in range(10): # 最初の10個を取得
bin = encrypt(key, i)
print(i, bin, bin.hex())
# bin.hex() を ID として使用する
注意点
Cipher 第二引数のモードが ECB だと厳密には次の数字が推測される可能性があるため
modes.CTR を利用すると更に推測しづらくなりますが、事前にクライアントと暗号を共有する等の手間があります、modes.CTR 用の暗号を内部で保持する等工夫でなんとかなるかもですが...
モードについてはこちらを参考に調べました
共通鍵暗号の暗号モード CTRについて