Redshiftのユーザー定義関数(UDF)をつくって、会員情報をソルト+ストレッチングでハッシュ化してみる

2018.01.31

こんにちは、みかみです。

はじめに

ユーザー登録のあるシステムだと、会員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-prefixstr-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

参考