DUKPTとは何か？

# DUKPT (Delivered Unique Key Per Transaction)

`DUKPT` は `ANSI` にて制定されている暗号鍵の運用についての仕様です。
「ディーユーケーピーティー」とか「ダックプット」などと呼ばれています。
クレジットカードを利用する際に、本人確認のために `PED`（決済端末）に `PIN` （暗証番号）を入力する場合がありますが、この `PIN` を安全にバックエンドに送信するための暗号化仕様です。
この `DUKPT` ですが、日本語で、且つ、開発者目線で踏み込んだ説明をしているものが少なく、運用イメージもつかないので、メモ書き的な感じでまとめてみました。

実際のサンプルコードは下記にアップロードしています。（古いコードなので、もうちょい最適化できますが雰囲気は読めると思います）

https://github.com/CODIANZ/dukpt


## 登場人物

### BDK (Base Derivation Key)

128bit

絶対に漏れてはいけない鍵です。
乱数のシード的な役割で、任意に指定します。
一般的には `HSM` (Hardware Security Module) に格納され、`HSM`から外に出ることはありません[^1]。
また、運用に入ったら余程のセキュリティ障害が無い限り更新されることもないでしょう。

[^1]: エクスポート機能がある場合でも、必ず何らかの暗号化を施してから外に出ます。

### KSI (Key Serial Identification)

40bit

任意に指定します。
一般的には `PED` の機種毎に数値を設定するようです。


### DID (Device ID)

19bit

任意に指定する。
一般的には `PED` の固有番号（例えばシリアル番号）が振られます。
すなわち、`PED` 毎に異なる値となります。
これで約５２万台の`PED`を賄えることになります。


### CTR (Transaction Counter)

21bit

トランザクション毎にインクリメントされる値です。
約２００万回でグルリンパします。[^2]
暗号化においては数値として扱われず、21ビットの各ビットを後述する `Future Key` の配列を参照するフラグとして機能します。

[^2]: その際は、新しい `IPEK` と `IKSN` がインジェクションされるのですが、２００万回の `PIN` 入力よりも `PED`の寿命が先に訪れる思いますので、一般的には故障対応をすることになります。


### KSN (Key Serial Number)

80bit

KSN = `KSI` + `DID` + `CTR`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1038343/0f6edb06-accb-22af-e10a-e09e6f06393f.png)

### IKSN (Initial Key Serial Number)

80bit

`KSN` のうち、`CTR` がゼロのもの。
この `IKSN` を `PED` (Pin Entry Device) にインジェクションします。


### IPEK (Initial PIN Encryption Key)

128bit

`BDK` と `KSI` と `DID` を使って生成されるハッシュ値[^3]です。
この `IPEK` を `PED` (Pin Entry Device) にインジェクションします。

[^3]: ハッシュ値は 3DES とビット演算（主にシフトとXOR）によって求められます。


### Future Key

128bit　x 21個

`IPEK` を元にビット演算を行い生成される21個のハッシュ値です。
`PED` は `IPEK` がインジェクションされるとこの21個の `Future Key` を生成し、セキュア領域に保存される。 インジェクションされた `IPEK` は `PED` から破棄されます。


## 流れ

### 1. `BDK` を格納

一般的には `HSM` に `BDK` をインジェクションします。
この `BDK` の取り扱いには十分注意しましょう。


### 2. `KSI` と `DID` を決定

先述のとおり任意の値を決めます。


### 3. `IPEK` を生成

`BDK` と `KSI` と `DID` で生成します。
一般的には `HSM` に `KSI` と `DID` を入力し、`HSM`内部で `BDK` を絡めた演算が施され `IPEK` を取得します。


### 4. `PED` の設定

`IPEK` と `IKSN` をインジェクションします。
`IPEK` は `Future Key` を２１個生成しセキュア領域に保存した後、破棄されます。
`IKSN` は セキュア領域に保存します。
インターネット網を介してインジェクションすることは稀で、基本的には工場出荷時やキッティング時に行われます。


### 5. `PIN` を暗号化

`PIN` が入力された後、これを暗号化します。

#### 5-1. `CTR` をインクリメント

この `CTR` がインクリメントすることで後述する `PIN` を暗号化する鍵が演算によって変化します。

#### 5-2. 暗号化する鍵を生成

`CTR` の各ビット番号が `Future Key` の配列に対応してます。
`CTR` のビットを順に走査します。２１ビットなので２１回走査します。
ビットが１の場合、そのビット番号の `Future Key` をビット演算します。
これを繰り返して`暗号鍵`となります。

#### 5-3. `PIN` を暗号化

`PIN` を 5-2 で生成した`暗号鍵`を使って `3DES` で暗号化します。

#### 5-4. 情報をバックエンドへ送信

5-3で生成した暗号文と `KSN` をバックエンドへ送信します。

### 6. バックエンドで復号化

`KSN` には `KSI` と `DID` が含まれているので、 `BDK` を絡めて `IPEK` を生成します。
`IPEK` を生成すれば `Future Key` を生成することができます。
この `Future Key` と `CTR` を使って暗号鍵を生成します。
そして、暗号文を復号します。

バックエンド側には `BDK` を抱えている `HSM` がありますので、材料が揃えば鍵を生成して復号化できるという訳です。


## 関係図

関係図を作成しましたので、合わせて参考にしてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1038343/694ab0be-86c0-eb28-02d6-3be8a700f867.png)


## 最後に

この暗号化はトランザクション毎に`暗号鍵`が変わるものの、本質は共通鍵暗号です。
`Future Key` （または `IPEK`）と`KSN`が漏洩すると`PIN`は保護されません。
したがって、`PCI DSS`[^4] のセキュリティ要件を満たすデバイスやシステム構成でなければ安全とは言えません。[^5]

[^4]: クレジットカード決済におけるセキュリティ要件をまとめたものです。（ https://ja.wikipedia.org/wiki/PCI_DSS ）

[^5]: 語弊がありますが `DUKPT` は `PCI DSS` の構成要素のひとつと考えても良いでしょう。