愛記システムの基本設計:DApps側である愛記システム データの一貫性 データの暗号化 | 続・ティール組織 研究会のブログ

続・ティール組織 研究会のブログ

ティール組織が話題になっているが、具現化するにはどうしたらよいか?
その研究を続けるにあたり、さらに次の形態である、続・ティール組織なるものまで視野に入れ、具体的な施策・行動内容を研究・支援する会。

先までは、"愛記"についての記載で、どのようにブロックチェーンSNSに組み込んで実装していけばよいのか、概念的なところからアプローチ方法を記載していった。概念設計としてはひとまず終えた。次は、フェデレーションモデル全体の基本設計といえるところまで、基本設計書に着手できるようなところまで、概念を具体化していきたい。そして、それにつながるDApps側である「愛記システム」を、Pythonプログラムで開発していきたい。

 

愛の行動のPL,BSを決算書として、個人単位、市町村単位、で公表するような愛記システムというものを考えている。愛の行動のデータベースはブロックチェーンのプログラムであり、日々の愛の行動による愛貨の移動を決算書にまとめていきたい。なお、市町村のブロックチェーンのプログラムは以前にも記載している。その市町村のブロックチェーンのプログラムにつながる愛記システムを、DApps側であるPythonプログラムとして設計したい。その場合、基本設計をどのような手順で進めていけばよいか、詳しく見ていこう。

 

愛記システムを設計するための基本手順を以下に示す。このシステムは、Pythonを用いて市町村のブロックチェーンと連携し、個人および市町村単位での愛の行動のデータを収集、記録し、決算書(PL、BS)として公表するものである。

基本設計のステップ

  1. 要件定義
  2. アーキテクチャ設計
  3. データベース設計
  4. API設計
  5. ブロックチェーンインターフェース
  6. 決算書の生成
  7. フロントエンド開発
  8. テストとデプロイ

基本設計の各ステップを順番に進めることで、ブロックチェーンとDAppsとして繋がる「愛記システム」の詳細な設計が可能になる。各ステップでは、関係者との協議やレビューを通じて設計内容を確定していくことが重要である。

1.要件定義

まず、基本設計の最初のステップである要件定義をしていきたい。どのような機能が必要か、どのような問題を解決するのかを洗い出したい。要件定義はシステム設計の最初の重要なステップであり、システムが解決するべき問題と、必要な機能を明確に定義するプロセスである。以下に、愛記システムのプログラムに必要な機能と解決すべき問題を列挙してみよう。

機能要件

  1. 愛の行動の記録

  2. 愛貨の移動の記録

  3. 決算書の生成

  4. 個人および市町村単位でのデータの集約

  5. データのブロックチェーンへの記録と取得

  6. 愛貨の管理

  7. ユーザー管理

  8. 通知機能

  9. レポート機能

  10. ダッシュボード

非機能要件

  1. セキュリティ

  2. 可用性

  3. パフォーマンス

  4. スケーラビリティ

  5. ユーザビリティ

  6. コンプライアンス

解決すべき問題

  1. 透明性と信頼性の確保

  2. データの一元管理

  3. 愛の行動の促進

  4. 評価制度の確立

  5. データのセキュリティとプライバシーの保護

これらの要件を基に、愛記システムの基本設計を進めていくことが重要である。次のステップでは、これらの要件を具体的なアーキテクチャ設計に反映していくことになる。まずは、要件定義の解決すべき問題を一つずつクリアにしていきたい。

透明性と信頼性の確保

1. データの完全性と一貫性の保証

  • データの完全性: すべての取引と愛の行動記録が正確かつ改ざんされていないことを保証する。

  • データの一貫性: システム全体でデータが統一されていることを確認する。

2. 取引の透明性の確保

  • 公開取引データ: 取引データを公開し、誰でも確認できるようにする。

  • 監査ログ: 取引や行動のすべての変更履歴を保持し、監査可能にする。

3. データのセキュリティとプライバシー保護

  • 暗号化: データの送受信時および保存時に暗号化を行い、データの安全性を確保。

  • アクセス制御: データへのアクセスを制御し、必要な権限を持つユーザーのみに限定。

4. 取引の正当性の確認

  • 署名の生成と検証: 取引データの署名を生成し、取引の正当性を検証。

  • 取引の検証: 各取引を検証し、不正行為や二重支出を防止。

これらの項目を詳細に決定し、実装することで、愛記システムの透明性と信頼性を確保することができる。各項目については、具体的な技術要件や設計仕様を定義し、システム開発の各フェーズで反映させることが重要である。

データの一貫性について

1. データの一貫性

システム全体でデータが統一されていることを確認するために、次の点に注意する。

  • トランザクションのアトミック性: トランザクションが完全に成功するか、まったく成功しないかを保証する。
  • データの整合性チェック: データが一貫性を保つための整合性チェックを設計する。
  • データの同期: 分散システム間でデータの同期を適切に行う。

