Commit de7e3446 authored by Matthieu Tanon's avatar Matthieu Tanon

Remove PHP server

parent e947f41b
#!/usr/bin/env bash
# All versions are set to more or less the latest at writting time
# it shall be safe to use latest instead but just in case, this
# configuration is known to work.
# Nginx. Do not change the name or self signed certicate will fail
NGINX_HOST=localhost
NGINX_VERSION=1.13.12
# PHP
PHP_VERSION=7.2
#PHPMYADMIN
PHPMYADMIN_VERSION=4.8.0-3
# MySQL
MYSQL_VERSION=5.7.22
# host name must match what is used in x3dh server setting
MYSQL_HOST=mysql
MYSQL_ROOT_USER=root
MYSQL_ROOT_PASSWORD=root
README for the X3DH test server running on nginx/php/mysql docker images
========================================================================
Disclaimer
-----------
THIS SERVER IS NOT INTENDED FOR REAL USE BUT FOR TEST PURPOSE ONLY
DO NOT USE IN REAL LIFE IT IS NOT SECURE.
Mostly, it is missing clients authentication. Providing a client
authentication layer before calling the x3dh_process_request function
SHOULD be enough to use it in a real situation.
As usual, this code is distributed in the hope it will be usefull but
without any warranty or implied warranty.
Requirements
------------
- docker-compose
Install
-------
**Permissions:**
Check that the ./source/var/log directory is writable by anyone
**Certificates:**
The X3DH servers use ./source/cn/x3dh-cert.pem and source/cn/x3dh-key.pem
By default it is the certificate available to test client in tester/data
**Database:**
The database is accessible through phpmyadmin on localhost:8080
User : root
Password : root
To reset it, just delete the content of ./db/mysql directory.
**Images version:**
All images points to version more or less matching the latest
at the time this is being written.
Content and Settings
--------------------
./.env : docker-compose environment variables (https://docs.docker.com/compose/environment-variables/#the-env-file)
- images version
- mysql root password and host name
- nginx host name
./customphp.ini : the php.ini configuration file
- make sure the error display is turned off
- set the path to error logs: /source/var/log/php-error.log
./site.conf: the nginx sites configuration file spawning:
- http://localhost:8080 the phpmyadmin access
- https://localhost:25519 and https://localhost:25520 the X3DH test servers
./docker-compose.yml : set images for
- nginx
- php
- phpmyadmin (used to help debugging if needed)
- mysql : acces on port 3306, user: root, password: root
./db/mysql/ : directory used by mysql container to store all its data.
- When container is down, erase the content of this to force a DB reset at next up
./db/initdb.d/ : contains SQL scripts executed at mysql container setup (first intanciation of the mysql container)
- x3dh25519.sql : set up the database for the x3dh-25519.php server
- x3dh448.sql : set up the database for the x3dh-448.php server
./source/cn/: self signed certificate used by https server
./source/x3dh/ : php sources of X3DH server.
- x3dh-25519.php : the settings file for the x3dh server running on curve 25519
- x3dh-448.php : the settings file for the x3dh server running on curve 448
- x3dh.php : the actual server source
- x3dh-createBase.php : a script to create the X3DH server database as needed.
It is not active by default and not used, just provided as example.
./source/var/log : directory were the x3dh server and php logs are written, make sur it is writable
- php-error.log : the php logs
- X3DH25519.log : logs from X3DH 25519 server
- X3DH448.log : logs from X3DH 448 server
Usage
-----
start:
docker-compose up -d
(run without -d options to see full logs in the console, can be wise for the first runs)
This command run 2 X3DH servers accessible at:
- https://localhost:25519 using curve25519
- https://localhost:25520 using curve448
stop:
docker-compose down --volumes
log_errors = On
error_log = /source/var/log/php-error.log
display_errors = Off
date.timezone = UTC
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET AUTOCOMMIT = 0;
DROP DATABASE IF EXISTS `x3dh25519`;
CREATE DATABASE `x3dh25519` CHARACTER SET utf8 COLLATE utf8_bin;
USE `x3dh25519`;
START TRANSACTION;
DROP TABLE IF EXISTS `Users`;
CREATE TABLE `Users` (
`Uid` INTEGER NOT NULL AUTO_INCREMENT,
`UserId` TEXT COLLATE utf8_bin NOT NULL,
`Ik` BLOB NOT NULL,
`SPk` BLOB DEFAULT NULL,
`SPk_sig` BLOB DEFAULT NULL,
`SPk_id` INTEGER UNSIGNED DEFAULT NULL,
PRIMARY KEY(`Uid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
DROP TABLE IF EXISTS `OPk`;
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
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
DROP TABLE IF EXISTS `Config`;
CREATE TABLE `Config` (
`Name` VARCHAR(20) COLLATE utf8_bin DEFAULT NULL,
`Value` INTEGER NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
INSERT INTO `Config` (`Name`, `Value`) VALUES
('version', 1),
('curveId', 25519);
COMMIT;
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET AUTOCOMMIT = 0;
DROP DATABASE IF EXISTS `x3dh448`;
CREATE DATABASE `x3dh448` CHARACTER SET utf8 COLLATE utf8_bin;
USE `x3dh448`;
START TRANSACTION;
DROP TABLE IF EXISTS `Users`;
CREATE TABLE `Users` (
`Uid` INTEGER NOT NULL AUTO_INCREMENT,
`UserId` TEXT COLLATE utf8_bin NOT NULL,
`Ik` BLOB NOT NULL,
`SPk` BLOB DEFAULT NULL,
`SPk_sig` BLOB DEFAULT NULL,
`SPk_id` INTEGER UNSIGNED DEFAULT NULL,
PRIMARY KEY(`Uid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
DROP TABLE IF EXISTS `OPk`;
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
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
DROP TABLE IF EXISTS `Config`;
CREATE TABLE `Config` (
`Name` VARCHAR(20) COLLATE utf8_bin DEFAULT NULL,
`Value` INTEGER NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
INSERT INTO `Config` (`Name`, `Value`) VALUES
('version', 1),
('curveId', 448);
COMMIT;
# Ignore everything in this directory
*
# Except this file
!.gitignore
version: '2'
services:
web:
image: nginx:${NGINX_VERSION}
ports:
- "25519:25519"
- "25520:25520"
volumes:
- ./source:/source
- ./site.conf:/etc/nginx/conf.d/default.conf
restart: always
depends_on:
- php
- mysqldb
php:
# use nanoninja php image to get mysqli
# https://hub.docker.com/r/nanoninja/php-fpm/tags/
image: nanoninja/php-fpm:${PHP_VERSION}
volumes:
- ./source:/source
- ./customphp.ini:/usr/local/etc/php/conf.d/custom.ini
restart: always
myadmin:
image: phpmyadmin/phpmyadmin:${PHPMYADMIN_VERSION}
container_name: phpmyadmin
ports:
- "8080:80"
environment:
- PMA_ARBITRARY=1
- PMA_HOST=${MYSQL_HOST}
restart: always
depends_on:
- mysqldb
mysqldb:
image: mysql:${MYSQL_VERSION}
container_name: ${MYSQL_HOST}
restart: always
env_file:
- ".env"
environment:
- MYSQL_DATABASE=${MYSQL_DATABASE}
- MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
ports:
- "8989:3306"
volumes:
- "./db/mysql:/var/lib/mysql"
- "./db/initdb.d:/docker-entrypoint-initdb.d"
server {
listen 25519 ssl default_server;
listen [::]:25519 ssl default_server;
ssl_certificate /source/cn/x3dh-cert.pem;
ssl_certificate_key /source/cn/x3dh-key.pem;
server_name localhost;
index x3dh/x3dh-25519.php;
error_log /var/log/nginx/error.log;
access_log /var/log/nginx/access.log;
root /source;
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass php:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
}
server {
listen 25520 ssl default_server;
listen [::]:25520 ssl default_server;
ssl_certificate /source/cn/x3dh-cert.pem;
ssl_certificate_key /source/cn/x3dh-key.pem;
server_name localhost;
index x3dh/x3dh-448.php;
error_log /var/log/nginx/error.log;
access_log /var/log/nginx/access.log;
root /source;
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass php:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
}
-----BEGIN CERTIFICATE-----
MIIEnjCCAwagAwIBAgIJAOIhBkBz+NzWMA0GCSqGSIb3DQEBCwUAMFkxCzAJBgNV
BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
aWRnaXRzIFB0eSBMdGQxEjAQBgNVBAMMCWxvY2FsaG9zdDAeFw0xODA0MzAwMjQ2
MzNaFw0yODA0MjcwMjQ2MzNaMFkxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21l
LVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxEjAQBgNV
BAMMCWxvY2FsaG9zdDCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBAK+Y
ZC3KPmB4XjGjDos6Tr1EFWCGkt3RAF1B/KNvXVvM2vve56yhjHM2PtHFBr9/JXCC
iZZq7fc/bN4JusZMWGDhs3EXAuP56/ydZ6X7eaYjRKXrClm1bKde1vSd3cTfiqDN
0YsrQfpW+6XK3stRAob0IKmQbcDjlrGjj8cUNd0YWfBLqkFvfpZALn4uwXXEGs+k
d9hijwXBwJhigzRVoazjZJWd57i+dKDxNzKRmlifMhFaBgh26Knx9F51JcMZbBJn
9bMQDjPc7l5yX0hmTyHouydA7ALCuIUVF/fhvJX+jwrGEMTraSl+ieLYWEtHkit8
Vg5BEJXnitGFuGW3UelHz/sj/t9LDqBLAjrDVoebAFj0W0e1hSIQfmNNx2Q52j7U
TTH24wUqCOaWh4zqqcl4NlgJORqco1BjAGUNkkqhJnrzcSkoHBrcfWtvej+eoxo2
IiCU8trxCyrTN5KMk0i/jXNVb2nChR3WZNvTQV60jKm8/zgX0kvkbLmgMxY8uQID
AQABo2kwZzAUBgNVHREEDTALgglsb2NhbGhvc3QwHQYDVR0OBBYEFGwQgyXv3x7h
lGhIRpgniBEr6Y6/MB8GA1UdIwQYMBaAFGwQgyXv3x7hlGhIRpgniBEr6Y6/MA8G
A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggGBACeOV0fk0gNlHcMJr5y3
8ikVxElAbOjwa6WkOXDmCqp9ju33dvjC+F4kI4XWxVY/JeO5cPAYQNz6uIX0EGue
ynENSHKTnnJddCrcWkR50qAeo/vUHRzqiPyIQXxallp6qGxpDPJujVEfssnG6ZWm
JHrEbWa7YlXaDCzoy2L0CbXhRn4hFAC63+ReTec9y3cJo7zaZ07+xXi8oKO4pI/x
FXD4Xmmrs34JJNyWTaAw5a1na0Tuf8nxs+GkiuG8K1zthLjMZ1v+VjiMwzZw1MsQ
+8Z9fqkOjApmrtFpn2BD06AYobjopsSEzlsFyX4v49142bKmFCxzA3d88rL7hWH9
6SC2hM4bgdQK1vP2vgNoGfdzew7R9Cszi1ApsXHbjCllldtMxySzivOJi7CuU6CF
PE5RjQ1uRKgazfFmBMuLHkE8aaPSiJOusrzmxHoE5QV5CmlE6H06PiQEPYA5v36C
Z9hMTT7bUxCA2r/2xcrqmF982HKrBbGZ2mt9O8HeF2SvIg==
-----END CERTIFICATE-----
-----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----
# Ignore everything in this directory
*
# Except this file
!.gitignore
<?php
/*
x3dh-25519.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/>.
*/
include "x3dh.php";
/*** X3DH server settings ***/
// Curve to use, shall be either CurveId::CURVE25519 or CurveId::CURVE25519
define ("curveId", CurveId::CURVE25519);
// Database access
define("DB_HOST", "mysql");
define("DB_USER", "root");
define("DB_PASSWORD", "root");
// this database must already exists with the requested tables
define ("DB_NAME", "x3dh25519");
// log level one of (LogLevel::DISABLED, ERROR, WARNING. MESSAGE, DEBUG)
// default to DISABLED (recommended value)
define ("x3dh_logLevel" , LogLevel::MESSAGE);
define ("x3dh_logFile", "/source/var/log/X3DH25519.log"); // make sure to have actual write permission to this file
define ("x3dh_logDomain", "X3DH"); // in case Logs are mixed with other applications ones, format is [time tag] -Domain- message
/*** End of X3DH server settings ***/
// That one shall be set by the user authentication layer
$userId = $_SERVER['HTTP_FROM'];
x3dh_process_request($userId);
?>
<?php
/*
x3dh-448.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/>.
*/
include "x3dh.php";
/*** X3DH server settings ***/
// Curve to use, shall be either CurveId::CURVE25519 or CurveId::CURVE25519
define ("curveId", CurveId::CURVE448);
// Database access
define("DB_HOST", "mysql");
define("DB_USER", "root");
define("DB_PASSWORD", "root");
// this database must already exists with the requested tables
define ("DB_NAME", "x3dh448");
// log level one of (LogLevel::DISABLED, ERROR, WARNING. MESSAGE, DEBUG)
// default to DISABLED (recommended value)
define ("x3dh_logLevel" , LogLevel::MESSAGE);
define ("x3dh_logFile", "/source/var/log/X3DH448.log"); // make sure to have actual write permission to this file
define ("x3dh_logDomain", "X3DH"); // in case Logs are mixed with other applications ones, format is [time tag] -Domain- message
/*** End of X3DH server settings ***/
// That one shall be set by the user authentication layer
$userId = $_SERVER['HTTP_FROM'];
x3dh_process_request($userId);
?>
<?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);
?>
<?php
/*
x3dh.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/>.
*/
function x3dh_get_db_conn() {
$db = mysqli_connect(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME);
if (!$db) {
error_log ("Error: Unable to connect to MySQL.\nDebugging errno: " . mysqli_connect_errno() . "\nDebugging error: " . mysqli_connect_error() . "\n");
exit;
}
return $db;
}
// be sure we do not display any error or it may mess the returned message
ini_set('display_errors', 'Off');
// emulate simple enumeration
abstract class LogLevel {
const DISABLED = 0;
const ERROR = 1;
const WARNING = 2;
const MESSAGE = 3;
const DEBUG = 4;
};
function stringErrorLevel($level) {
switch($level) {
case LogLevel::DISABLED: return "DISABLED";
case LogLevel::ERROR: return "ERROR";
case LogLevel::WARNING: return "WARNING";
case LogLevel::MESSAGE: return "MESSAGE";
case LogLevel::DEBUG: return "DEBUG";
default: return "UNKNOWN";
}
}
function x3dh_log($level, $message) {
if (x3dh_logLevel>=$level) {
if ($level === LogLevel::ERROR) { // in ERROR case, add a backtrace
file_put_contents(x3dh_logFile, date("Y-m-d h:m:s")." -".x3dh_logDomain."- ".stringErrorLevel($level)." : $message\n".print_r(debug_backtrace(),true), FILE_APPEND);
} else {
file_put_contents(x3dh_logFile, date("Y-m-d h:m:s")." -".x3dh_logDomain."- ".stringErrorLevel($level)." : $message\n", FILE_APPEND);
}
}
}
/**
* Constants settings
*/
// define the curve Id used on this server, default is curve25519, it will be either load from DB or got from args if we are creation the DB.
// WARNING: value shall be in sync with defines in client code: Curve25519 = 1, Curve448 = 2 */
// emulate simple enumeration with abstract class
abstract class CurveId {
const CURVE25519 = 1;
const CURVE448 = 2;
};
define ('X3DH_protocolVersion', 0x01);
define ('X3DH_headerSize', 3);
// WARNING: value shall be in sync with defines in client code */
// emulate simple enumeration with abstract class
abstract class MessageTypes {
const unset_type = 0x00;
const registerUser = 0x01;
const deleteUser = 0x02;
const postSPk = 0x03;
const postOPks = 0x04;
const getPeerBundle = 0x05;
const peerBundle = 0x06;
const getSelfOPks = 0x07;
const selfOPks = 0x08;
const error = 0xff;
};
// emulate simple enumeration with abstract class
abstract class ErrorCodes {
const bad_content_type = 0x00;
const bad_curve = 0x01;
const missing_senderId = 0x02;
const bad_x3dh_protocol_version = 0x03;
const bad_size = 0x04;
const user_already_in = 0x05;
const user_not_found = 0x06;
const db_error = 0x07;
const bad_request = 0x08;
const server_failure = 0x09;
};
// emulate simple enumeration with abstract class
abstract class KeyBundleFlag {
const noOPk = 0x00;
const OPk = 0x01;
const noBundle = 0x02;
}
// define keys and signature size in bytes based on the curve used
const keySizes = array(
CurveId::CURVE25519 => array ('X_pub' => 32, 'X_priv' => 32, 'ED_pub' => 32, 'ED_priv' => 32, 'Sig' => 64),
CurveId::CURVE448 => array ('X_pub' => 56, 'X_priv' => 56, 'ED_pub' => 57, 'ED_priv' => 57, 'Sig' => 114)
);
function returnError($code, $errorMessage) {
x3dh_log(LogLevel::WARNING, "return an error message code ".$code." : ".$errorMessage);
$header = pack("C4",X3DH_protocolVersion, MessageTypes::error, curveId, $code); // build the X3DH response header, append the error code
file_put_contents('php://output', $header.$errorMessage);
exit;
}
function returnOk($message) {
x3dh_log(LogLevel::DEBUG, "Ok return a message ".bin2hex($message));
file_put_contents('php://output', $message);
exit;
}
// Check server setting:
function x3dh_checkSettings() {
// curveId must be 25519 or 448
switch(curveId) {
// Authorized values
case CurveId::CURVE25519 :
case CurveId::CURVE448 :
break;
// Any other are invalid
default:
x3dh_log(LogLevel::ERROR, "Process X3DH request given incorrect curveId parameter (".curveId.").");
returnError(ErrorCodes::server_failure, "X3DH server is not correctly configured");