Linphone + X3DH 暗号化メッセージ送受信

X3DHによるメッセージの暗号化をLinphoneに導入。X3DH暗号化プロトコルについては以下参照(Signalによって開発されたDiffie-Hellmanの拡張プロトコルです)。LinphoneではLIME(Linphone Instant Messaging Encryption)として導入されています。X3DHで使用される共有セッションキーを作成するため、各ユーザの公開キーと一時キーを保存・管理するための専用サーバが必要です。

Signal:X3DH

The Double Ratchet Algorithm

LIME

ドキュメント:Ver.5.3

flexisip.conf

ダイジェスト認証する上で、以下のユーザ認証に関わる設定を見直す必要があるかもしれません。特にサーバ上でクライアントアプリのダイジェスト認証を動作させるには、以下の trusted-hosts をコメントアウトすること。

[module::Authentication]

# Indicate whether the module is activated.
# Default: false
enabled=true

# A request/response enters module if the boolean filter evaluates
# to true. Ex: from.uri.domain contains 'sip.linphone.org', from.uri.domain
# in 'a.org b.org c.org', (to.uri.domain in 'a.org b.org c.org')
# && (user-agent == 'Linphone v2'). You can consult the full filter
# documentation here : https://wiki.linphone.org/xwiki/wiki/public/view/Flexisip/Configuration/Filter%20syntax/
# Default: 
#filter=

# List of whitespace-separated IP addresses which will be judged
# as trustful. Messages coming from these addresses won't be challenged.
# Default: 
#trusted-hosts=127.0.0.1 

PHPによるダイジェスト認証サーバを導入

HTTP authentication

Digest authentication with SHA-256 and MD5

Authorization

作成中。。。

SIP Globally Routable User Agent (UA) URIs (GRUU)

SIP GRUU

RFC 5627: Obtaining and Using Globally Routable User Agent URIs (GRUUs) in the Session Initiation Protocol (SIP)

Common Presence and Instant Messaging (CPIM): Message Format

Content-Type: message/cpim は、CPIM(Common Profile for Instant Messaging)のメッセージフォーマットを指定するMIMEタイプです。CPIMは、異なるインスタントメッセージングシステム間の相互運用性を確保するために設計された標準的なプロトコルです。以下はCPIMの特徴と使用目的の詳細です。

CPIMの特徴と目的

  1. 標準化されたフォーマット:
  • CPIMは、インスタントメッセージング(IM)プロトコル間でメッセージを交換するための共通のフォーマットを提供します。これにより、異なるIMシステムが互いにメッセージを送受信できるようになります。
  1. メッセージのパッケージ化:
  • CPIMメッセージは、インスタントメッセージングの内容をパッケージ化し、送信者情報、受信者情報、日時、メッセージID、IMDN(Instant Message Disposition Notification)などのメタデータを含むことができます。
  1. プロトコルに依存しない:
  • CPIMは、特定のトランスポートプロトコル(例えばSIP、XMPP、SMTPなど)に依存しない形式で設計されています。これにより、CPIMメッセージはさまざまなプロトコル上で伝送できます。
  1. メタデータのサポート:
  • CPIMメッセージは、IMDNを使用して、メッセージの受領確認、表示確認、拒否などの配信通知をサポートしています。これにより、送信者はメッセージの配信状況を把握できます。

CPIMメッセージの構造

CPIMメッセージの一般的な構造は以下のようになります:

  • ヘッダー:
    • From: 送信者の識別子(例:SIP URIやメールアドレス)。
    • To: 受信者の識別子。
    • DateTime: メッセージが送信された日時。
    • Message-ID: メッセージの一意の識別子。
    • その他、必要に応じて追加されるヘッダー(例:NSimdn.Message-IDなど)。
  • ボディ:
    • メッセージの内容。テキスト、画像、その他のメディア形式を含むことができます。

X3DH暗号化メッセージに必要な鍵サーバはプロプライエタリソフトのため、 Belledonne Communicationsから公開されているテストサーバを参考にPHPコードで自作。

X3DHプロトコルにおけるサーバの主な役割は、公開鍵(特に、長期鍵、セッション鍵、そしてワンタイムプリキー)を保存・配布することです。サーバは、鍵交換のための公開鍵をホストするだけであり、秘密鍵には一切アクセスできません。

チャットルームテーブルデータ

各デバイス間のメッセージ・ファイル送受信の確認

X3DHにより暗号化されたメッセージの送受信は、チャットルームのSIPアドレス経由で行われます。flexisip.conf[conference-server] セクションが、この動作に影響するため、以下のポイントを再チェックして下さい。