2. データの完全性
データが損なわれないようにするために、次の点に注意する。

  • データの暗号化: データの機密性を確保するために、保存時および通信時にデータを暗号化する。
  • データのバリデーション: 入力データをバリデーションして、不正なデータがシステムに入らないようにする。

3. 監査ログ

すべての操作を監査ログに記録し、後から検証可能にする。では、以下に、データの完全性と一貫性を確保するための具体的なプログラム例を示す。

 

・データの暗号化:

量子耐性のある暗号化方式の例として、ラティスベースの暗号(Lattice-based Cryptography)があり、例えば、NTRUやCRYSTALS-Kyberといった方式が知られている。これに対して、Paillier暗号方式やAESなどの従来の公開鍵暗号方式や対称鍵暗号方式は、量子コンピュータによって破られる可能性が高いとされている。以下に、量子耐性のラティスベースの暗号方式を使用したプログラム例を示す。これに基づいて、フェデレーションモデルにおける各種通信の暗号化を実装し直す。

NTRUを使った量子耐性の暗号化例

NTRU暗号化方式は、ポスト量子暗号の一種であり、格子に基づいた暗号アルゴリズムである。これにより、量子コンピュータによる攻撃に耐性がある。以下にNTRU暗号化方式の基本的なロジックを詳しく説明する。

・NTRU暗号化方式の基本

  1. 鍵生成 (Key Generation)

    • 秘密鍵 (Private Key)
      • 2つの多項式 f と g をランダムに生成する。
      • f は不可約多項式であり、NTRUの秘密鍵になる。
      • f と g は、あるモジュロ q での演算に対して逆元を持つ必要がある。
    • 公開鍵 (Public Key)
      • 公開鍵 h は、次のように計算される:  f^{-1} * g \mod qh
      • ここで、 f^{-1}は q に対する f の逆元である。
  2. 暗号化 (Encryption)

    • メッセージ m を暗号化するために、ランダムな多項式 r を生成する。
    • 暗号文 c は次のように計算される: c = r * h + m mod q
  3. 復号 (Decryption)

    • 受信者は秘密鍵 f を使って、暗号文 c からメッセージ m を復号する: a = f * c mod q
    • メッセージ m は次のようにして取り出される: m = a mod p
    • ここで、 p は小さなモジュロであり、通常は2や3である。

・NTRU暗号化方式のRust実装

以下は、DApps側であるPythonプログラムの全体的な実装である。このプログラムは、市町村のブロックチェーンと通信し、NTRU暗号化方式を使用してトランザクションを送信および受信する。

・前提条件

Pythonの依存関係をインストールする。

pip install pymongo requests pqcrypto
 

・データ構造の定義と暗号化/復号化
import hashlib
import datetime
import requests
from pymongo import MongoClient
from pqcrypto.kem.ntruhps4096821 import generate_keypair, encapsulate, decapsulate

# MongoDBクライアント設定
client = MongoClient('mongodb://localhost:27017/')
db = client['blockchain_db']

# 公開鍵と秘密鍵の生成
public_key, secret_key = generate_keypair()

def encrypt_message(public_key, message):
    """メッセージをNTRUで暗号化"""
    ciphertext, shared_secret = encapsulate(public_key)
    return ciphertext

def decrypt_message(secret_key, ciphertext):
    """NTRUで暗号化されたメッセージを復号化"""
    plaintext = decapsulate(secret_key, ciphertext)
    return plaintext

# データ構造定義
transaction = {
    'transaction_id': 'tx123',
    'sender': 'user1',
    'receiver': 'user2',
    'amount': 100.0,
    'action_content': 'Helping with groceries',
    'location': '36.5,137.0',
    'municipality': 'Kaga',
    'timestamp': datetime.datetime.now().isoformat(),
    'signature': 'usersignature123',
    'proof_of_place': {
        'latitude': 36.5,
        'longitude': 137.0,
        'timestamp': datetime.datetime.now().isoformat(),
    },
    'approver_info': None
}

# トランザクションの整合性をチェックする
def check_transaction_consistency(transaction):
    """トランザクションの整合性をチェックする"""
    if not verify_signature(transaction['data'], transaction['public_key'], transaction['signature']):
        raise ValueError("Invalid Signature")
    if transaction['timestamp'] > datetime.datetime.now().timestamp():
        raise ValueError("Future timestamp")

# トランザクションの署名を検証
def verify_signature(transaction_data, public_key, signature):
    """署名を検証する疑似関数"""
    return hashlib.sha256(str(transaction_data + public_key).encode()).hexdigest() == signature

