Crypto to src
move Crypto to src and Friendica\Util namespace
This commit is contained in:
parent
6d6d83012c
commit
9e6bf79380
15 changed files with 317 additions and 230 deletions
|
@ -1,172 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
use Friendica\Core\Config;
|
|
||||||
|
|
||||||
require_once 'library/ASNValue.class.php';
|
|
||||||
require_once 'library/asn1.php';
|
|
||||||
|
|
||||||
// supported algorithms are 'sha256', 'sha1'
|
|
||||||
|
|
||||||
function rsa_sign($data, $key, $alg = 'sha256') {
|
|
||||||
openssl_sign($data, $sig, $key, (($alg == 'sha1') ? OPENSSL_ALGO_SHA1 : $alg));
|
|
||||||
return $sig;
|
|
||||||
}
|
|
||||||
|
|
||||||
function rsa_verify($data, $sig, $key, $alg = 'sha256') {
|
|
||||||
return openssl_verify($data, $sig, $key, (($alg == 'sha1') ? OPENSSL_ALGO_SHA1 : $alg));
|
|
||||||
}
|
|
||||||
|
|
||||||
function DerToPem($Der, $Private = false) {
|
|
||||||
//Encode:
|
|
||||||
$Der = base64_encode($Der);
|
|
||||||
//Split lines:
|
|
||||||
$lines = str_split($Der, 65);
|
|
||||||
$body = implode("\n", $lines);
|
|
||||||
//Get title:
|
|
||||||
$title = $Private ? 'RSA PRIVATE KEY' : 'PUBLIC KEY';
|
|
||||||
//Add wrapping:
|
|
||||||
$result = "-----BEGIN {$title}-----\n";
|
|
||||||
$result .= $body . "\n";
|
|
||||||
$result .= "-----END {$title}-----\n";
|
|
||||||
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
function DerToRsa($Der) {
|
|
||||||
//Encode:
|
|
||||||
$Der = base64_encode($Der);
|
|
||||||
//Split lines:
|
|
||||||
$lines = str_split($Der, 64);
|
|
||||||
$body = implode("\n", $lines);
|
|
||||||
//Get title:
|
|
||||||
$title = 'RSA PUBLIC KEY';
|
|
||||||
//Add wrapping:
|
|
||||||
$result = "-----BEGIN {$title}-----\n";
|
|
||||||
$result .= $body . "\n";
|
|
||||||
$result .= "-----END {$title}-----\n";
|
|
||||||
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
function pkcs8_encode($Modulus, $PublicExponent) {
|
|
||||||
//Encode key sequence
|
|
||||||
$modulus = new ASNValue(ASNValue::TAG_INTEGER);
|
|
||||||
$modulus->SetIntBuffer($Modulus);
|
|
||||||
$publicExponent = new ASNValue(ASNValue::TAG_INTEGER);
|
|
||||||
$publicExponent->SetIntBuffer($PublicExponent);
|
|
||||||
$keySequenceItems = array($modulus, $publicExponent);
|
|
||||||
$keySequence = new ASNValue(ASNValue::TAG_SEQUENCE);
|
|
||||||
$keySequence->SetSequence($keySequenceItems);
|
|
||||||
//Encode bit string
|
|
||||||
$bitStringValue = $keySequence->Encode();
|
|
||||||
$bitStringValue = chr(0x00) . $bitStringValue; //Add unused bits byte
|
|
||||||
$bitString = new ASNValue(ASNValue::TAG_BITSTRING);
|
|
||||||
$bitString->Value = $bitStringValue;
|
|
||||||
//Encode body
|
|
||||||
$bodyValue = "\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00" . $bitString->Encode();
|
|
||||||
$body = new ASNValue(ASNValue::TAG_SEQUENCE);
|
|
||||||
$body->Value = $bodyValue;
|
|
||||||
//Get DER encoded public key:
|
|
||||||
$PublicDER = $body->Encode();
|
|
||||||
return $PublicDER;
|
|
||||||
}
|
|
||||||
|
|
||||||
function pkcs1_encode($Modulus, $PublicExponent) {
|
|
||||||
//Encode key sequence
|
|
||||||
$modulus = new ASNValue(ASNValue::TAG_INTEGER);
|
|
||||||
$modulus->SetIntBuffer($Modulus);
|
|
||||||
$publicExponent = new ASNValue(ASNValue::TAG_INTEGER);
|
|
||||||
$publicExponent->SetIntBuffer($PublicExponent);
|
|
||||||
$keySequenceItems = array($modulus, $publicExponent);
|
|
||||||
$keySequence = new ASNValue(ASNValue::TAG_SEQUENCE);
|
|
||||||
$keySequence->SetSequence($keySequenceItems);
|
|
||||||
//Encode bit string
|
|
||||||
$bitStringValue = $keySequence->Encode();
|
|
||||||
return $bitStringValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
function metopem($m, $e) {
|
|
||||||
$der = pkcs8_encode($m, $e);
|
|
||||||
$key = DerToPem($der, false);
|
|
||||||
return $key;
|
|
||||||
}
|
|
||||||
|
|
||||||
function pubrsatome($key, &$m, &$e)
|
|
||||||
{
|
|
||||||
require_once 'library/asn1.php';
|
|
||||||
|
|
||||||
$lines = explode("\n", $key);
|
|
||||||
unset($lines[0]);
|
|
||||||
unset($lines[count($lines)]);
|
|
||||||
$x = base64_decode(implode('', $lines));
|
|
||||||
|
|
||||||
$r = ASN_BASE::parseASNString($x);
|
|
||||||
|
|
||||||
$m = base64url_decode($r[0]->asnData[0]->asnData);
|
|
||||||
$e = base64url_decode($r[0]->asnData[1]->asnData);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function rsatopem($key) {
|
|
||||||
pubrsatome($key, $m, $e);
|
|
||||||
return metopem($m, $e);
|
|
||||||
}
|
|
||||||
|
|
||||||
function pemtorsa($key) {
|
|
||||||
pemtome($key, $m, $e);
|
|
||||||
return metorsa($m, $e);
|
|
||||||
}
|
|
||||||
|
|
||||||
function pemtome($key, &$m, &$e)
|
|
||||||
{
|
|
||||||
$lines = explode("\n", $key);
|
|
||||||
unset($lines[0]);
|
|
||||||
unset($lines[count($lines)]);
|
|
||||||
$x = base64_decode(implode('', $lines));
|
|
||||||
|
|
||||||
$r = ASN_BASE::parseASNString($x);
|
|
||||||
|
|
||||||
$m = base64url_decode($r[0]->asnData[1]->asnData[0]->asnData[0]->asnData);
|
|
||||||
$e = base64url_decode($r[0]->asnData[1]->asnData[0]->asnData[1]->asnData);
|
|
||||||
}
|
|
||||||
|
|
||||||
function metorsa($m, $e) {
|
|
||||||
$der = pkcs1_encode($m, $e);
|
|
||||||
$key = DerToRsa($der);
|
|
||||||
return $key;
|
|
||||||
}
|
|
||||||
|
|
||||||
function salmon_key($pubkey) {
|
|
||||||
pemtome($pubkey, $m, $e);
|
|
||||||
return 'RSA' . '.' . base64url_encode($m, true) . '.' . base64url_encode($e, true) ;
|
|
||||||
}
|
|
||||||
|
|
||||||
function new_keypair($bits) {
|
|
||||||
$openssl_options = array(
|
|
||||||
'digest_alg' => 'sha1',
|
|
||||||
'private_key_bits' => $bits,
|
|
||||||
'encrypt_key' => false
|
|
||||||
);
|
|
||||||
|
|
||||||
$conf = Config::get('system', 'openssl_conf_file');
|
|
||||||
if ($conf) {
|
|
||||||
$openssl_options['config'] = $conf;
|
|
||||||
}
|
|
||||||
$result = openssl_pkey_new($openssl_options);
|
|
||||||
|
|
||||||
if (empty($result)) {
|
|
||||||
logger('new_keypair: failed');
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get private key
|
|
||||||
$response = array('prvkey' => '', 'pubkey' => '');
|
|
||||||
|
|
||||||
openssl_pkey_export($result, $response['prvkey']);
|
|
||||||
|
|
||||||
// Get public key
|
|
||||||
$pkey = openssl_pkey_get_details($result);
|
|
||||||
$response['pubkey'] = $pkey["key"];
|
|
||||||
|
|
||||||
return $response;
|
|
||||||
}
|
|
|
@ -21,7 +21,6 @@ use Friendica\Protocol\Feed;
|
||||||
|
|
||||||
require_once 'include/bbcode.php';
|
require_once 'include/bbcode.php';
|
||||||
require_once 'include/oembed.php';
|
require_once 'include/oembed.php';
|
||||||
require_once 'include/crypto.php';
|
|
||||||
require_once 'include/tags.php';
|
require_once 'include/tags.php';
|
||||||
require_once 'include/files.php';
|
require_once 'include/files.php';
|
||||||
require_once 'include/text.php';
|
require_once 'include/text.php';
|
||||||
|
|
|
@ -29,6 +29,7 @@ use Friendica\Model\Group;
|
||||||
use Friendica\Model\User;
|
use Friendica\Model\User;
|
||||||
use Friendica\Network\Probe;
|
use Friendica\Network\Probe;
|
||||||
use Friendica\Protocol\Diaspora;
|
use Friendica\Protocol\Diaspora;
|
||||||
|
use Friendica\Util\Crypto;
|
||||||
|
|
||||||
require_once 'include/enotify.php';
|
require_once 'include/enotify.php';
|
||||||
|
|
||||||
|
@ -162,9 +163,7 @@ function dfrn_confirm_post(App $a, $handsfree = null) {
|
||||||
* worried about key leakage than anybody cracking it.
|
* worried about key leakage than anybody cracking it.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
require_once 'include/crypto.php';
|
$res = Crypto::newKeypair(4096);
|
||||||
|
|
||||||
$res = new_keypair(4096);
|
|
||||||
|
|
||||||
|
|
||||||
$private_key = $res['prvkey'];
|
$private_key = $res['prvkey'];
|
||||||
|
|
|
@ -8,8 +8,6 @@ use Friendica\Core\System;
|
||||||
use Friendica\Protocol\Diaspora;
|
use Friendica\Protocol\Diaspora;
|
||||||
use Friendica\Util\XML;
|
use Friendica\Util\XML;
|
||||||
|
|
||||||
require_once "include/crypto.php";
|
|
||||||
|
|
||||||
function fetch_init(App $a)
|
function fetch_init(App $a)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
|
@ -1,18 +1,20 @@
|
||||||
<?php
|
<?php
|
||||||
|
/**
|
||||||
|
* @file mod/hostxrd.php
|
||||||
|
*/
|
||||||
use Friendica\App;
|
use Friendica\App;
|
||||||
use Friendica\Core\Config;
|
use Friendica\Core\Config;
|
||||||
use Friendica\Core\System;
|
use Friendica\Core\System;
|
||||||
|
use Friendica\Util\Crypto;
|
||||||
|
|
||||||
require_once('include/crypto.php');
|
function hostxrd_init(App $a)
|
||||||
|
{
|
||||||
function hostxrd_init(App $a) {
|
|
||||||
header('Access-Control-Allow-Origin: *');
|
header('Access-Control-Allow-Origin: *');
|
||||||
header("Content-type: text/xml");
|
header("Content-type: text/xml");
|
||||||
$pubkey = Config::get('system', 'site_pubkey');
|
$pubkey = Config::get('system', 'site_pubkey');
|
||||||
|
|
||||||
if (! $pubkey) {
|
if (! $pubkey) {
|
||||||
$res = new_keypair(1024);
|
$res = Crypto::newKeypair(1024);
|
||||||
|
|
||||||
Config::set('system','site_prvkey', $res['prvkey']);
|
Config::set('system','site_prvkey', $res['prvkey']);
|
||||||
Config::set('system','site_pubkey', $res['pubkey']);
|
Config::set('system','site_pubkey', $res['pubkey']);
|
||||||
|
@ -23,8 +25,8 @@ function hostxrd_init(App $a) {
|
||||||
'$zhost' => $a->get_hostname(),
|
'$zhost' => $a->get_hostname(),
|
||||||
'$zroot' => System::baseUrl(),
|
'$zroot' => System::baseUrl(),
|
||||||
'$domain' => System::baseUrl(),
|
'$domain' => System::baseUrl(),
|
||||||
'$bigkey' => salmon_key(Config::get('system','site_pubkey')),
|
'$bigkey' => Crypto::salmonKey(Config::get('system', 'site_pubkey')))
|
||||||
));
|
);
|
||||||
exit();
|
|
||||||
|
|
||||||
|
exit();
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,6 @@ use Friendica\Protocol\Diaspora;
|
||||||
use Friendica\Protocol\Email;
|
use Friendica\Protocol\Email;
|
||||||
use Friendica\Util\Emailer;
|
use Friendica\Util\Emailer;
|
||||||
|
|
||||||
require_once 'include/crypto.php';
|
|
||||||
require_once 'include/enotify.php';
|
require_once 'include/enotify.php';
|
||||||
require_once 'include/tags.php';
|
require_once 'include/tags.php';
|
||||||
require_once 'include/files.php';
|
require_once 'include/files.php';
|
||||||
|
|
|
@ -9,8 +9,6 @@ use Friendica\Core\Config;
|
||||||
use Friendica\Database\DBM;
|
use Friendica\Database\DBM;
|
||||||
use Friendica\Protocol\Diaspora;
|
use Friendica\Protocol\Diaspora;
|
||||||
|
|
||||||
require_once 'include/crypto.php';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param object $a App
|
* @param object $a App
|
||||||
* @return void
|
* @return void
|
||||||
|
|
|
@ -7,8 +7,8 @@ use Friendica\Core\PConfig;
|
||||||
use Friendica\Database\DBM;
|
use Friendica\Database\DBM;
|
||||||
use Friendica\Protocol\OStatus;
|
use Friendica\Protocol\OStatus;
|
||||||
use Friendica\Protocol\Salmon;
|
use Friendica\Protocol\Salmon;
|
||||||
|
use Friendica\Util\Crypto;
|
||||||
|
|
||||||
require_once 'include/crypto.php';
|
|
||||||
require_once 'include/items.php';
|
require_once 'include/items.php';
|
||||||
require_once 'include/follow.php';
|
require_once 'include/follow.php';
|
||||||
|
|
||||||
|
@ -117,23 +117,23 @@ function salmon_post(App $a) {
|
||||||
|
|
||||||
logger('mod-salmon: key details: ' . print_r($key_info,true), LOGGER_DEBUG);
|
logger('mod-salmon: key details: ' . print_r($key_info,true), LOGGER_DEBUG);
|
||||||
|
|
||||||
$pubkey = metopem($m,$e);
|
$pubkey = Crypto::meToPem($m, $e);
|
||||||
|
|
||||||
// We should have everything we need now. Let's see if it verifies.
|
// We should have everything we need now. Let's see if it verifies.
|
||||||
|
|
||||||
// Try GNU Social format
|
// Try GNU Social format
|
||||||
$verify = rsa_verify($signed_data, $signature, $pubkey);
|
$verify = Crypto::rsaVerify($signed_data, $signature, $pubkey);
|
||||||
$mode = 1;
|
$mode = 1;
|
||||||
|
|
||||||
if (! $verify) {
|
if (! $verify) {
|
||||||
logger('mod-salmon: message did not verify using protocol. Trying compliant format.');
|
logger('mod-salmon: message did not verify using protocol. Trying compliant format.');
|
||||||
$verify = rsa_verify($compliant_format, $signature, $pubkey);
|
$verify = Crypto::rsaVerify($compliant_format, $signature, $pubkey);
|
||||||
$mode = 2;
|
$mode = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! $verify) {
|
if (! $verify) {
|
||||||
logger('mod-salmon: message did not verify using padding. Trying old statusnet format.');
|
logger('mod-salmon: message did not verify using padding. Trying old statusnet format.');
|
||||||
$verify = rsa_verify($stnet_signed_data, $signature, $pubkey);
|
$verify = Crypto::rsaVerify($stnet_signed_data, $signature, $pubkey);
|
||||||
$mode = 3;
|
$mode = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
24
mod/xrd.php
24
mod/xrd.php
|
@ -1,12 +1,14 @@
|
||||||
<?php
|
<?php
|
||||||
|
/**
|
||||||
|
* @file mod/xrd.php
|
||||||
|
*/
|
||||||
use Friendica\App;
|
use Friendica\App;
|
||||||
use Friendica\Core\System;
|
use Friendica\Core\System;
|
||||||
use Friendica\Database\DBM;
|
use Friendica\Database\DBM;
|
||||||
|
use Friendica\Util\Crypto;
|
||||||
|
|
||||||
require_once('include/crypto.php');
|
function xrd_init(App $a)
|
||||||
|
{
|
||||||
function xrd_init(App $a) {
|
|
||||||
if ($a->argv[0] == 'xrd') {
|
if ($a->argv[0] == 'xrd') {
|
||||||
$uri = urldecode(notags(trim($_GET['uri'])));
|
$uri = urldecode(notags(trim($_GET['uri'])));
|
||||||
if ($_SERVER['HTTP_ACCEPT'] == 'application/jrd+json') {
|
if ($_SERVER['HTTP_ACCEPT'] == 'application/jrd+json') {
|
||||||
|
@ -54,8 +56,9 @@ function xrd_init(App $a) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function xrd_json($a, $uri, $alias, $profile_url, $r) {
|
function xrd_json($a, $uri, $alias, $profile_url, $r)
|
||||||
$salmon_key = salmon_key($r['spubkey']);
|
{
|
||||||
|
$salmon_key = Crypto::salmonKey($r['spubkey']);
|
||||||
|
|
||||||
header('Access-Control-Allow-Origin: *');
|
header('Access-Control-Allow-Origin: *');
|
||||||
header("Content-type: application/json; charset=utf-8");
|
header("Content-type: application/json; charset=utf-8");
|
||||||
|
@ -79,8 +82,9 @@ function xrd_json($a, $uri, $alias, $profile_url, $r) {
|
||||||
killme();
|
killme();
|
||||||
}
|
}
|
||||||
|
|
||||||
function xrd_xml($a, $uri, $alias, $profile_url, $r) {
|
function xrd_xml($a, $uri, $alias, $profile_url, $r)
|
||||||
$salmon_key = salmon_key($r['spubkey']);
|
{
|
||||||
|
$salmon_key = Crypto::salmonKey($r['spubkey']);
|
||||||
|
|
||||||
header('Access-Control-Allow-Origin: *');
|
header('Access-Control-Allow-Origin: *');
|
||||||
header("Content-type: text/xml");
|
header("Content-type: text/xml");
|
||||||
|
@ -100,8 +104,8 @@ function xrd_xml($a, $uri, $alias, $profile_url, $r) {
|
||||||
'$salmon' => System::baseUrl() . '/salmon/' . $r['nickname'],
|
'$salmon' => System::baseUrl() . '/salmon/' . $r['nickname'],
|
||||||
'$salmen' => System::baseUrl() . '/salmon/' . $r['nickname'] . '/mention',
|
'$salmen' => System::baseUrl() . '/salmon/' . $r['nickname'] . '/mention',
|
||||||
'$subscribe' => System::baseUrl() . '/follow?url={uri}',
|
'$subscribe' => System::baseUrl() . '/follow?url={uri}',
|
||||||
'$modexp' => 'data:application/magic-public-key,' . $salmon_key,
|
'$modexp' => 'data:application/magic-public-key,' . $salmon_key)
|
||||||
));
|
);
|
||||||
|
|
||||||
$arr = array('user' => $r, 'xml' => $o);
|
$arr = array('user' => $r, 'xml' => $o);
|
||||||
call_hooks('personal_xrd', $arr);
|
call_hooks('personal_xrd', $arr);
|
||||||
|
|
|
@ -16,11 +16,11 @@ use Friendica\Model\Contact;
|
||||||
use Friendica\Model\Group;
|
use Friendica\Model\Group;
|
||||||
use Friendica\Model\Photo;
|
use Friendica\Model\Photo;
|
||||||
use Friendica\Object\Image;
|
use Friendica\Object\Image;
|
||||||
|
use Friendica\Util\Crypto;
|
||||||
use dba;
|
use dba;
|
||||||
use Exception;
|
use Exception;
|
||||||
|
|
||||||
require_once 'boot.php';
|
require_once 'boot.php';
|
||||||
require_once 'include/crypto.php';
|
|
||||||
require_once 'include/dba.php';
|
require_once 'include/dba.php';
|
||||||
require_once 'include/enotify.php';
|
require_once 'include/enotify.php';
|
||||||
require_once 'include/network.php';
|
require_once 'include/network.php';
|
||||||
|
@ -299,7 +299,7 @@ class User
|
||||||
|
|
||||||
$return['password'] = $new_password;
|
$return['password'] = $new_password;
|
||||||
|
|
||||||
$keys = new_keypair(4096);
|
$keys = Crypto::newKeypair(4096);
|
||||||
if ($keys === false) {
|
if ($keys === false) {
|
||||||
throw new Exception(t('SERIOUS ERROR: Generation of security keys failed.'));
|
throw new Exception(t('SERIOUS ERROR: Generation of security keys failed.'));
|
||||||
}
|
}
|
||||||
|
@ -308,7 +308,7 @@ class User
|
||||||
$pubkey = $keys['pubkey'];
|
$pubkey = $keys['pubkey'];
|
||||||
|
|
||||||
// Create another keypair for signing/verifying salmon protocol messages.
|
// Create another keypair for signing/verifying salmon protocol messages.
|
||||||
$sres = new_keypair(512);
|
$sres = Crypto::newKeypair(512);
|
||||||
$sprvkey = $sres['prvkey'];
|
$sprvkey = $sres['prvkey'];
|
||||||
$spubkey = $sres['pubkey'];
|
$spubkey = $sres['pubkey'];
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ use Friendica\Database\DBM;
|
||||||
use Friendica\Model\Profile;
|
use Friendica\Model\Profile;
|
||||||
use Friendica\Protocol\Email;
|
use Friendica\Protocol\Email;
|
||||||
use Friendica\Protocol\Feed;
|
use Friendica\Protocol\Feed;
|
||||||
|
use Friendica\Util\Crypto;
|
||||||
use Friendica\Util\XML;
|
use Friendica\Util\XML;
|
||||||
|
|
||||||
use dba;
|
use dba;
|
||||||
|
@ -25,7 +26,6 @@ use DOMDocument;
|
||||||
|
|
||||||
require_once 'include/dba.php';
|
require_once 'include/dba.php';
|
||||||
require_once 'include/network.php';
|
require_once 'include/network.php';
|
||||||
require_once "include/crypto.php";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This class contain functions for probing URL
|
* @brief This class contain functions for probing URL
|
||||||
|
@ -944,7 +944,7 @@ class Probe
|
||||||
|
|
||||||
//if (strstr($data["pubkey"], 'RSA ') || ($link["type"] == "RSA"))
|
//if (strstr($data["pubkey"], 'RSA ') || ($link["type"] == "RSA"))
|
||||||
if (strstr($data["pubkey"], 'RSA ')) {
|
if (strstr($data["pubkey"], 'RSA ')) {
|
||||||
$data["pubkey"] = rsatopem($data["pubkey"]);
|
$data["pubkey"] = Crypto::rsaToPem($data["pubkey"]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1043,7 +1043,7 @@ class Probe
|
||||||
if ($search->length > 0) {
|
if ($search->length > 0) {
|
||||||
$data["pubkey"] = $search->item(0)->nodeValue;
|
$data["pubkey"] = $search->item(0)->nodeValue;
|
||||||
if (strstr($data["pubkey"], 'RSA ')) {
|
if (strstr($data["pubkey"], 'RSA ')) {
|
||||||
$data["pubkey"] = rsatopem($data["pubkey"]);
|
$data["pubkey"] = Crypto::rsaToPem($data["pubkey"]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1133,7 +1133,7 @@ class Probe
|
||||||
|
|
||||||
//if (strstr($data["pubkey"], 'RSA ') || ($link["type"] == "RSA"))
|
//if (strstr($data["pubkey"], 'RSA ') || ($link["type"] == "RSA"))
|
||||||
if (strstr($data["pubkey"], 'RSA ')) {
|
if (strstr($data["pubkey"], 'RSA ')) {
|
||||||
$data["pubkey"] = rsatopem($data["pubkey"]);
|
$data["pubkey"] = Crypto::rsaToPem($data["pubkey"]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1244,7 +1244,7 @@ class Probe
|
||||||
if (sizeof($key) >= 3) {
|
if (sizeof($key) >= 3) {
|
||||||
$m = base64url_decode($key[1]);
|
$m = base64url_decode($key[1]);
|
||||||
$e = base64url_decode($key[2]);
|
$e = base64url_decode($key[2]);
|
||||||
$data["pubkey"] = metopem($m, $e);
|
$data["pubkey"] = Crypto::meToPem($m, $e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -463,7 +463,7 @@ class DFRN
|
||||||
/* get site pubkey. this could be a new installation with no site keys*/
|
/* get site pubkey. this could be a new installation with no site keys*/
|
||||||
$pubkey = Config::get('system', 'site_pubkey');
|
$pubkey = Config::get('system', 'site_pubkey');
|
||||||
if (! $pubkey) {
|
if (! $pubkey) {
|
||||||
$res = new_keypair(1024);
|
$res = Crypto::newKeypair(1024);
|
||||||
Config::set('system', 'site_prvkey', $res['prvkey']);
|
Config::set('system', 'site_prvkey', $res['prvkey']);
|
||||||
Config::set('system', 'site_pubkey', $res['pubkey']);
|
Config::set('system', 'site_pubkey', $res['pubkey']);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ use Friendica\Model\Group;
|
||||||
use Friendica\Model\Profile;
|
use Friendica\Model\Profile;
|
||||||
use Friendica\Model\User;
|
use Friendica\Model\User;
|
||||||
use Friendica\Network\Probe;
|
use Friendica\Network\Probe;
|
||||||
|
use Friendica\Util\Crypto;
|
||||||
use Friendica\Util\XML;
|
use Friendica\Util\XML;
|
||||||
|
|
||||||
use dba;
|
use dba;
|
||||||
|
@ -173,7 +174,7 @@ class Diaspora
|
||||||
|
|
||||||
$key = self::key($handle);
|
$key = self::key($handle);
|
||||||
|
|
||||||
$verify = rsa_verify($signable_data, $sig, $key);
|
$verify = Crypto::rsaVerify($signable_data, $sig, $key);
|
||||||
if (!$verify) {
|
if (!$verify) {
|
||||||
logger('Message did not verify. Discarding.');
|
logger('Message did not verify. Discarding.');
|
||||||
return false;
|
return false;
|
||||||
|
@ -273,7 +274,7 @@ class Diaspora
|
||||||
$author_addr = base64_decode($key_id);
|
$author_addr = base64_decode($key_id);
|
||||||
$key = self::key($author_addr);
|
$key = self::key($author_addr);
|
||||||
|
|
||||||
$verify = rsa_verify($signed_data, $signature, $key);
|
$verify = Crypto::rsaVerify($signed_data, $signature, $key);
|
||||||
if (!$verify) {
|
if (!$verify) {
|
||||||
logger('Message did not verify. Discarding.');
|
logger('Message did not verify. Discarding.');
|
||||||
http_status_exit(400);
|
http_status_exit(400);
|
||||||
|
@ -406,7 +407,7 @@ class Diaspora
|
||||||
http_status_exit(400);
|
http_status_exit(400);
|
||||||
}
|
}
|
||||||
|
|
||||||
$verify = rsa_verify($signed_data, $signature, $key);
|
$verify = Crypto::rsaVerify($signed_data, $signature, $key);
|
||||||
|
|
||||||
if (!$verify) {
|
if (!$verify) {
|
||||||
logger('Message did not verify. Discarding.');
|
logger('Message did not verify. Discarding.');
|
||||||
|
@ -699,7 +700,7 @@ class Diaspora
|
||||||
|
|
||||||
$key = self::key($msg["author"]);
|
$key = self::key($msg["author"]);
|
||||||
|
|
||||||
if (!rsa_verify($signed_data, $parent_author_signature, $key, "sha256")) {
|
if (!Crypto::rsaVerify($signed_data, $parent_author_signature, $key, "sha256")) {
|
||||||
logger("No valid parent author signature for parent author ".$msg["author"]. " in type ".$type." - signed data: ".$signed_data." - Message: ".$msg["message"]." - Signature ".$parent_author_signature, LOGGER_DEBUG);
|
logger("No valid parent author signature for parent author ".$msg["author"]. " in type ".$type." - signed data: ".$signed_data." - Message: ".$msg["message"]." - Signature ".$parent_author_signature, LOGGER_DEBUG);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -709,7 +710,7 @@ class Diaspora
|
||||||
|
|
||||||
$key = self::key($fields->author);
|
$key = self::key($fields->author);
|
||||||
|
|
||||||
if (!rsa_verify($signed_data, $author_signature, $key, "sha256")) {
|
if (!Crypto::rsaVerify($signed_data, $author_signature, $key, "sha256")) {
|
||||||
logger("No valid author signature for author ".$fields->author. " in type ".$type." - signed data: ".$signed_data." - Message: ".$msg["message"]." - Signature ".$author_signature, LOGGER_DEBUG);
|
logger("No valid author signature for author ".$fields->author. " in type ".$type." - signed data: ".$signed_data." - Message: ".$msg["message"]." - Signature ".$author_signature, LOGGER_DEBUG);
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1432,7 +1433,7 @@ class Diaspora
|
||||||
// Check signature
|
// Check signature
|
||||||
$signed_text = 'AccountMigration:'.$old_handle.':'.$new_handle;
|
$signed_text = 'AccountMigration:'.$old_handle.':'.$new_handle;
|
||||||
$key = self::key($old_handle);
|
$key = self::key($old_handle);
|
||||||
if (!rsa_verify($signed_text, $signature, $key, "sha256")) {
|
if (!Crypto::rsaVerify($signed_text, $signature, $key, "sha256")) {
|
||||||
logger('No valid signature for migration.');
|
logger('No valid signature for migration.');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -3032,7 +3033,7 @@ class Diaspora
|
||||||
$user['uprvkey'] = $user['prvkey'];
|
$user['uprvkey'] = $user['prvkey'];
|
||||||
}
|
}
|
||||||
|
|
||||||
$signature = rsa_sign($signable_data, $user["uprvkey"]);
|
$signature = Crypto::rsaSign($signable_data, $user["uprvkey"]);
|
||||||
$sig = base64url_encode($signature);
|
$sig = base64url_encode($signature);
|
||||||
|
|
||||||
$xmldata = array("me:env" => array("me:data" => $data,
|
$xmldata = array("me:env" => array("me:data" => $data,
|
||||||
|
@ -3088,7 +3089,7 @@ class Diaspora
|
||||||
|
|
||||||
$signed_text = implode(";", $sigmsg);
|
$signed_text = implode(";", $sigmsg);
|
||||||
|
|
||||||
return base64_encode(rsa_sign($signed_text, $owner["uprvkey"], "sha256"));
|
return base64_encode(Crypto::rsaSign($signed_text, $owner["uprvkey"], "sha256"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -3282,7 +3283,7 @@ class Diaspora
|
||||||
$profile = self::createProfileData($uid);
|
$profile = self::createProfileData($uid);
|
||||||
|
|
||||||
$signed_text = 'AccountMigration:'.$old_handle.':'.$profile['author'];
|
$signed_text = 'AccountMigration:'.$old_handle.':'.$profile['author'];
|
||||||
$signature = base64_encode(rsa_sign($signed_text, $owner["uprvkey"], "sha256"));
|
$signature = base64_encode(Crypto::rsaSign($signed_text, $owner["uprvkey"], "sha256"));
|
||||||
|
|
||||||
$message = array("author" => $old_handle,
|
$message = array("author" => $old_handle,
|
||||||
"profile" => $profile,
|
"profile" => $profile,
|
||||||
|
|
|
@ -5,10 +5,9 @@
|
||||||
namespace Friendica\Protocol;
|
namespace Friendica\Protocol;
|
||||||
|
|
||||||
use Friendica\Network\Probe;
|
use Friendica\Network\Probe;
|
||||||
|
use Friendica\Util\Crypto;
|
||||||
use Friendica\Util\XML;
|
use Friendica\Util\XML;
|
||||||
|
|
||||||
require_once 'include/crypto.php';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Salmon Protocol class
|
* @brief Salmon Protocol class
|
||||||
* The Salmon Protocol is a message exchange protocol running over HTTP designed to decentralize commentary
|
* The Salmon Protocol is a message exchange protocol running over HTTP designed to decentralize commentary
|
||||||
|
@ -107,18 +106,18 @@ class Salmon
|
||||||
$data_type = 'application/atom+xml';
|
$data_type = 'application/atom+xml';
|
||||||
$encoding = 'base64url';
|
$encoding = 'base64url';
|
||||||
$algorithm = 'RSA-SHA256';
|
$algorithm = 'RSA-SHA256';
|
||||||
$keyhash = base64url_encode(hash('sha256', salmon_key($owner['spubkey'])), true);
|
$keyhash = base64url_encode(hash('sha256', Crypto::salmonKey($owner['spubkey'])), true);
|
||||||
|
|
||||||
$precomputed = '.' . base64url_encode($data_type) . '.' . base64url_encode($encoding) . '.' . base64url_encode($algorithm);
|
$precomputed = '.' . base64url_encode($data_type) . '.' . base64url_encode($encoding) . '.' . base64url_encode($algorithm);
|
||||||
|
|
||||||
// GNU Social format
|
// GNU Social format
|
||||||
$signature = base64url_encode(rsa_sign($data . $precomputed, $owner['sprvkey']));
|
$signature = base64url_encode(Crypto::rsaSign($data . $precomputed, $owner['sprvkey']));
|
||||||
|
|
||||||
// Compliant format
|
// Compliant format
|
||||||
$signature2 = base64url_encode(rsa_sign(str_replace('=', '', $data . $precomputed), $owner['sprvkey']));
|
$signature2 = base64url_encode(Crypto::rsaSign(str_replace('=', '', $data . $precomputed), $owner['sprvkey']));
|
||||||
|
|
||||||
// Old Status.net format
|
// Old Status.net format
|
||||||
$signature3 = base64url_encode(rsa_sign($data, $owner['sprvkey']));
|
$signature3 = base64url_encode(Crypto::rsaSign($data, $owner['sprvkey']));
|
||||||
|
|
||||||
// At first try the non compliant method that works for GNU Social
|
// At first try the non compliant method that works for GNU Social
|
||||||
$xmldata = array("me:env" => array("me:data" => $data,
|
$xmldata = array("me:env" => array("me:data" => $data,
|
||||||
|
|
260
src/Util/Crypto.php
Normal file
260
src/Util/Crypto.php
Normal file
|
@ -0,0 +1,260 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @file src/Util/Crypto.php
|
||||||
|
*/
|
||||||
|
namespace Friendica\Util;
|
||||||
|
|
||||||
|
use Friendica\Core\Config;
|
||||||
|
|
||||||
|
require_once 'library/ASNValue.class.php';
|
||||||
|
require_once 'library/asn1.php';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Crypto class
|
||||||
|
*/
|
||||||
|
class Crypto
|
||||||
|
{
|
||||||
|
// supported algorithms are 'sha256', 'sha1'
|
||||||
|
/**
|
||||||
|
* @param string $data data
|
||||||
|
* @param string $key key
|
||||||
|
* @param string $alg algorithm
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function rsaSign($data, $key, $alg = 'sha256')
|
||||||
|
{
|
||||||
|
openssl_sign($data, $sig, $key, (($alg == 'sha1') ? OPENSSL_ALGO_SHA1 : $alg));
|
||||||
|
return $sig;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $data data
|
||||||
|
* @param string $sig signature
|
||||||
|
* @param string $key key
|
||||||
|
* @param string $alg algorithm
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public static function rsaVerify($data, $sig, $key, $alg = 'sha256')
|
||||||
|
{
|
||||||
|
return openssl_verify($data, $sig, $key, (($alg == 'sha1') ? OPENSSL_ALGO_SHA1 : $alg));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $Der der formatted string
|
||||||
|
* @param string $Private key type optional, default false
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
private static function DerToPem($Der, $Private = false)
|
||||||
|
{
|
||||||
|
//Encode:
|
||||||
|
$Der = base64_encode($Der);
|
||||||
|
//Split lines:
|
||||||
|
$lines = str_split($Der, 65);
|
||||||
|
$body = implode("\n", $lines);
|
||||||
|
//Get title:
|
||||||
|
$title = $Private ? 'RSA PRIVATE KEY' : 'PUBLIC KEY';
|
||||||
|
//Add wrapping:
|
||||||
|
$result = "-----BEGIN {$title}-----\n";
|
||||||
|
$result .= $body . "\n";
|
||||||
|
$result .= "-----END {$title}-----\n";
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $Der der formatted string
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
private static function DerToRsa($Der)
|
||||||
|
{
|
||||||
|
//Encode:
|
||||||
|
$Der = base64_encode($Der);
|
||||||
|
//Split lines:
|
||||||
|
$lines = str_split($Der, 64);
|
||||||
|
$body = implode("\n", $lines);
|
||||||
|
//Get title:
|
||||||
|
$title = 'RSA PUBLIC KEY';
|
||||||
|
//Add wrapping:
|
||||||
|
$result = "-----BEGIN {$title}-----\n";
|
||||||
|
$result .= $body . "\n";
|
||||||
|
$result .= "-----END {$title}-----\n";
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $Modulus modulo
|
||||||
|
* @param string $PublicExponent exponent
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
private static function pkcs8Encode($Modulus, $PublicExponent)
|
||||||
|
{
|
||||||
|
//Encode key sequence
|
||||||
|
$modulus = new ASNValue(ASNValue::TAG_INTEGER);
|
||||||
|
$modulus->SetIntBuffer($Modulus);
|
||||||
|
$publicExponent = new ASNValue(ASNValue::TAG_INTEGER);
|
||||||
|
$publicExponent->SetIntBuffer($PublicExponent);
|
||||||
|
$keySequenceItems = array($modulus, $publicExponent);
|
||||||
|
$keySequence = new ASNValue(ASNValue::TAG_SEQUENCE);
|
||||||
|
$keySequence->SetSequence($keySequenceItems);
|
||||||
|
//Encode bit string
|
||||||
|
$bitStringValue = $keySequence->Encode();
|
||||||
|
$bitStringValue = chr(0x00) . $bitStringValue; //Add unused bits byte
|
||||||
|
$bitString = new ASNValue(ASNValue::TAG_BITSTRING);
|
||||||
|
$bitString->Value = $bitStringValue;
|
||||||
|
//Encode body
|
||||||
|
$bodyValue = "\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00" . $bitString->Encode();
|
||||||
|
$body = new ASNValue(ASNValue::TAG_SEQUENCE);
|
||||||
|
$body->Value = $bodyValue;
|
||||||
|
//Get DER encoded public key:
|
||||||
|
$PublicDER = $body->Encode();
|
||||||
|
return $PublicDER;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $Modulus modulo
|
||||||
|
* @param string $PublicExponent exponent
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
private static function pkcs1Encode($Modulus, $PublicExponent)
|
||||||
|
{
|
||||||
|
//Encode key sequence
|
||||||
|
$modulus = new ASNValue(ASNValue::TAG_INTEGER);
|
||||||
|
$modulus->SetIntBuffer($Modulus);
|
||||||
|
$publicExponent = new ASNValue(ASNValue::TAG_INTEGER);
|
||||||
|
$publicExponent->SetIntBuffer($PublicExponent);
|
||||||
|
$keySequenceItems = array($modulus, $publicExponent);
|
||||||
|
$keySequence = new ASNValue(ASNValue::TAG_SEQUENCE);
|
||||||
|
$keySequence->SetSequence($keySequenceItems);
|
||||||
|
//Encode bit string
|
||||||
|
$bitStringValue = $keySequence->Encode();
|
||||||
|
return $bitStringValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $m modulo
|
||||||
|
* @param string $e exponent
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function meToPem($m, $e)
|
||||||
|
{
|
||||||
|
$der = self::pkcs8Encode($m, $e);
|
||||||
|
$key = self::DerToPem($der, false);
|
||||||
|
return $key;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $key key
|
||||||
|
* @param string $m modulo reference
|
||||||
|
* @param object $e exponent reference
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private static function pubRsaToMe($key, &$m, &$e)
|
||||||
|
{
|
||||||
|
$lines = explode("\n", $key);
|
||||||
|
unset($lines[0]);
|
||||||
|
unset($lines[count($lines)]);
|
||||||
|
$x = base64_decode(implode('', $lines));
|
||||||
|
|
||||||
|
$r = ASN_BASE::parseASNString($x);
|
||||||
|
|
||||||
|
$m = base64url_decode($r[0]->asnData[0]->asnData);
|
||||||
|
$e = base64url_decode($r[0]->asnData[1]->asnData);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $key key
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function rsaToPem($key)
|
||||||
|
{
|
||||||
|
self::pubRsaToMe($key, $m, $e);
|
||||||
|
return self::meToPem($m, $e);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $key key
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
private static function pemToRsa($key)
|
||||||
|
{
|
||||||
|
self::pemToMe($key, $m, $e);
|
||||||
|
return self::meToRsa($m, $e);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $key key
|
||||||
|
* @param string $m modulo reference
|
||||||
|
* @param string $e exponent reference
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private static function pemToMe($key, &$m, &$e)
|
||||||
|
{
|
||||||
|
$lines = explode("\n", $key);
|
||||||
|
unset($lines[0]);
|
||||||
|
unset($lines[count($lines)]);
|
||||||
|
$x = base64_decode(implode('', $lines));
|
||||||
|
|
||||||
|
$r = ASN_BASE::parseASNString($x);
|
||||||
|
|
||||||
|
$m = base64url_decode($r[0]->asnData[1]->asnData[0]->asnData[0]->asnData);
|
||||||
|
$e = base64url_decode($r[0]->asnData[1]->asnData[0]->asnData[1]->asnData);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $m modulo
|
||||||
|
* @param string $e exponent
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
private static function meToRsa($m, $e)
|
||||||
|
{
|
||||||
|
$der = self::pkcs1Encode($m, $e);
|
||||||
|
$key = self::DerToRsa($der);
|
||||||
|
return $key;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $pubkey public key
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function salmonKey($pubkey)
|
||||||
|
{
|
||||||
|
self::pemToMe($pubkey, $m, $e);
|
||||||
|
return 'RSA' . '.' . base64url_encode($m, true) . '.' . base64url_encode($e, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param integer $bits number of bits
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public static function newKeypair($bits)
|
||||||
|
{
|
||||||
|
$openssl_options = array(
|
||||||
|
'digest_alg' => 'sha1',
|
||||||
|
'private_key_bits' => $bits,
|
||||||
|
'encrypt_key' => false
|
||||||
|
);
|
||||||
|
|
||||||
|
$conf = Config::get('system', 'openssl_conf_file');
|
||||||
|
if ($conf) {
|
||||||
|
$openssl_options['config'] = $conf;
|
||||||
|
}
|
||||||
|
$result = openssl_pkey_new($openssl_options);
|
||||||
|
|
||||||
|
if (empty($result)) {
|
||||||
|
logger('new_keypair: failed');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get private key
|
||||||
|
$response = array('prvkey' => '', 'pubkey' => '');
|
||||||
|
|
||||||
|
openssl_pkey_export($result, $response['prvkey']);
|
||||||
|
|
||||||
|
// Get public key
|
||||||
|
$pkey = openssl_pkey_get_details($result);
|
||||||
|
$response['pubkey'] = $pkey["key"];
|
||||||
|
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue