音波通信 Quiet を使った認証サーバ構築

# 音波通信 Quiet とは
電磁波の波形を使って無線通信を行うように，音波の波形を使って情報伝達を行う仕組み．
可聴域の音波（audible）の他，超音波（ultrasonic）を選ぶこともできる．
詳しくは[本家 Quiet Modem Project](https://github.com/quiet/) を参照．
JavaScript や，C 言語，Android NDK 用，など様々な環境で利用できる．


# なぜ使うのか
勤務先の Web サービスで「ある時刻にある場所にいることを保証したい」という要望があった．
Web ブラウザから取得した GPS だとクライアントが偽装ができるし，
その場所でパスワードを通知をすると打ち込んでもらう手間がかかる．
ということで，Web サービス側から通知したワンタイムパスワードを
Web ブラウザから音波にしてもらい，こちらが用意したデバイスで受け取ることにした．


# Web 版の使い方
詳しくは [quiet-js](https://github.com/quiet/quiet-js) を参照．
ここではデモ用の Web サーバを立ててサンプルページを表示するまでを解説．
※本番環境ではちゃんとした方法で Web サーバを起動をしてください．
git，npm，node などのコマンドのインストールは OS に依存するので別途調べてほしい．
ターミナル（shell）で以下のコマンドを実行．

```shell
cd ~/
git clone https://github.com/quiet/quiet-js
cd quiet-js/
npm init
npm install http-server
node node_modules/http-server/bin/http-server
```

この状態で以下のページにアクセスするとサンプルページが見られる
[送信用サンプル http://127.0.0.1:8080/examples/text/sendtext.html](http://127.0.0.1:8080/examples/text/sendtext.html)
[受信用サンプル http://127.0.0.1:8080/examples/text/receivetext.html](http://127.0.0.1:8080/examples/text/receivetext.html)
受信用ページでマイク使用の許可をした上で，
送信用ページのテキストボックスに文字を入れ「Send」ボタンを押すと音が流れる．
受信用ページを見て，書き込んだ文字が表示されていれば成功．
可聴音ではなく超音波を使いたい場合は，quiet-js/examples/text/sendtext.html と quiet-js/examples/text/receivetext.html の

```html
<div class="hidden" data-quiet-profile-name="audible"></div>
```

となっている部分を

```html
<div class="hidden" data-quiet-profile-name="ultrasonic"></div>
```

とすればよい．
両 Web ページを参考に用途に合わせたカスタマイズをすれば良い．
私の使い方では，「Send」ボタンを押すとサーバから受け取ったワンタイムパスワードを送るように変更した．


# ネイティブプログラムの使い方
C 言語版のプログラムを Ubuntu Linux のマシンで実行する．

## デバイスを調達
今の所 [Raspberry Pi](https://www.amazon.co.jp/dp/B07F5WTG3Y/?linkCode=ll1&tag=ayanami06-22&linkId=4a9321eaa46afb84ee9afee263dea630) か [Intel Compute Stick](https://www.amazon.co.jp/dp/B00W7KAABK/?linkCode=ll1&tag=ayanami06-22&linkId=9aaf7932097e2dac1265f7e53edb6158) のような，
安価で小型な PC をサーバにする予定．
φ3.5mm のマイクを USB に変換してつなぐことをおすすめ．
どうも Linux で USB マイク直挿しすると Quiet プログラム(正確には Quiet が依存している PortAudio)が誤認識する．
USB に変換するデバイスはジャックの形状（極）に注意が必要．
マイクと形状が合わないと正しく使えない．
【3 極(TRS)に対応する変換デバイス】
[Plugable USB-AUDIO](https://www.amazon.co.jp/dp/B00NMXY2MO/?linkCode=ll1&tag=ayanami06-22&linkId=ab0219e9b0412637f7f21749b3d65809)
[UGREEN 30724](https://www.amazon.co.jp/dp/B01N41607I/?linkCode=ll1&tag=ayanami06-22&linkId=c41b6c70bd9c67768f7b75c0dd2cd786)
【4 極(TRRS)に対応する変換デバイス】
[ORICO G11 3UA](https://www.amazon.co.jp/dp/B074TG23CX/?linkCode=ll1&tag=ayanami06-22&linkId=7074e62bac37d74820d0020ad9edbc94)

## プログラムをインストール
かなりの量のプログラムをコンパイル・インストールする必要がある．

### liquid-dsp のインストール
./configure はコンパイルに必要なコマンドが有るかどうかをチェックする．
もし足りないコマンドがあれば別途インストールしてほしい．
automake や

```shell
mkdir ~/quiet/
cd ~/quiet/
git clone https://github.com/quiet/liquid-dsp.git -b devel --single-branch
cd liquid-dsp/
./bootstrap.sh
./configure
make
sudo make install
```

### libfec のインストール

```shell
cd ~/quiet/
git clone https://github.com/quiet/libfec
cd libfec/
./configure
make
sudo make install
```

### jansson のインストール

```shell
cd ~/quiet/
git clone https://github.com/akheron/jansson
cd jansson/
autoreconf -i
./configure
make
sudo make install
```

### PortAudio のインストール

```
cd ~/quiet/
wget http://www.portaudio.com/archives/pa_stable_v190600_20161030.tgz
tar xzf pa_stable_v190600_20161030.tgz
cd portaudio/
./configure
make
sudo make install
```

### quiet のインストール

```
cd ~/quiet/
git clone https://github.com/quiet/quiet
cd quiet/
./bootstrap
cd build/
sudo make install
```

## プログラムの起動
ターミナルから以下のコマンドを打つことで可聴音を待つ．
超音波にしたければ audible ではなく ultrasonic にする．

```
quiet_decode_soundcard audible
```

## プログラムのデーモン化
systemd を使って，デバイスに電源が入った後に自動でプログラム起動するようにして完成．
ただし最初から入っている quiet_decode_soundcard は，受け取った文字を標準出力に出すだけなので，
認証で使うには少々使いにくい．
適宜，quiet.git の programs/decode_soundcard.c を編集したり，
シェルスクリプトなどから呼び出したりして起動する．
私は入力が途切れてから 1 秒後に受け取った文字を解析し，
次のプログラムが Web サーバに送信するというスクリプトを用意した．

```
# /etc/systemd/system/quiet.service
[Unit]
Description=Photobes Quiet Decoder
After=network.target

[Install]
WantedBy=multi-user.target

[Service]
Type=simple
User=hoge
Group=fuga
WorkingDirectory=/home/hoge/
ExecStart=/path/to/shell.sh 
ExecReload=
ExecStop=/bin/kill -SIGINT ${MAINPID}
KillSignal=SIGINT
Restart=on-failure
RestartSec=5
```