# トランザクションを送信する関数
def send_transaction(transaction):
    encrypted_data = encrypt_message(public_key, str(transaction).encode())
    response = requests.post("http://localhost:8080/transactions", json={
        'transaction_id': transaction['transaction_id'],
        'data': encrypted_data,
        'timestamp': transaction['timestamp']
    })
    return response.json()

# トランザクションを受信する関数
def receive_transaction():
    response = requests.get("http://localhost:8080/receive_transaction")
    encrypted_data = response.json()['data']
    decrypted_data = decrypt_message(secret_key, encrypted_data)
    return decrypted_data

# トランザクションの送信
try:
    result = send_transaction(transaction)
    print("Transaction sent successfully:", result)
except ValueError as e:
    print(f"Error sending transaction: {e}")

# トランザクションの受信
try:
    result = receive_transaction()
    print("Transaction received successfully:", result)
except ValueError as e:
    print(f"Error receiving transaction: {e}")

・説明:

  1. データ構造の定義:

    • トランザクションデータの構造を定義する。各トランザクションは、ID、送信者、受信者、金額、アクション内容、位置情報、タイムスタンプ、署名、Proof of Place、および承認者情報を含む。
  2. 整合性チェック:

    • check_transaction_consistency関数でトランザクションの整合性をチェックする。これは、署名の検証とタイムスタンプのチェックを行う。
  3. NTRU暗号化/復号化:

    • encrypt_message関数でメッセージを暗号化し、decrypt_message関数で暗号化されたメッセージを復号化する。
  4. トランザクションの送信と受信:

    • send_transaction関数でトランザクションを市町村のブロックチェーンに送信する。暗号化されたデータを含むリクエストを送信する。
    • receive_transaction関数で市町村のブロックチェーンからトランザクションを受信し、復号化する。

この実装により、DApps側でNTRU暗号化方式を使用してトランザクションの送信と受信を安全に行うことができる。また、フェデレーションモデルにおける各種通信の暗号化において、量子耐性のある暗号方式を使用することで、将来的なセキュリティリスクを軽減できる。NTRUを使用した暗号化を通じて、各通信パターンでのデータの完全性と機密性を確保することが重要である。

なお、市町村のブロックチェーン、大陸毎のメインチェーン、グローバルメインチェーン、DApps、スマートフォンアプリと、それぞれの接続時に場合分けして、上記の暗号の実装例を示してみよう。以下の例では、NTRU暗号方式を使用してデータの暗号化を実装する。フェデレーションモデルにおける各種接続時のデータの暗号化を示す。


・前提条件

以下の依存関係をCargo.tomlに追加する。
[dependencies]
actix-web = "4.0"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
chrono = { version = "0.4", features = ["serde"] }
pqcrypto-ntru = "0.7"
 

・市町村ブロックチェーンとDApps間の接続

NTRU暗号方式の鍵生成、暗号化、復号化
use pqcrypto_ntru::ntruhps4096821::*;
use pqcrypto_traits::kem::{PublicKey, SecretKey};

fn generate_keys() -> (PublicKey, SecretKey) {
    keypair()
}

fn encrypt_message(public_key: &PublicKey, message: &[u8]) -> Vec<u8> {
    let (ciphertext, _) = encapsulate(public_key);
    ciphertext.as_bytes().to_vec()
}

fn decrypt_message(secret_key: &SecretKey, ciphertext: &[u8]) -> Vec<u8> {
    let encapsulated = pqcrypto_ntru::ntruhps4096821::Ciphertext::from_bytes(ciphertext).unwrap();
    let (shared_secret, _) = decapsulate(secret_key, &encapsulated);
    shared_secret.as_bytes().to_vec()
}


・トランザクションの送信と受信
use actix_web::{post, web, App, HttpResponse, HttpServer, Responder};
use serde::{Deserialize, Serialize};
use std::sync::{Arc, Mutex};

#[derive(Debug, Clone, Serialize, Deserialize)]
struct Transaction {
    transaction_id: String,
    data: Vec<u8>, // 暗号化されたデータ
    timestamp: String,
}

struct AppState {
    pending_transactions: Mutex<Vec<Transaction>>,
}

#[post("/send_transaction")]
async fn send_transaction(data: web::Data<AppState>, req: web::Json<Transaction>) -> impl Responder {
    let transaction = req.into_inner();
    let mut pending_transactions = data.pending_transactions.lock().unwrap();
    pending_transactions.push(transaction);
    HttpResponse::Ok().json("Transaction received")
}

