はじめに
- 何を作ったか:個人情報を1か所に集めず、断片に分けて別々のサーバに置き、ベンダ必要なときに必要なだけ情報を取得する仕組み(X-Roadとは違い、生データを返さずに答えだけ返す)
- この記事の範囲:仕組みの理屈ではなく、自宅の機材で実際に組んで動かすところまで。理論や攻撃への強さは別の記事に書く
- 誰向けか:分散システムや秘密計算に興味があり、手を動かして試したい人
個人情報を分散して保持、参照するシステムの教材的な立ち位置であるため、実運用は不可
全体構成
- 5台のサーバ(+操作用のWindows)で、役割を分けた構成
| 機械 | 役割 | IP | ホスト名 |
|---|---|---|---|
| Raspberry Pi Zero 2 W | hub(ビーコン・掲示板・名簿) | 192.168.0.10/24 | DPQ-hub |
| VM ①(Xubuntu) | S1、API窓口、管理操作 | 192.168.0.20/24 | DPQ01 |
| VM ②(Xubuntu) | S2 | 192.168.0.30/24 | DPQ02 |
| AlmaLinux 9(実機) | S3 | 192.168.0.40/24 | DPQ03 |
| Raspbian(実機) | S4 | 192.168.0.50/24 | DPQ04 |
| Windows | 利用者本人の端末、お店(API呼び出し) | DHCP(192.168.0.0/24) | - |
本来はセグメントを分けるべきだが、今回は動作確認のみのため、同一セグメントに各サーバを配置している
用意したもの
- ハード:Raspberry Pi Zero 2 W、Raspberry Pi 5、PC(Windowsなら何でもOK)
- ソフト:VirtualBox、Python
- パッケージ:
dpq_0.3.2-1_all.deb(Ubuntu系・Raspi)/dpq-0.3.2-1.el9.noarch.rpm(Alma)/dpqctl-windows-0.3.2.zip(Windows)
1. hub を Raspberry Pi Zero 2 W に置く
OSのインストール方法やSSHの設定方法は省略しています
時刻同期がyesになっていることを確認(ビーコンの起点が時刻で決まるため、時刻同期は必須)
pi2w@DPQ-hub:~ $ timedatectl
Local time: Wed 2026-10-07 19:06:09 JST
Universal time: Wed 2026-10-07 10:06:09 UTC
RTC time: n/a
Time zone: Asia/Tokyo (JST, +0900)
System clock synchronized: yes
NTP service: active
RTC in local TZ: no
pi2w@DPQ-hub:~ $
IP を固定する
pi2w@DPQ-hub:~ $ nmcli -f NAME,DEVICE con show
NAME DEVICE
Wired connection 1 eth0
lo lo
pi2w@DPQ-hub:~ $ sudo nmcli con mod "Wired connection 1" ipv4.method manual ipv4.addresses 192.168.0.10/24 ipv4.gateway 192.168.0.1 ipv4.dns 192.168.0.1
[sudo] password for pi2w:
pi2w@DPQ-hub:~ $ sudo nmcli con up "Wired connection 1"
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/3)
pi2w@DPQ-hub:~ $ ip a s
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host noprefixroute
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 6c:6e:07:22:7a:ed brd ff:ff:ff:ff:ff:ff
inet 192.168.0.10/24 brd 192.168.0.255 scope global noprefixroute eth0
valid_lft forever preferred_lft forever
inet6 2001:f70:bf61:5500:215d:a312:5a4:41e0/64 scope global dynamic noprefixroute
valid_lft 2591998sec preferred_lft 604798sec
inet6 fe80::58b4:db3:cec7:bac2/64 scope link noprefixroute
valid_lft forever preferred_lft forever
3: wlan0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
link/ether 2c:cf:67:a8:a0:1d brd ff:ff:ff:ff:ff:ff
pi2w@DPQ-hub:~ $
DPQをインストールする
pi2w@DPQ-hub:~ $ ls
Desktop Downloads Music Public Videos
Documents dpq_0.3.2-1_all.deb Pictures Templates
pi2w@DPQ-hub:~ $ sudo apt update && sudo apt install -y ./dpq_0.3.2-1_all.deb
Hit:1 http://deb.debian.org/debian trixie InRelease
Hit:2 http://deb.debian.org/debian trixie-updates InRelease
Hit:3 http://deb.debian.org/debian-security trixie-security InRelease
Hit:4 http://archive.raspberrypi.com/debian trixie InRelease
All packages are up to date.
Note, selecting 'dpq' instead of './dpq_0.3.2-1_all.deb'
Installing:
dpq
Summary:
Upgrading: 0, Installing: 1, Removing: 0, Not Upgrading: 0
Download size: 0 B / 37.2 kB
Space needed: 0 B / 52.3 GB available
Get:1 /home/pi2w/dpq_0.3.2-1_all.deb dpq all 0.3.2-1 [37.2 kB]
Selecting previously unselected package dpq.
(Reading database ... 121273 files and directories currently installed.)
Preparing to unpack /home/pi2w/dpq_0.3.2-1_all.deb ...
Unpacking dpq (0.3.2-1) ...
Setting up dpq (0.3.2-1) ...
Notice: Download is performed unsandboxed as root as file '/home/pi2w/dpq_0.3.2-1_all.deb' couldn't be accessed by user '_apt'. - pkgAcquire::Run (13: Permission denied)
pi2w@DPQ-hub:~ $
管理トークンを作成する(システム管理に必要なトークン)
pi2w@DPQ-hub:~ $ python3 -c 'import secrets; print(secrets.token_hex(16))' > ~/admin_token.txt && chmod 600 ~/admin_token.txt
pi2w@DPQ-hub:~ $
/etc/dpq/hub.confを編集し、取得した管理トークンを追記する
pi2w@DPQ-hub:~ $ sudo sed -i "s/^admin_token = .*/admin_token = $(cat ~/admin_to
ken.txt)/" /etc/dpq/hub.conf
pi2w@DPQ-hub:~ $
編集対象のファイルの中身
CHANGE_MEと管理トークンとを置き換える
# DPQ hub(ランダムビーコン・事前掲示板・名簿台帳・ベンダ等の公開鍵)の設定
[hub]
# 待ち受けるアドレスとポート
listen = 0.0.0.0:8700
# データの保存先(systemd の StateDirectory と合わせる)
data_dir = /var/lib/dpq/hub
# ベンダ・配送事業者の登録に使う管理トークン(必ず変更する)
admin_token = CHANGE_ME
# ビーコンの更新間隔(秒)。同意の有効期間(最大100回)= 100 × この値
beacon_interval = 3
# ビーコンの総回数(3秒間隔で 3000000 回 ≒ 104日)。使い切ったら hub を作り直す
beacon_length = 3000000
# ログの詳しさ(DEBUG / INFO / WARNING)
log_level = INFO
hubを起動する
pi2w@DPQ-hub:~ $ sudo systemctl enable --now dpq-hub
Created symlink '/etc/systemd/system/multi-user.target.wants/dpq-hub.service' → '/usr/lib/systemd/system/dpq-hub.service'.
pi2w@DPQ-hub:~ $ journalctl -u dpq-hub -f
Oct 07 19:23:23 DPQ-hub systemd[1]: Started dpq-hub.service - DPQ hub (random beacon, commit board, directory).
Oct 07 19:23:24 DPQ-hub dpq-hub[3745]: 2026-10-07 19:23:24,826 INFO dpq: ビーコ ンのチェーンを計算中(長さ 3000000)…
Oct 07 19:23:51 DPQ-hub dpq-hub[3745]: 2026-10-07 19:23:51,291 INFO dpq: ビーコ ン準備完了(26.5 秒)anchor=e58018cb8423e136…
Oct 07 19:23:51 DPQ-hub dpq-hub[3745]: 2026-10-07 19:23:51,307 INFO dpq: hub を 0.0.0.0:8700 で待ち受け開始
pi2w@DPQ-hub:~ $ curl http://127.0.0.1:8700/beacon
{"round": 35, "value": "1409fa82e4aeaec8a7a27d4885b15b246353380e88c7d6c3f7fd05684153c5e7", "anchor": "e58018cb8423e136241ba4e5a83550641dc1c81b7da08a541b0a25581f7c3c78", "interval": 3.0, "start": 1791368604.8106613}
pi2w@DPQ-hub:~ $
2. 断片サーバを各機械に置く
接続構成図
この記事ではVM①の設定手順のみ記載するが、他の機器でもすることは同じ
OSインストール、IPの固定、SSH設定などを事前に済ませておく
System clock synchronizedがyesで、NTP serviceがactiveであることを確認(以下コマンドはxubuntuの場合)
xubuntu@DPQ01:~$ timedatectl
Local time: Wed 2026-10-07 16:33:30 JST
Universal time: Wed 2026-10-07 07:33:30 UTC
RTC time: Wed 2026-10-07 07:24:23
Time zone: Asia/Tokyo (JST, +0900)
System clock synchronized: no
NTP service: inactive
RTC in local TZ: no
xubuntu@DPQ01:~$ sudo timedatectl set-ntp true
xubuntu@DPQ01:~$ timedatectl
Local time: Wed 2026-10-07 16:34:01 JST
Universal time: Wed 2026-10-07 07:34:01 UTC
RTC time: Wed 2026-10-07 07:24:28
Time zone: Asia/Tokyo (JST, +0900)
System clock synchronized: yes
NTP service: active
RTC in local TZ: no
System clock synchronizedがno、またはNTP serviceがinactiveである場合は以下コマンドを実行
sudo timedatectl set-ntp true
almalinuxの場合は、以下のコマンドでactiveが出ていればOK
[almalinux@DPQ03 ~]$ systemctl is-active chronyd
active
dpqをインストールするdpq_[バージョン]-1_all.debをサーバの任意の場所に配置し、以下コマンドを実行する
RedHat系ディストリビューションを利用する場合はdpq-[バージョン].el9.noarch.rpmを使用する
xubuntu@DPQ01:~$ ls
dpq_0.3.2-1_all.deb テンプレート ドキュメント ピクチャ 公開
ダウンロード デスクトップ ビデオ ミュージック
xubuntu@DPQ01:~$ sudo apt install -y ./dpq_0.3.2-1_all.deb
パッケージリストを読み込んでいます... 完了
依存関係ツリーを作成しています... 完了
状態情報を読み取っています... 完了
注意、'./dpq_0.3.2-1_all.deb' の代わりに 'dpq' を選択します
以下のパッケージが新たにインストールされます:
dpq
アップグレード: 0 個、新規インストール: 1 個、削除: 0 個、保留: 362 個。
37.2 kB 中 0 B のアーカイブを取得する必要があります。
この操作後に追加で 0 B のディスク容量が消費されます。
取得:1 /home/xubuntu/dpq_0.3.2-1_all.deb dpq all 0.3.2-1 [37.2 kB]
以前に未選択のパッケージ dpq を選択しています。
(データベースを読み込んでいます ... 現在 127537 個のファイルとディレクトリがインストールされています。)
.../xubuntu/dpq_0.3.2-1_all.deb を展開する準備をしています ...
dpq (0.3.2-1) を展開しています...
dpq (0.3.2-1) を設定しています ...
info: 100 から 999 の範囲でグループ ID を選択しています...
info: グループ `dpq' (グループ ID 124) を追加しています...
info: The home dir /var/lib/dpq you specified can't be accessed: No such file or directory
info: 100 から 999 の範囲でユーザーID を選択しています...
info: システムユーザ `dpq' (UID 117) を追加しています...
info: 新しいユーザ `dpq' (UID 117) をグループ `dpq' に追加しています...
info: ホームディレクトリ `/var/lib/dpq' は作成しません。
N: ファイル '/home/xubuntu/dpq_0.3.2-1_all.deb' がユーザ '_apt' からアクセスできないため、ダウンロードは root でサンドボックスを通さずに行われます。 - pkgAcquire::Run (13: 許可がありません)
xubuntu@DPQ01:~$
- dpqサーバの設定ファイルを作成する
/etc/dpq/server-{コンフィグファイルのID}.conf
xubuntu@DPQ01:~$ sudo cp /etc/dpq/server01.conf /etc/dpq/server-S1.conf
xubuntu@DPQ01:~$ sudo vim /etc/dpq/server-S1.conf
server-S1.confの中身
# DPQ 断片保管サーバの設定例
# /etc/dpq/server-<ID>.conf にコピーして編集し、
# systemctl enable --now dpq-server@<ID> で起動する
[server]
# サーバID(名簿上の名前。ファイル名の <ID> と合わせる)
id = S1
# 秘密分散の評価点(サーバごとに 1, 2, 3, ... と重複しない整数)
x = 1
# 地域(選定時に「同じ地域は1台まで」の判定に使う)
region = 札幌
# 運営事業者(名簿の変更を承認する単位。1事業者1サーバを推奨)
operator = 事業者A
# 待ち受けるアドレスとポート
listen = 0.0.0.0:8701
# 他のサーバやクライアントから見たこのサーバのURL
public_url = http://192.168.1.11:8701
# hub のURL
hub_url = http://192.168.1.10:8700
# データの保存先(systemd の StateDirectory と合わせる)
data_dir = /var/lib/dpq/server-S1
# 断片更新(dpqctl admin refresh)に使う管理トークン。hub と同じ値にする
admin_token = CHANGE_ME
# 1ベンダあたり60秒間に受け付ける照会の上限
DPQ01用に編集後のserver-S1.confの中身
# DPQ 断片保管サーバの設定例
# /etc/dpq/server-<ID>.conf にコピーして編集し、
# systemctl enable --now dpq-server@<ID> で起動する
[server]
# サーバID(名簿上の名前。ファイル名の <ID> と合わせる)
id = S1
# 秘密分散の評価点(サーバごとに 1, 2, 3, ... と重複しない整数)
x = 1
# 地域(選定時に「同じ地域は1台まで」の判定に使う)
region = R01
# 運営事業者(名簿の変更を承認する単位。1事業者1サーバを推奨)
operator = opA
# 待ち受けるアドレスとポート
listen = 0.0.0.0:8701
# 他のサーバやクライアントから見たこのサーバのURL
public_url = http://192.168.0.20:8701
# hub のURL
hub_url = http://192.168.0.10:8700
# データの保存先(systemd の StateDirectory と合わせる)
data_dir = /var/lib/dpq/server-S1
# 断片更新(dpqctl admin refresh)に使う管理トークン。hub と同じ値にする
admin_token = {ここにはhubで作成した管理用トークンを記載する}
# 1ベンダあたり60秒間に受け付ける照会の上限
rate_limit = 30
# hub と名簿を同期する間隔(秒)
sync_interval = 15
log_level = INFO
xubuntu@DPQ01:~$
server-S1.confの権限設定をする
xubuntu@DPQ01:~$ sudo chown root:dpq /etc/dpq/server-S1.conf && sudo chmod 640 /etc/dpq/server-S1.conf
xubuntu@DPQ01:~$ sudo ls -la /etc/dpq/server-S1.conf
-rw-r----- 1 root dpq 1180 Oct 7 19:29 /etc/dpq/server-S1.conf
xubuntu@DPQ01:~$
サービスを起動する
xubuntu@DPQ01:~$ sudo systemctl enable --now dpq-server@S1
Created symlink /etc/systemd/system/multi-user.target.wants/dpq-server@S1.service → /usr/lib/systemd/system/dpq-server@.service.
xubuntu@DPQ01:~$ journalctl -u dpq-server@S1 -n 5
Oct 06 19:31:41 xubuntu-VirtualBox systemd[1]: Stopped dpq-server@S1.service - DPQ share server S1.
-- Boot fb810c768797439b88dfa44b5ce87d40 --
Oct 07 19:31:07 DPQ01 systemd[1]: Started dpq-server@S1.service - DPQ share server S1.
Oct 07 19:31:08 DPQ01 dpq-server[1889]: 2026-10-07 19:31:08,516 INFO dpq: サーバ S1(x=1, R01, opA)運営鍵 78fdd719bb41ac2c…
Oct 07 19:31:08 DPQ01 dpq-server[1889]: 2026-10-07 19:31:08,565 INFO dpq: server-S1 を 0.0.0.0:8701 で待ち受け開始
Oct 07 19:31:08 DPQ01 dpq-server[1889]: 2026-10-07 19:31:08,666 INFO dpq: ビーコンの起点を記録: e58018cb8423e136…
~
~
ここから下については、DQP01のみの設定とする
/etc/dpq/api.confを編集する
# DPQ HTTP API(dpq-api)の設定
# ベンダの照会と配送事業者の引き換えを、curl などから API トークンで行うための窓口
[api]
# 待ち受けるアドレスとポート
listen = 0.0.0.0:8710
# hub の URL
hub_url = http://127.0.0.1:8700
# データの保存先(利用者・トークン・操作記録・ベンダ等の鍵)
data_dir = /var/lib/dpq/api
# 管理トークン(hub と同じ値)。API 利用者の登録と、hub へのベンダ等の公開鍵の登録に使う
admin_token = CHANGE_ME
# 管理操作(利用者の登録など)を受け付ける接続元。カンマ区切り
admin_allow = 127.0.0.1, ::1
# API トークンの有効期間(秒)の既定値と上限
token_ttl = 3600
max_token_ttl = 86400
# ログインの失敗がこの回数続いたら、この秒数だけロックする
login_max_failures = 5
login_lock_seconds = 300
# ログの詳しさ(DEBUG / INFO / WARNING)
log_level = INFO
apiサービスを起動する
xubuntu@DPQ01:~$ sudo systemctl enable --now dpq-api
Created symlink /etc/systemd/system/multi-user.target.wants/dpq-api.service → /usr/lib/systemd/system/dpq-api.service.
xubuntu@DPQ01:~$ curl http://127.0.0.1:8710/health
{"ok": true, "version": "0.3.2"}
xubuntu@DPQ01:~$
dpqctlコマンドを実行する際の環境変数をbachrcに書き込んでおく
xubuntu@DPQ01:~$ echo 'export DPQ_HUB=http://192.168.0.10:8700' >> ~/.bashrc
xubuntu@DPQ01:~$ echo 'export DPQ_ADMIN_TOKEN={管理トークン}' >> ~/.bashrc
xubuntu@DPQ01:~$ source ~/.bashrc
念のため、以下にalmalinux(DPQ03)の設定の様子も載せる
パッケージインストール
[almalinux@DPQ03 ~]$ ls
Desktop Downloads Pictures Templates dpq-0.3.2-1.el9.noarch.rpm
Documents Music Public Videos
[almalinux@DPQ03 ~]$ sudo dnf install -y ./dpq-0.3.2-1.el9.noarch.rpm
AlmaLinux 9 - AppStream 7.1 kB/s | 4.2 kB 00:00
AlmaLinux 9 - AppStream 11 MB/s | 33 MB 00:03
AlmaLinux 9 - BaseOS 6.4 kB/s | 3.8 kB 00:00
AlmaLinux 9 - BaseOS 16 MB/s | 57 MB 00:03
AlmaLinux 9 - Extras 5.8 kB/s | 3.3 kB 00:00
AlmaLinux 9 - Extras 52 kB/s | 33 kB 00:00
AlmaLinux 9 - Raspberry Pi 5.1 kB/s | 3.0 kB 00:00
AlmaLinux 9 - Raspberry Pi 3.6 MB/s | 2.8 MB 00:00
Last metadata expiration check: 0:00:01 ago on Wed Oct 7 11:11:09 2026.
Dependencies resolved.
================================================================================
Package Arch Version Repository Size
================================================================================
Installing:
dpq noarch 0.3.2-1.el9 @commandline 51 k
Installing dependencies:
python3-cffi aarch64 1.14.5-5.el9 baseos 244 k
python3-cryptography aarch64 36.0.1-5.el9_6 baseos 1.1 M
python3-ply noarch 3.11-14.el9 baseos 103 k
python3-pycparser noarch 2.20-6.el9 baseos 124 k
Transaction Summary
================================================================================
Install 5 Packages
Total size: 1.6 M
Total download size: 1.6 M
Installed size: 6.6 M
Downloading Packages:
(1/4): python3-ply-3.11-14.el9.noarch.rpm 907 kB/s | 103 kB 00:00
(2/4): python3-cryptography-36.0.1-5.el9_6.aarc 6.8 MB/s | 1.1 MB 00:00
(3/4): python3-cffi-1.14.5-5.el9.aarch64.rpm 1.3 MB/s | 244 kB 00:00
(4/4): python3-pycparser-2.20-6.el9.noarch.rpm 1.7 MB/s | 124 kB 00:00
--------------------------------------------------------------------------------
Total 2.1 MB/s | 1.6 MB 00:00
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
Preparing : 1/1
Installing : python3-ply-3.11-14.el9.noarch 1/5
Installing : python3-pycparser-2.20-6.el9.noarch 2/5
Installing : python3-cffi-1.14.5-5.el9.aarch64 3/5
Installing : python3-cryptography-36.0.1-5.el9_6.aarch64 4/5
Running scriptlet: dpq-0.3.2-1.el9.noarch 5/5
Installing : dpq-0.3.2-1.el9.noarch 5/5
Running scriptlet: dpq-0.3.2-1.el9.noarch 5/5
Verifying : python3-cffi-1.14.5-5.el9.aarch64 1/5
Verifying : python3-cryptography-36.0.1-5.el9_6.aarch64 2/5
Verifying : python3-ply-3.11-14.el9.noarch 3/5
Verifying : python3-pycparser-2.20-6.el9.noarch 4/5
Verifying : dpq-0.3.2-1.el9.noarch 5/5
Installed:
dpq-0.3.2-1.el9.noarch python3-cffi-1.14.5-5.el9.aarch64
python3-cryptography-36.0.1-5.el9_6.aarch64 python3-ply-3.11-14.el9.noarch
python3-pycparser-2.20-6.el9.noarch
Complete!
[almalinux@DPQ03 ~]$
ファイアウォールの設定をする(8701/tcpで受け付ける必要がある)
[almalinux@DPQ03 ~]$ sudo firewall-cmd --permanent --add-port=8701/tcp && sudo f
irewall-cmd --reload
success
success
[almalinux@DPQ03 ~]$ sudo firewall-cmd --list-ports
22/tcp 8701/tcp
[almalinux@DPQ03 ~]$
コンフィグファイルを作成し、サービス起動
[almalinux@DPQ03 ~]$ sudo ls /etc/dpq
api.conf hub.conf server.conf.example
[almalinux@DPQ03 ~]$ sudo mv /etc/dpq/server.conf.example /etc/dpq/server-S3.conf
[almalinux@DPQ03 ~]$ sudo vim /etc/dpq/server-S3.conf
[almalinux@DPQ03 ~]$ sudo systemctl enable --now dpq-server@S3
Created symlink /etc/systemd/system/multi-user.target.wants/dpq-server@S3.service → /usr/lib/systemd/system/dpq-server@.service.
[almalinux@DPQ03 ~]$
3. 名簿を作る
各サーバにdpqをインストール出来たら、いよいよ名簿を作成する。
以下の場合は1台攻撃されても情報が漏れることはなく、また4台のうち3台が情報照会に参加することを示す
xubuntu@DPQ01:~$ dpqctl directory init --t 1 --k 3 --distinct region --servers http://192.168.0.20:8701,http://192.168.0.30:8701,http://192.168.0.40:8701,http://192.168.0.50:8701
名簿 第1版 を掲示しました(4台、t=1, k=3, 重複禁止=region)
{
"ok": true,
"hash": "3ac74fb474dfe488bfa709972d244a8c58fb80edcac3a274bdc640a91b004f9d"
}
xubuntu@DPQ01:~$ dpqctl status
hub: http://192.168.0.10:8700 ラウンド 3264(3.0秒間隔)
S1 R01 在籍 利用者0件 epoch0 名簿第1版
S2 R02 在籍 利用者0件 epoch0 名簿第1版
S3 R03 在籍 利用者0件 epoch0 名簿第1版
S4 R04 在籍 利用者0件 epoch0 名簿第1版
xubuntu@DPQ01:~$
4. Windowsを利用者の端末にする
- Python.3.12とcryptographyをインストールする
winget install -e --id Python.Python.3.12
py -m pip install cryptography
- dpqctl-windows-[バージョン].zipを展開してC:\Users[ユーザ名]\dpqctlに展開し、そのフォルダで下記コマンドが通ることを確認する
.\dpqctl.cmd --help
apiユーザを登録する
xubuntu@DPQ01:~$ dpqctl api user add --username dpquser --role vendor --party dpqs
パスワード:
パスワード(確認):
エラー: HTTP 400: password は 8 文字以上
xubuntu@DPQ01:~$ dpqctl api user add --username dpquser --role vendor --party dpqs
パスワード:
パスワード(確認):
dpquser を登録しました(vendor / dpqs)
xubuntu@DPQ01:~$ dpqctl api user add --username dpqop --role carrier --party dpqops
パスワード:
パスワード(確認):
dpqop を登録しました(carrier / dpqops)
xubuntu@DPQ01:~$ dpqctl api user list
dpqop carrier dpqops 有効 最終ログイン - 有効なトークン 0
dpquser vendor dpqs 有効 最終ログイン - 有効なトークン 0
xubuntu@DPQ01:~$
利用者端末(Windows)からもアクセスできることを確認
名簿の参照は認証情報なしでアクセス可能
PS C:\Users\User\dpqctl> [Console]::OutputEncoding = [Text.Encoding]::UTF8
PS C:\Users\User\dpqctl> $env:DPQ_HUB = "http://192.168.0.10:8700"
PS C:\Users\User\dpqctl> .\dpqctl.cmd status
hub: http://192.168.0.10:8700 ラウンド 3370(3.0秒間隔)
S1 R01 在籍 利用者0件 epoch0 名簿第1版
S2 R02 在籍 利用者0件 epoch0 名簿第1版
S3 R03 在籍 利用者0件 epoch0 名簿第1版
S4 R04 在籍 利用者0件 epoch0 名簿第1版
PS C:\Users\User\dpqctl>
自分の情報を登録する
ここで本人確認用の秘密鍵/公開鍵作成も行う
このregisterは、例えばECサイトで個人情報を登録することを想定している
PS C:\Users\User\dpqctl> .\dpqctl.cmd wallet create --subject u1
利用者 u1 の鍵を作成しました(公開鍵 1801baeffeb373f0…)
PS C:\Users\User\dpqctl> .\dpqctl.cmd wallet register --subject u1 --name "山田 太郎" --birth 1995-04-12 --address "東京都千代田区千代田1-1"
u1 を 4/4 台に登録しました(各サーバには断片のみ)
PS C:\Users\User\dpqctl>
5. 動かしてみる
まずはAPIトークンを取得する
PS C:\Users\User\dpqctl> $API = "http://192.168.0.20:8710"
PS C:\Users\User\dpqctl> '{"username":"dpquser","password":"Password"}' | Out-File -Encoding ascii login.json
PS C:\Users\User\dpqctl> $T = (curl.exe -s -X POST "$API/auth/token" -H "Content-Type: application/json" --data-binary "@login.json" | ConvertFrom-Json).token
PS C:\Users\User\dpqctl> '{"username":"dpqop","password":"Password"}' | Out-File -Encoding ascii login.json
PS C:\Users\User\dpqctl> $CT = (curl.exe -s -X POST "$API/auth/token" -H "Content-Type: application/json" --data-binary "@login.json" | ConvertFrom-Json).token
PS C:\Users\User\dpqctl> Remove-Item login.json
PS C:\Users\User\dpqctl> $T.Length
47
PS C:\Users\User\dpqctl>
同意トークンを作成する
同意トークンは照会のたびに作成する必要がある
PS C:\Users\User\dpqctl> .\dpqctl.cmd wallet consent --subject u1 --vendor dpqs --purpose age --age 18 --rounds 100 -o a1.json
同意トークンを a1.json に保存(ラウンド53636〜53736 有効)
同意トークンを使用し、対象ユーザが18歳以降であるかどうかを照会してみる
PS C:\Users\User\dpqctl> curl.exe -s -X POST "$API/v1/query?type=age_over&age=18" -H "Authorization: Bearer $T" -H "Content-Type: application/json" --data-binary "@a1.json"
{"over": true, "selected": ["S2", "S1", "S3"], "round": 53639, "elapsed": 1.47}
生年月日はどこにも渡らず、どの1台にも集まらないまま、「18歳以上かどうか」という答えだけが出た
どのサーバも生年月日の情報を持っていないにもかかわらず、情報照会ができている
同じ同意トークンを使用して照会を行おうとすると、照会が拒否される
PS C:\Users\User\dpqctl> .\dpqctl.cmd wallet consent --subject u1 --vendor dpqs --purpose age --age 18 --rounds 100 -o a2.json
同意トークンを a2.json に保存(ラウンド53666〜53766 有効)
PS C:\Users\User\dpqctl> curl.exe -s -X POST "$API/v1/query?type=age_over&age=18" -H "Authorization: Bearer $T" -H "Content-Type: application/json" --data-binary "@a2.json"
{"over": true, "selected": ["S3", "S2", "S1"], "round": 53671, "elapsed": 1.23}
PS C:\Users\User\dpqctl> curl.exe -s -X POST "$API/v1/query?type=age_over&age=18" -H "Authorization: Bearer $T" -H "Content-Type: application/json" --data-binary "@a2.json"
{"error": "選定されたサーバが照会を受け付けなかった {\"S1\": \"拒否: HTTP 403: [S1] 同意トークンの再利用\", \"S3\": \"拒否: HTTP 403: [S3] 同意トークンの再利用\", \"S4\": \"拒否: HTTP 403: [S4] 同じ同意で複数の照会を掲示(選定の操作試行)\"}"}
氏名の照会を行う
不一致の場合はfalseが返ってくる
PS C:\Users\User\dpqctl> .\dpqctl.cmd wallet consent --subject u1 --vendor dpqs --purpose identity --rounds 100 -o a3.json
同意トークンを a3.json に保存(ラウンド54066〜54166 有効)
PS C:\Users\User\dpqctl> curl.exe -s -X POST "$API/v1/query?type=name_match&claimed_name=%E5%B1%B1%E7%94%B0%E5%A4%AA%E9%83%8E" -H "Authorization: Bearer $T" -H "Content-Type: application/json" --data-binary "@a3.json"
{"match": true, "selected": ["S1", "S2", "S3"], "round": 54067, "elapsed": 0.19}
PS C:\Users\User\dpqctl> .\dpqctl.cmd wallet consent --subject u1 --vendor dpqs --purpose identity --rounds 100 -o a4.json
同意トークンを a4.json に保存(ラウンド54067〜54167 有効)
PS C:\Users\User\dpqctl> curl.exe -s -X POST "$API/v1/query?type=name_match&claimed_name=%E5%B1%B1%E7%94%B0%E6%AC%A1%E9%83%8E" -H "Authorization: Bearer $T" -H "Content-Type: application/json" --data-binary "@a4.json"
{"match": false, "selected": ["S1", "S4", "S3"], "round": 54068, "elapsed": 0.18}
PS C:\Users\User\dpqctl>
APIトークンを指定しなかった場合や、誤ったロールで照会をしようとすると、エラーになる
以下の例では、配送業者(carrier)は住所の照会のみ受け付けるにもかかわらず、年齢照会をしようしている
PS C:\Users\User\dpqctl> .\dpqctl.cmd wallet consent --subject u1 --vendor dpqs --purpose age --age 18 --rounds 100 -o a5.json
同意トークンを a5.json に保存(ラウンド54104〜54204 有効)
PS C:\Users\User\dpqctl> curl.exe -s -X POST "$API/v1/query?type=age_over&age=18" --data-binary "@a5.json"
{"error": "Authorization: Bearer <API トークン> が必要"}
PS C:\Users\User\dpqctl> curl.exe -s -X POST "$API/v1/query?type=age_over&age=18" -H "Authorization: Bearer $CT" --data-binary "@a5.json"
{"error": "この操作は vendor の利用者のみ(あなたは carrier)"}
PS C:\Users\User\dpqctl>
利用者が署名をし、配送元に住所引換券を渡している
この住所引換券を配送業者に渡し、配送業者のみが配送先の住所を照会できるようになっている
引き換えは1回のみ
PS C:\Users\User\dpqctl> .\dpqctl.cmd wallet consent --subject u1 --vendor dpqs --purpose delivery --carrier dpqops --rounds 100 -o a6.json
同意トークンを a6.json に保存(ラウンド54281〜54381 有効)
PS C:\Users\User\dpqctl> $D = curl.exe -s -X POST "$API/v1/query?type=delivery_token&carrier=dpqops" -H "Authorization: Bearer $T" -H "Content-Type: application/json" --data-binary "@a6.json" | ConvertFrom-Json
PS C:\Users\User\dpqctl> $D
token : c6a3fd5c219f793fe571dde0f2e57a
servers : {S1, S2, S3}
selected : {S1, S2, S3}
round : 54282
elapsed : 0.1
PS C:\Users\User\dpqctl> @{ token = $D.token; servers = $D.servers } | ConvertTo-Json | Out-File -Encoding ascii redeem.json
PS C:\Users\User\dpqctl> curl.exe -s -X POST "$API/v1/redeem" -H "Authorization: Bearer $CT" -H "Content-Type: application/json" --data-binary "@redeem.json"
{"address": "東京都千代田区千代田1-1"}
PS C:\Users\User\dpqctl> curl.exe -s -X POST "$API/v1/redeem" -H "Authorization: Bearer $CT" -H "Content-Type: application/json" --data-binary "@redeem.json"
{"error": "引き換えを受け付けなかったサーバがある {\"S1\": \"HTTP 403: [S1] トークンは使用済み\", \"S2\": \"HTTP 403: [S2] トークンは使用済み\", \"S3\": \"HTTP 403: [S3] トークンは使用済み\"}"}
PS C:\Users\User\dpqctl>
配送元の会社に住所情報を渡さずに配送依頼ができる
照会履歴(ユーザのみが閲覧できる)
10-09 16:05:20 S1 accepted {"vendor": "dpqs", "qtype": "age_over", "purpose": "age_verification", "selected": ["S2", "S1", "S3"]}
10-09 16:05:21 S1 released {"vendor": "dpqs", "qtype": "age_over"}
10-09 16:05:23 S2 released {"vendor": "dpqs", "qtype": "age_over"}
10-09 16:05:23 S3 released {"vendor": "dpqs", "qtype": "age_over"}
10-09 16:06:56 S1 accepted {"vendor": "dpqs", "qtype": "age_over", "purpose": "age_verification", "selected": ["S3", "S2", "S1"]}
10-09 16:06:57 S1 released {"vendor": "dpqs", "qtype": "age_over"}
10-09 16:06:59 S2 released {"vendor": "dpqs", "qtype": "age_over"}
10-09 16:06:59 S3 released {"vendor": "dpqs", "qtype": "age_over"}
10-09 16:07:20 S1 rejected {"vendor": "dpqs", "qtype": "age_over", "reason": "同意トークンの再利用"}
10-09 16:07:22 S3 rejected {"vendor": "dpqs", "qtype": "age_over", "reason": "同意トークンの再利用"}
10-09 16:07:22 S4 rejected {"vendor": "dpqs", "qtype": "age_over", "reason": "同じ同意で複数の照会を掲示(選定の操作試行)"}
10-09 16:18:17 S1 accepted {"vendor": "dpqs", "qtype": "name_match", "purpose": "identity_verification", "selected": ["S1", "S3", "S2"]}
10-09 16:18:35 S1 accepted {"vendor": "dpqs", "qtype": "name_match", "purpose": "identity_verification", "selected": ["S1", "S3", "S2"]}
10-09 16:26:43 S2 accepted {"vendor": "dpqs", "qtype": "name_match", "purpose": "identity_verification", "selected": ["S1", "S2", "S3"]}
10-09 16:26:43 S2 released {"vendor": "dpqs", "qtype": "name_match"}
10-09 16:26:44 S1 released {"vendor": "dpqs", "qtype": "name_match"}
10-09 16:26:46 S3 released {"vendor": "dpqs", "qtype": "name_match"}
10-09 16:26:47 S1 accepted {"vendor": "dpqs", "qtype": "name_match", "purpose": "identity_verification", "selected": ["S1", "S4", "S3"]}
10-09 16:26:47 S1 released {"vendor": "dpqs", "qtype": "name_match"}
10-09 16:26:49 S3 released {"vendor": "dpqs", "qtype": "name_match"}
10-09 16:26:49 S4 released {"vendor": "dpqs", "qtype": "name_match"}
10-09 16:33:37 S2 rejected {"vendor": "dpqs", "qtype": "delivery_token", "reason": "同意の範囲外のパラメータ"}
10-09 16:33:38 S1 rejected {"vendor": "dpqs", "qtype": "delivery_token", "reason": "同意の範囲外のパラメータ"}
10-09 16:33:40 S3 rejected {"vendor": "dpqs", "qtype": "delivery_token", "reason": "同意の範囲外のパラメータ"}
10-09 16:34:14 S1 rejected {"vendor": "dpqs", "qtype": "delivery_token", "reason": "同意の範囲外のパラメータ"}
10-09 16:34:16 S3 rejected {"vendor": "dpqs", "qtype": "delivery_token", "reason": "同意の範囲外のパラメータ"}
10-09 16:34:16 S4 rejected {"vendor": "dpqs", "qtype": "delivery_token", "reason": "同意の範囲外のパラメータ"}
10-09 16:36:19 S2 rejected {"vendor": "dpqs", "qtype": "delivery_token", "reason": "同意の範囲外のパラメータ"}
10-09 16:36:20 S1 rejected {"vendor": "dpqs", "qtype": "delivery_token", "reason": "同意の範囲外のパラメータ"}
10-09 16:36:22 S3 rejected {"vendor": "dpqs", "qtype": "delivery_token", "reason": "同意の範囲外のパラメータ"}
10-09 16:37:28 S2 accepted {"vendor": "dpqs", "qtype": "delivery_token", "purpose": "delivery", "selected": ["S1", "S2", "S3"]}
10-09 16:37:28 S2 released {"vendor": "dpqs", "qtype": "delivery_token"}
10-09 16:37:29 S2 redeemed {"vendor": "dpqops", "qtype": "delivery_token"}
10-09 16:37:30 S1 released {"vendor": "dpqs", "qtype": "delivery_token"}
10-09 16:37:30 S1 redeemed {"vendor": "dpqops", "qtype": "delivery_token"}
10-09 16:37:31 S3 released {"vendor": "dpqs", "qtype": "delivery_token"}
10-09 16:37:31 S3 redeemed {"vendor": "dpqops", "qtype": "delivery_token"}
PS C:\Users\User\dpqctl>
dpqのapiサーバの照会ログ
10-09 16:01:49 OK login dpquser 192.168.0.105 {"ttl": 3600}
10-09 16:02:14 NG query dpquser 192.168.0.105 {"qtype": "age_over", "error": "選定されたサーバが照会を受け付けなかった"}
10-09 16:02:29 NG query dpquser 192.168.0.105 {"qtype": "age_over", "error": "選定されたサーバが照会を受け付けなかった"}
10-09 16:05:21 OK query dpquser 192.168.0.105 {"qtype": "age_over", "selected": ["S2", "S1", "S3"], "elapsed": 1.47, "over": true}
10-09 16:06:57 OK query dpquser 192.168.0.105 {"qtype": "age_over", "selected": ["S3", "S2", "S1"], "elapsed": 1.23, "over": true}
10-09 16:07:20 NG query dpquser 192.168.0.105 {"qtype": "age_over", "error": "選定されたサーバが照会を受け付けなかった"}
10-09 16:16:26 NG query dpquser 192.168.0.105 {"qtype": "name_match", "error": "この同意トークンは webshop 宛てで、dpqs では使えない"}
10-09 16:16:28 NG query dpquser 192.168.0.105 {"qtype": "name_match", "error": "この同意トークンは webshop 宛てで、dpqs では使えない"}
10-09 16:16:47 NG query dpquser 192.168.0.105 {"qtype": "name_match", "error": "この同意トークンは dpqop 宛てで、dpqs では使えない"}
10-09 16:16:49 NG query dpquser 192.168.0.105 {"qtype": "name_match", "error": "この同意トークンは webshop 宛てで、dpqs では使えない"}
10-09 16:17:08 NG query dpquser 192.168.0.105 {"qtype": "name_match", "error": "この同意トークンは dpquser 宛てで、dpqs では使えない"}
10-09 16:17:12 NG query dpquser 192.168.0.105 {"qtype": "name_match", "error": "この同意トークンは dpquser 宛てで、dpqs では使えない"}
10-09 16:17:39 NG query dpquser 192.168.0.105 {"qtype": "name_match", "error": "この同意トークンは dpquser 宛てで、dpqs では使えない"}
10-09 16:17:43 NG query dpquser 192.168.0.105 {"qtype": "name_match", "error": "この同意トークンは dpquser 宛てで、dpqs では使えない"}
10-09 16:18:31 NG query dpquser 192.168.0.105 {"qtype": "name_match", "error": "選定されたサーバが照会を受け付けなかった"}
10-09 16:18:38 NG query dpquser 192.168.0.105 {"qtype": "name_match", "error": "選定されたサーバが照会を受け付けなかった"}
10-09 16:26:44 OK query dpquser 192.168.0.105 {"qtype": "name_match", "selected": ["S1", "S2", "S3"], "elapsed": 0.19, "match": true}
10-09 16:26:47 OK query dpquser 192.168.0.105 {"qtype": "name_match", "selected": ["S1", "S4", "S3"], "elapsed": 0.18, "match": false}
10-09 16:33:38 NG query dpquser 192.168.0.105 {"qtype": "delivery_token", "error": "選定されたサーバが照会を受け付けなかった"}
10-09 16:34:14 NG query dpquser 192.168.0.105 {"qtype": "delivery_token", "error": "選定されたサーバが照会を受け付けなかった"}
10-09 16:34:45 NG query dpquser 192.168.0.105 {"qtype": "delivery_token", "error": "この同意トークンは dpqops 宛てで、dpqs では使えない"}
10-09 16:35:04 NG query dpquser 192.168.0.105 {"qtype": "delivery_token", "error": "この同意トークンは dpqop 宛てで、dpqs では使えない"}
10-09 16:36:20 NG query dpquser 192.168.0.105 {"qtype": "delivery_token", "error": "選定されたサーバが照会を受け付けなかった"}
10-09 16:37:30 OK query dpquser 192.168.0.105 {"qtype": "delivery_token", "selected": ["S1", "S2", "S3"], "elapsed": 0.1}
10-09 16:37:30 OK redeem dpqop 192.168.0.105 {"token": "c6a3fd", "servers": ["S1", "S2", "S3"]}
10-09 16:37:31 NG redeem dpqop 192.168.0.105 {"token": "c6a3fd", "error": "引き換えを受け付けなかったサーバがある"}
xubuntu@DPQ01:~$
DPQ01とDPQ02で、登録されている断片が異なることを確認する
xubuntu@DPQ01:~$ sudo python3 -c "import sqlite3; [print(f,v) for f,v in sqlite3.connect('/var/lib/dpq/server-S1/server.db').execute(\"select field,value from shares where subject='u1' order by field limit 6\")]"
addr_0 10885028834777348911583572659220919496
addr_1 121047053344765768540758329492912501247
addr_2 104974225765197280829386050903801499592
addr_3 67929253756992375760582111541907897115
birth_b0 166730689781338015599408128537891557424
birth_b1 56632887262881871485499681072474009504
xubuntu@DPQ01:~$
xubuntu@DPQ02:~$ sudo python3 -c "import sqlite3; [print(f,v) for f,v in sqlite3.connect('/var/lib/dpq/server-S2/server.db').execute(\"select field,value from shares where subject='u1' order by field limit 6\")]"
addr_0 21770057669554697823167145318441838959
addr_1 70755496519118497661888611903908620380
addr_2 38604831683783642328646571850955852513
addr_3 135858507513984751521164223083812571397
birth_b0 163320196102206799467128953359899009120
birth_b1 113265774525763742970999362144948019007
xubuntu@DPQ02:~$
6. サーバを1台外しても続く
1台サーバを落とした状態で年齢照会をしてみる
xubuntu@DPQ01:~$ dpqctl status
hub: http://192.168.0.10:8700 ラウンド 54677(3.0秒間隔)
S1 R01 在籍 利用者1件 epoch0 名簿第1版
S2 R02 在籍 利用者1件 epoch0 名簿第1版
S3 R03 在籍 利用者1件 epoch0 名簿第1版
S4 R04 在籍 利用者1件 epoch0 名簿第1版
xubuntu@DPQ01:~$
xubuntu@DPQ01:~$ dpqctl directory remove S4
名簿 第2版 を掲示しました(ラウンド54724 から有効、3台)
xubuntu@DPQ01:~$ dpqctl status
hub: http://192.168.0.10:8700 ラウンド 54722(3.0秒間隔)
S1 R01 在籍 利用者1件 epoch0 名簿第2版
S2 R02 在籍 利用者1件 epoch0 名簿第2版
S3 R03 在籍 利用者1件 epoch0 名簿第2版
S4 R04 除外 応答なし
xubuntu@DPQ01:~$
admin@DPQ04:~ $ sudo systemctl stop dpq-server@S4
admin@DPQ04:~ $ systemctl status dpq-server@S4
○ dpq-server@S4.service - DPQ share server S4
Loaded: loaded (/lib/systemd/system/dpq-server@.service; enabled; preset: >
Active: inactive (dead) since Fri 2026-10-09 16:57:54 JST; 4s ago
Duration: 1d 18h 28min 53.544s
Docs: file:///usr/share/doc/dpq/INSTALL.md
Process: 1128 ExecStart=/usr/bin/dpq-server --config /etc/dpq/server-S4.con>
Main PID: 1128 (code=killed, signal=TERM)
CPU: 620ms
10月 07 22:29:00 DPQ04 systemd[1]: Started dpq-server@S4.service - DPQ share se>
10月 07 22:29:05 DPQ04 dpq-server[1128]: 2026-10-07 22:29:05,419 INFO dpq: サー>
10月 07 22:29:05 DPQ04 dpq-server[1128]: 2026-10-07 22:29:05,423 INFO dpq: serv>
10月 07 22:29:05 DPQ04 dpq-server[1128]: 2026-10-07 22:29:05,438 WARNING dpq: h>
10月 07 22:29:20 DPQ04 dpq-server[1128]: 2026-10-07 22:29:20,439 WARNING dpq: h>
10月 09 16:57:54 DPQ04 systemd[1]: Stopping dpq-server@S4.service - DPQ share s>
10月 09 16:57:54 DPQ04 systemd[1]: dpq-server@S4.service: Deactivated successfu>
10月 09 16:57:54 DPQ04 systemd[1]: Stopped dpq-server@S4.service - DPQ share se>
admin@DPQ04:~ $
S4を名簿から排除したので、S4以外からサーバが選定される
PS C:\Users\User\dpqctl> .\dpqctl.cmd wallet consent --subject u1 --vendor dpqs --purpose age --age 18 --rounds 100 -o a7.json
同意トークンを a7.json に保存(ラウンド54747〜54847 有効)
PS C:\Users\User\dpqctl> curl.exe -s -X POST "$API/v1/query?type=age_over&age=18" -H "Authorization: Bearer $T" -H "Content-Type: application/json" --data-binary "@a7.json"
{"over": true, "selected": ["S1", "S2", "S3"], "round": 54753, "elapsed": 0.9}
PS C:\Users\User\dpqctl>
S4を名簿に戻す
admin@DPQ04:~ $ sudo systemctl start dpq-server@S4
admin@DPQ04:~ $ systemctl status dpq-server@S4
● dpq-server@S4.service - DPQ share server S4
Loaded: loaded (/lib/systemd/system/dpq-server@.service; enabled; preset: >
Active: active (running) since Fri 2026-10-09 17:02:29 JST; 3s ago
Docs: file:///usr/share/doc/dpq/INSTALL.md
Main PID: 2167 (dpq-server)
Tasks: 2 (limit: 9571)
CPU: 181ms
CGroup: /system.slice/system-dpq\x2dserver.slice/dpq-server@S4.service
mq2167 /usr/bin/python3 /usr/bin/dpq-server --config /etc/dpq/serv>
10月 09 17:02:29 DPQ04 systemd[1]: Started dpq-server@S4.service - DPQ share se>
10月 09 17:02:29 DPQ04 dpq-server[2167]: 2026-10-09 17:02:29,799 INFO dpq: サー>
10月 09 17:02:29 DPQ04 dpq-server[2167]: 2026-10-09 17:02:29,802 INFO dpq: serv>
10月 09 17:02:29 DPQ04 dpq-server[2167]: 2026-10-09 17:02:29,826 INFO dpq: 名簿>
admin@DPQ04:~ $
xubuntu@DPQ01:~$ dpqctl directory restore S4
名簿 第3版 を掲示しました(ラウンド54793 から有効、4台)
xubuntu@DPQ01:~$ dpqctl status
hub: http://192.168.0.10:8700 ラウンド 54791(3.0秒間隔)
S1 R01 在籍 利用者1件 epoch0 名簿第3版
S2 R02 在籍 利用者1件 epoch0 名簿第3版
S3 R03 在籍 利用者1件 epoch0 名簿第3版
S4 R04 在籍 利用者1件 epoch0 名簿第3版
xubuntu@DPQ01:~$
まとめ
- サーバに個人情報を置かずに情報照会を行うことができた
- 断片の計算方法については次回まとめる
- 利用可能なdpqのパッケージのURL: https://github.com/Shun141421356/dpq/releases
