YubiKeyのワンタイムパスワードでZIPの暗号化してみた


はじめに

YubiKeyをユーザ認証以外にも使いたい!

YubiKeyの一番多い使い方は、ユーザ認証(ログイン認証など)だと思っています。
言い換えると、ユーザ認証以外の使い方を見たことがありません。

これたけ拡張性の高いYubiKeyをユーザ認証だけにしか使わないのはもったいない!
という訳で、今回はDAuthというサービスを使用して、ZIPの暗号化/UNZIPの複号にYubiKeyのワンタイムパスワード(OTP)を使ってみたいと思います。

もしYubiKeyをご存じない方は、下記のサイトをご参照ください。

YubiKeyの概要(日本語サイト)
yubico社(メーカー)

概要

YubiKeyのワンタイムパスワードを使用したZIP/UNZIPアプリケーションをBashで作ります。

準備するもの

  • YubiKey
  • インターネットに接続したPC (Webブラウザ)
  • Bashが動く環境 (私はAWS EC2のAmazon Linux2上で作りました)

構成

「YubiKeyのワンタイムパスワードの検証」、「ZIP(暗号化)に使用するパスワードの保管」等をゼロから自前で作ると大変なので、DAuthというオンライン・データベースサービスを使います。

  • ZIP/UNZIPアプリケーション : Bashで作成
  • DAuth : 「YubiKeyの検証」と「ZIP(暗号化)に使用したパスワードを保存するデータベース」として使用
  • Rakuten Rapid API : DAuthの無料トライアル版を使用するために必要

アプリケーションの作成途中で、DAuthとRakuten Rapid APIマーケットプレイスのアカウントを作ります。
本記事の範囲であれば、無料かつクレジットカード不要でアカウントを作れます。

Rakuten Rapid APIマーケットプレイスとは、開発者がAPIを検索・接続し、利用状況を管理できるAPIマーケットプレイスです。 ご自身のプロジェクトに必要なAPIを検索してアプリに埋め込み、ダッシュボードでAPIの利用状況が一括管理できます。

注意事項

このサンプルアプリケーションでZIP(暗号化)した場合、DAuthのトライアル用アカウントの期限超過、データベースから該当データを削除した場合、データをUNZIP(複号)できなくなる恐れがあります。

圧縮・暗号化前のオリジナルデータを削除しないようにしてください。

このサンプルアプリケーションの目的は、YubiKeyをログイン認証以外で使うことにあります。
セキュリティについては、利用される環境のセキュリティポリシーに合わせてご対応ください。

また、このサンプルアプリケーションの使用により生じる如何なる損害に対しても、その法的根拠に関わらず責任を負いません。自己責任の範囲でご利用ください。

DAuthとは

DAuthは、「YubiKeyと連動したクラウド上のオンライン・データベース」です。

仕組みは非常にシンプルで、KVSや連想配列のような使い方ができます。

■データベースに登録するとき

データをデータベースに登録するとき、次のものが必要になります。

  • 認証に使うYubiKeyのID (ワンタイムパスワードの先頭12桁)
  • キーワード (データベースのプライマリーキー)
  • データ (JSON)

■データを取得するとき

データベースからデータを取得するとき、次のものが必要になります。

  • 認証に使うYubiKeyのワンタイムパスワード(OTP)
  • キーワード (データベースのプライマリーキー)

YubiKeyのOTPが正しいとき、キーワードに紐付いたデータが取得できます。

アプリケーションの仕様

今回はDAuthのデータベースを下記の仕様で使います。

  • YubiKeyのID : 複号を許可するYubiKeyのID
  • キーワード : 複号するときに必要なので、ZIP後のファイル名に付ける
  • データ : ZIP(暗号化)に使用したパスワード

ZIP(暗号化)アプリケーション

▼ zip.shの処理の流れ

▼ zip.shの使い方

暗号化(zip.sh)するとき
$ ./zip.sh test.txt ccccccxxxxgrjdtlgtlglffueedttuklinncddibljiu

# 元ファイル               : test.txt
# ZIP(暗号化)されたファイル : test.txt.hcYB7lwI.zip

zip.shの第1引数に「ZIP(暗号化)するファイル名」を入力します。
第2引数に「複号を許可するYubiKeyのワンタイムパスワード(OTP)」を入力します。

ZIP(暗号化)したファイル名には、キーワード(DAuthのデータベースのプライマリーキー)を付けます。"test.txt.hcYB7lwI.zip"の"hcYB7lwI"の部分。

zip.shからDAuthのデータベースに、下記のデータを登録します。

  • YubiKeyのID : OTPの先頭12桁
  • キーワード : "hcYB71wI" スクリプト内で自動生成 (複号するとき用にファイル名に付けます)
  • パスワード : ZIP暗号化したときのパスワード。スクリプト内で自動生成

UNZIP(複号)アプリケーション

