ある文字列から一方向性のパスワードを作成させたくなりました。
パスワードというか厳密にはただのハッシュで、結果の文字列を16進ではなくランダムっぽい文字列の生成を行わせようとしました。
先に結論を上げると下記のコマンドです。
seed="your_seed_string"; echo -n "$seed" | sha256sum | awk '{print $1}' | fold -2 | while IFS= read -r byte; do printf "\\$(printf '%03o' $((16#$byte % 94 + 33)))"; done | tr -d '\\' | head -c16
.k|Kz|MVNs?kwLSw
前段階としてハッシュ化してパスワードのように取り扱う場合には下記のようにしていました。
seed="your_seed_string"; echo -n "$seed" | sha256 | cut -c-16
c94a995b2ab75b2c
ただこれだと小文字16進数の範囲の文字しか出てこないため、要件を満たせないことがありました。
そこで一方向性のハッシュの結果を大文字、小文字、数字、記号を混ぜて
コマンド | 解説 |
---|---|
seed="your_seed_string"; echo -n "$seed" | 文字列の定義 |
sha256sum | ハッシュ化 |
fold -2 | 16進数で文字ごとに切り分け |
while IFS= read -r byte; do ~~ done | 文字でループ |
printf "\$(printf '%03o' $((16#$byte % 94 + 33)))"; | 文字にアスキーキャラクターの33を足し込む |
tr -d '\' | バックスラッシュを取り除く |
head -c16 | 16文字で切り出す |
途中で33を足しているところはASCIIコード表のビックリマーク(33)を基準にして下駄を履かせています。
バックスラッシュは何かとエラーになりそうだったので省いています。雑に省いているので、tr
コマンドの前に大量のバックスラッシュがあった場合には文字数が16文字未満になる恐れがあります。対処としてはprintfの中で条件分岐させるほうが良さそうですが…、まぁ実務上は問題ないかと思います。
もちろん、ランダムなパスワード生成ではなくあくまでハッシュなので取り扱いには十分注意してください。