#[post("/receive_transaction")]
async fn receive_transaction(data: web::Data<AppState>, secret_key: web::Data<SecretKey>) -> impl Responder {
    let pending_transactions = data.pending_transactions.lock().unwrap();
    let secret_key = secret_key.get_ref();

    let decrypted_transactions: Vec<String> = pending_transactions.iter().map(|tx| {
        let decrypted_data = decrypt_message(&secret_key, &tx.data);
        String::from_utf8(decrypted_data).unwrap()
    }).collect();

    HttpResponse::Ok().json(decrypted_transactions)
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    let app_state = web::Data::new(AppState {
        pending_transactions: Mutex::new(Vec::new()),
    });

    let (public_key, secret_key) = generate_keys();
    let secret_key_data = web::Data::new(secret_key);

    HttpServer::new(move || {
        App::new()
            .app_data(app_state.clone())
            .app_data(secret_key_data.clone())
            .service(send_transaction)
            .service(receive_transaction)
    })
    .bind("127.0.0.1:8080")?
    .run()
    .await
}
 

・市町村ブロックチェーンと大陸毎のメインチェーン間の接続

トランザクションの送信と受信(非同期通信)
#[post("/send_to_main_chain")]
async fn send_to_main_chain(data: web::Data<AppState>, req: web::Json<Transaction>, public_key: web::Data<PublicKey>) -> impl Responder {
    let transaction = req.into_inner();
    let encrypted_data = encrypt_message(public_key.get_ref(), &transaction.data);
    let encrypted_transaction = Transaction {
        transaction_id: transaction.transaction_id,
        data: encrypted_data,
        timestamp: transaction.timestamp,
    };

    let mut pending_transactions = data.pending_transactions.lock().unwrap();
    pending_transactions.push(encrypted_transaction);
    HttpResponse::Ok().json("Transaction sent to main chain")
}

#[post("/receive_from_main_chain")]
async fn receive_from_main_chain(data: web::Data<AppState>, secret_key: web::Data<SecretKey>) -> impl Responder {
    let pending_transactions = data.pending_transactions.lock().unwrap();
    let secret_key = secret_key.get_ref();

    let decrypted_transactions: Vec<String> = pending_transactions.iter().map(|tx| {
        let decrypted_data = decrypt_message(&secret_key, &tx.data);
        String::from_utf8(decrypted_data).unwrap()
    }).collect();

    HttpResponse::Ok().json(decrypted_transactions)
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    let app_state = web::Data::new(AppState {
        pending_transactions: Mutex::new(Vec::new()),
    });

    let (public_key, secret_key) = generate_keys();
    let public_key_data = web::Data::new(public_key);
    let secret_key_data = web::Data::new(secret_key);

    HttpServer::new(move || {
        App::new()
            .app_data(app_state.clone())
            .app_data(public_key_data.clone())
            .app_data(secret_key_data.clone())
            .service(send_to_main_chain)
            .service(receive_from_main_chain)
    })
    .bind("127.0.0.1:8081")?
    .run()
    .await
}
 

・大陸毎のメインチェーン間の通信

大陸毎のメインチェーン間の通信では、さらに強力な量子耐性暗号を使用し、オフラインでのデータ交換を行う。オフライン通信例(擬似コード)
fn offline_data_exchange(data: Vec<u8>, public_key: &PublicKey, secret_key: &SecretKey) -> Vec<u8> {
    // データの暗号化
    let encrypted_data = encrypt_message(public_key, &data);

    // オフラインでデータ交換(例: USBドライブ、QRコードなど)
    let exchanged_data = encrypted_data.clone(); // 実際にはオフライン交換手段を使用

    // データの復号化
    decrypt_message(secret_key, &exchanged_data)
}
 

・DAppsとスマートフォンアプリ間の通信

スマートフォンアプリからDAppsへのリクエストをNTRUで暗号化し、安全に通信する。
スマートフォンアプリとDApps間の通信例
import requests
import pqcrypto

# 公開鍵を使用してメッセージを暗号化
def encrypt_message(public_key, message):
    ciphertext = pqcrypto.kem.enc(public_key)
    return ciphertext

# 秘密鍵を使用してメッセージを復号化
def decrypt_message(secret_key, ciphertext):
    plaintext = pqcrypto.kem.dec(secret_key, ciphertext)
    return plaintext

# メッセージの送信
def send_message(public_key, message):
    encrypted_message = encrypt_message(public_key, message)
    response = requests.post("http://localhost:8080/send_transaction", json={"data": encrypted_message})
    return response.json()

# メッセージの受信
def receive_message(secret_key):
    response = requests.get("http://localhost:8080/receive_transaction")
    encrypted_message = response.json()["data"]
    decrypted_message = decrypt_message(secret_key, encrypted_message)
    return decrypted_message


この設計では、量子耐性のあるNTRU暗号方式を使用して、フェデレーションモデル内の各接続時のデータの暗号化を実装した。市町村ブロックチェーン、大陸毎のメインチェーン、DApps、スマートフォンアプリ間でデータを安全にやり取りするための具体的な実装例を示した。このようにして、システム全体のデータ一貫性と信頼性を確保することができる。


いかがであろうか、これで量子耐性のあるラティス暗号にて、フェデレーションモデル内の各接続を行うことができる。このような設計にしていきたい。