[conference-server] セクションの
outbound-proxy=sip:127.0.0.1:5070;transport=tcp のSIPアドレスを
[global] セクションの transports に追加すること。

flexisip.conf

.....
.....
[global]
.....
.....
transports=sip:127.0.0.1:5070;transport=tcp .....................................
.....
.....

[conference-server]

# Enable conference server
# Default: true
enabled=true

# URI where the conference server must listen. Only one URI can
# be specified.
# Default: sip:127.0.0.1:6064;transport=tcp
transport=sip:127.0.0.1:6064;transport=tcp

# List of SIP uris used by clients to create a conference. This
# implicitely defines the list of SIP domains managed by the conference
# server. For example:
# conference-factory-uris=sip:[email protected]
# sip:[email protected]
# Default: 
conference-factory-uris=sip:[email protected] sip:[email protected] 

# uri used as conference server contact address. For example:
# conference-focus-uris=sip:[email protected]
# sip:[email protected]
# Default: 
conference-focus-uris=sip:[email protected] sip:[email protected]

# The Flexisip proxy URI to which the conference server should sent
# all its outgoing SIP requests.
# Default: sip:127.0.0.1:5060;transport=tcp
outbound-proxy=sip:127.0.0.1:5070;transport=tcp

ユーザ(デバイスID)、公開キー、選択する楕円曲線の保存データベース

以下のPHPコードを実行するか、SQLコマンドを直接実行してテーブルを作成して下さい。

<?php
/*
	x3dh-createBase.php
	@author Johan Pascal
	@copyright 	Copyright (C) 2018  Belledonne Communications SARL

	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/


// Database access
define("DB_HOST", "mysql");
define("DB_USER", "root");
define("DB_PASSWORD", "root");

$curve = $_GET['curve'];

if ($curve != 448 ) { // Default is curve25519
	$curve=25519;
}

function x3dh_create_db($dbname, $curve) {
	$db = mysqli_connect(DB_HOST, DB_USER, DB_PASSWORD);
	if (!$db) {
		error_log ("Error: Unable to connect to MySQL.\nDebugging errno: " . mysqli_connect_errno() . "\nDebugging error: " . mysqli_connect_error() . "\n");
		exit;
	}

	// get a clean base
	$db->query("DROP DATABASE IF EXISTS $dbname");
	$db->query("CREATE DATABASE $dbname CHARACTER SET utf8 COLLATE utf8_bin");

	// select DB
	$db->select_db($dbname);

	/* Users table:
	 *  - id as primary key (internal use)
	 *  - a userId(shall be the GRUU)
	 *  - Ik (Identity key - EDDSA public key)
	 *  - SPk(the current signed pre-key - ECDH public key)
	 *  - SPk_sig(current SPk public key signed with Identity key)
	 *  - SPh_id (id for SPk provided and internally used by client) - 4 bytes unsigned integer
	 */

	/* One Time PreKey table:
	 *  - an id as primary key (internal use)
	 *  - the Uid of user owning that key
	 *  - the public key (ECDH public key)
	 *  - OPk_id (id for OPk provided and internally used by client) - 4 bytes unsigned integer
	 */

	/* Config table: holds version and curveId parameters:
	 *  - Name: the parameter name (version or curveId)
	 *  - Value: the parameter value (db version scheme or curveId mapped to an integer)
	 */

	$db->query("CREATE TABLE Users (
			Uid INTEGER NOT NULL AUTO_INCREMENT,
			UserId TEXT NOT NULL,
			Ik BLOB NOT NULL,
			SPk BLOB DEFAULT NULL,
			SPk_sig BLOB DEFAULT NULL,
			SPk_id INTEGER UNSIGNED DEFAULT NULL,
			PRIMARY KEY(Uid));");

	$db->query("CREATE TABLE OPk (
			id INTEGER NOT NULL AUTO_INCREMENT,
			Uid INTEGER NOT NULL,
			OPk BLOB NOT NULL,
			OPk_id INTEGER UNSIGNED NOT NULL,
			PRIMARY KEY(id),
			FOREIGN KEY(Uid) REFERENCES Users(Uid) ON UPDATE CASCADE ON DELETE CASCADE);");

	$db->query("CREATE TABLE Config(
			Name VARCHAR(20),
			Value INTEGER NOT NULL);");

	$db->query("INSERT INTO Config(Name, Value) VALUES('version', 0x000001)"); // version of DB scheme MMmmpp
	$db->query("INSERT INTO Config(Name, Value) VALUES('curveId', $curve)"); // what curveId we're using

	$db->close();
}

// Uncomment next line if you really want to use this script to create the requested tables
//x3dh_create_db('x3dh'.$curve, $curve);

?>

Screenshot from 2024-09-11 22-04-49