この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
こんにちは、みかみです。
はじめに
ユーザー登録のあるシステムだと、会員IDやパスワードはアプリでハッシュ化してDBに格納するケースがほとんどだと思いますが、「今ハッシュ化していない会員IDをハッシュ化したい」「今ハッシュ化しているパスワードをソルト+ストレッチングで強化したい」などの要件がもちあがった場合、すでにDBに格納済みの会員データの更新も必要になります。
いったんDBから会員データ抜き出して、必要なところはハッシュ化して、またDBに格納して・・・だと、手間がかかるし、セキュリティ面のリスクもあるし。。
やりたいこと
- DBに格納済みの会員IDを、ソルト+ストレッチングでハッシュ化したい
- データを抜き出すことなく、DB側だけで完結させたい
- なるべく簡単に(時間をかけずに)やりたい
使うもの
- DB:Redshift
- 言語:Python、SQL
やってみた
ユーザー定義関数(UDF)を作る
Redshiftのユーザー定義関数を作成します。
他のRDBMSのストアドファンクションのようにSQLでも書けますが、RedshiftはPythonでもUDF作れます(Pythonならば、ロジック部分はDB登録前にローカル環境で動かして確認できるしv
UDF のための Python 言語のサポート | AWS Documentation
パラメータでもらった id を、ソルト(今回は、固定文字列の str-prefix と str-suffix )をつけてSHA-256でハッシュ化し、ストレッチング(とりあえず10回)して返します。
CREATE FUNCTION f_create_hush(id VARCHAR)
RETURNS varchar
STABLE AS $$
import hashlib
prefix = 'str-prefix'
suffix = 'str-suffix'
id = prefix + id + suffix
for i in range(10):
id = hashlib.sha256(id.encode()).hexdigest()
return id
$$ LANGUAGE plpythonu;
テスト用テーブルとデータを準備
会員情報テーブルを作ります。
create table test_members(
id varchar(20),
id_hush varchar(128),
name varchar(20)
);
そこに、会員IDとユーザー名データを登録します。
insert into test_members (id, name)
values
('12345678', 'mikami'),
('98765432', 'sakila'),
('67895432', 'gopher');
データを登録していない id_hush カラムには、後ほど、UDFで作成したIDのハッシュを入れる予定です。
こんなデータが入りました。
dev=# select * from test_members;
id | id_hush | name
----------+---------+--------
98765432 | | sakila
12345678 | | mikami
67895432 | | gopher
(3 行)
会員IDのハッシュ値をテーブルに格納
先ほど準備した会員情報テーブルに、ソルト付きハッシュ値をストレッチングしたIDを加えます。
dev=# update test_members set id_hush = f_create_hush(id);
UPDATE 3
データを確認してみると・・・
dev=# select * from test_members;
id | id_hush | name
----------+------------------------------------------------------------------+--------
98765432 | 9c3e333395e6cc03041f7260302ee307b8608c7592243435b679a66f64f3732a | sakila
12345678 | 5601d1ca89fff92f0039ba96517586064b14f3631cc08d5985eb04d74e95deef | mikami
67895432 | d94ea325b6315c111441433e2e07212a45f7263a7614104a46fc6a9c20baa6d6 | gopher
(3 行)
ちゃんとハッシュIDが入りました!
おわりに
思ってたより簡単に、RedshiftのUDF作成&使用できました。
ただ、今回自分はrootで確認してます。ユーザーによっては USAGE ON LANGUAGE PLPYTHONU 権限の付与が必要とのことです。
UDF のセキュリティおよび権限 | AWS Documentation
また、今回はhashlibしか使ってませんが、使いたいPythonライブラリがRedshiftに入っていない場合には、自分でインポートする必要があるそうです。
カスタム Python ライブラリモジュールのインポート | AWS Documentation
ライブラリ自分でインポートできるのならば、ハッシュ化に限らず、Pythonで書ける処理をUDFにおまかせすることできちゃうんですね@@v