▼ unzip.shの処理の流れ

▼ unzip.shの使い方

複号(unzip.sh)するとき
$ ./unzip.sh test.txt.hcYB7lwI.zip ccccccxxxxgrgnkthelculjkufbcnhhuucddhhcebdgu

unzip.shの第1引数に「UNZIP(複号)するファイル名」を入力します。
第2引数に「複号許可されたYubiKeyのOTP」を入力します。

unzip.shはDAuthからパスワードを取得するために、OTPとキーワード(ファイル名から抽出 "hcYB71wI")を送ります。
OTPの検証結果が正しく、かつ認可されたYubiKeyだった場合、キーワードに紐付いたデータ(パスワード)が返ります。

そのパスワードで、ZIPデータを解凍・複号します。

アプリケーションの作り方

DAuthドキュメントサイトにあるチュートリアルを行ってください。

Step 1. DAuth APIを使ってみる
Step 2. ZIP暗号/複合アプリを作ってみる(bashスクリプト)

DAuthのアカウントを既に持っている場合は、Step 1は省略できます。

※プログラムはGitHubでも公開されています。
GitHub - dauth-yubikey-zip-bash

Macで"zip.sh"を作ったときに、乱数生成部分でハマったので対応方法を記載します。

zip.sh
#!/bin/bash# Usage : zip.sh source.txt otp# ここの値を入れ替える    
# tr -dc 'abcdefghijkmnpqrstuvwxyz'
APIKEY=XXXXXXXXXXXXXXXX  # <- 自分のAPIキーを入力してください
RAPIDKEY=XXXXXXXXXXXXXX  # <- 自分のRAPID APIキーを入力してください# ランダム文字生成
PASSWORD=$(LC_CTYPE=C tr -dc 'A-Za-z0-9#%@&()' < /dev/urandom | fold -w64 | head -n 1)
KEY=$(LC_CTYPE=C tr -dc 'A-Za-z0-9' < /dev/urandom | fold -w8 | head -n 1)ZIPFILE=${1}
OTP=${2}
KEYID=${OTP::12}# call DAuth API# Rapid
RESULT=$(curl \
  -X POST \
  -s \
  -H "X-DAUTH-API-KEY:${APIKEY}" \
  -H "x-rapidapi-key: ${RAPIDKEY}" \
  -H "Content-Type: application/json" \
  -d '{"device_id":"'${KEYID}'", "key":"'${KEY}'", "value":"\"'${PASSWORD}'\""}' \
  'https://dauth-trial.p.rapidapi.com/v1/dkvs' \
)# Error check
if [ "`echo ${RESULT} | grep 'errors'`" ] ; then
  echo "Error!!"
  echo "`echo ${RESULT} | jq -r '.errors[0].message'`"
  exit 1
fi# zip
zip -e --password=${PASSWORD} ${ZIPFILE}.${KEY}.zip ${ZIPFILE}

動作確認

"test.txt"をZIP(暗号化)し、UNZIP(復号)してみます。

$ ls
test.txt  unzip.sh  zip.sh

# 暗号化(zip.sh)
$ ./zip.sh test.txt ccccccxxxxgrjdtlgtlglffueedttuklinncddibljiu
adding: test.txt (stored 0%)

# "test.txt.hcYB7lwI.zip"がZIP(暗号化)されたファイル
$ ls
test.txt  test.txt.hcYB7lwI.zip  unzip.sh  zip.sh

# オリジナルファイルを退避
$ mv test.txt test.txt.org
$ ls 
test.txt.hcYB7lwI.zip  test.txt.org  unzip.sh  zip.sh

# 複号(unzip.sh)するとき
$ ./unzip.sh test.txt.hcYB7lwI.zip ccccccxxxxgrgnkthelculjkufbcnhhuucddhhcebdgu
Archive:  test.txt.hcYB7lwI.zip
 extracting: test.txt                

# "test.txt"がUNZIP(複号)されたファイル
$ ls
test.txt  test.txt.hcYB7lwI.zip  test.txt.org  unzip.sh  zip.sh

参考

おわりに

DAuthはオンライン・データベースサービスです。
「YubiKeyを使ったユーザ認証サービス」と違い、ユーザという概念がありません。
もちろん、「ログインの他要素認証」を簡単に作ることもできますが、それ以外の目的でも自由に使えます。

今回は、ZIP(暗号化)のパスワードをYubiKeyのワンタイムパスワードにしてみましたが、DAuthを使えば

  • ワークフローのハンコ代わりにYubiKeyを使う
  • システムのメンテナンスをするときに、管理者に遠隔でYubiKeyで許可をもらう多人数?認証

など、いろいろなことが出来そうです。

「YubiKeyをユーザ認証以外にも使いたい!」
「簡単に自分のプログラムに組み込みたい!」

という方は、ぜひ一度DAuthを試して頂けたら幸いです。