[Composer] Upgrade to phpseclib version 3
- Create custom Key file format for Salmon Magic key - Remove obsolete pemToME and MEtoPem Crypto methods - Remove unused newECKeypair Crypto method - Switch to constant-time Base64 encode/decode in Base64Url Strings methods
This commit is contained in:
parent
a3fb499735
commit
55640eec87
13 changed files with 241 additions and 173 deletions
|
@ -45,7 +45,7 @@
|
||||||
"paragonie/hidden-string": "^1.0",
|
"paragonie/hidden-string": "^1.0",
|
||||||
"patrickschur/language-detection": "^5.0.0",
|
"patrickschur/language-detection": "^5.0.0",
|
||||||
"pear/console_table": "^1.3",
|
"pear/console_table": "^1.3",
|
||||||
"phpseclib/phpseclib": "^2.0",
|
"phpseclib/phpseclib": "^3.0",
|
||||||
"pragmarx/google2fa": "^5.0",
|
"pragmarx/google2fa": "^5.0",
|
||||||
"pragmarx/recovery": "^0.2",
|
"pragmarx/recovery": "^0.2",
|
||||||
"psr/container": "^1.0",
|
"psr/container": "^1.0",
|
||||||
|
|
26
composer.lock
generated
26
composer.lock
generated
|
@ -4,7 +4,7 @@
|
||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "e8626dc6957dff9cc783daad10cfc26f",
|
"content-hash": "2e082bac083ca61cc0c22f7055d690bf",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "asika/simple-console",
|
"name": "asika/simple-console",
|
||||||
|
@ -2952,32 +2952,32 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phpseclib/phpseclib",
|
"name": "phpseclib/phpseclib",
|
||||||
"version": "2.0.38",
|
"version": "3.0.17",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/phpseclib/phpseclib.git",
|
"url": "https://github.com/phpseclib/phpseclib.git",
|
||||||
"reference": "b03536539f43a4f9aa33c4f0b2f3a1c752088fcd"
|
"reference": "dbc2307d5c69aeb22db136c52e91130d7f2ca761"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/b03536539f43a4f9aa33c4f0b2f3a1c752088fcd",
|
"url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/dbc2307d5c69aeb22db136c52e91130d7f2ca761",
|
||||||
"reference": "b03536539f43a4f9aa33c4f0b2f3a1c752088fcd",
|
"reference": "dbc2307d5c69aeb22db136c52e91130d7f2ca761",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=5.3.3"
|
"paragonie/constant_time_encoding": "^1|^2",
|
||||||
|
"paragonie/random_compat": "^1.4|^2.0|^9.99.99",
|
||||||
|
"php": ">=5.6.1"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"phing/phing": "~2.7",
|
"phpunit/phpunit": "*"
|
||||||
"phpunit/phpunit": "^4.8.35|^5.7|^6.0|^9.4",
|
|
||||||
"squizlabs/php_codesniffer": "~2.0"
|
|
||||||
},
|
},
|
||||||
"suggest": {
|
"suggest": {
|
||||||
|
"ext-dom": "Install the DOM extension to load XML formatted public keys.",
|
||||||
"ext-gmp": "Install the GMP (GNU Multiple Precision) extension in order to speed up arbitrary precision integer arithmetic operations.",
|
"ext-gmp": "Install the GMP (GNU Multiple Precision) extension in order to speed up arbitrary precision integer arithmetic operations.",
|
||||||
"ext-libsodium": "SSH2/SFTP can make use of some algorithms provided by the libsodium-php extension.",
|
"ext-libsodium": "SSH2/SFTP can make use of some algorithms provided by the libsodium-php extension.",
|
||||||
"ext-mcrypt": "Install the Mcrypt extension in order to speed up a few other cryptographic operations.",
|
"ext-mcrypt": "Install the Mcrypt extension in order to speed up a few other cryptographic operations.",
|
||||||
"ext-openssl": "Install the OpenSSL extension in order to speed up a wide variety of cryptographic operations.",
|
"ext-openssl": "Install the OpenSSL extension in order to speed up a wide variety of cryptographic operations."
|
||||||
"ext-xml": "Install the XML extension to load XML formatted public keys."
|
|
||||||
},
|
},
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"autoload": {
|
"autoload": {
|
||||||
|
@ -2985,7 +2985,7 @@
|
||||||
"phpseclib/bootstrap.php"
|
"phpseclib/bootstrap.php"
|
||||||
],
|
],
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
"phpseclib\\": "phpseclib/"
|
"phpseclib3\\": "phpseclib/"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
@ -3054,7 +3054,7 @@
|
||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2022-09-02T17:04:26+00:00"
|
"time": "2022-10-24T10:51:50+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "pragmarx/google2fa",
|
"name": "pragmarx/google2fa",
|
||||||
|
|
|
@ -142,14 +142,9 @@ class Salmon extends \Friendica\BaseModule
|
||||||
throw new HTTPException\BadRequestException();
|
throw new HTTPException\BadRequestException();
|
||||||
}
|
}
|
||||||
|
|
||||||
$key_info = explode('.', $key);
|
$this->logger->info('Key details', ['info' => $key]);
|
||||||
|
|
||||||
$m = Strings::base64UrlDecode($key_info[1]);
|
$pubkey = SalmonProtocol::magicKeyToPem($key);
|
||||||
$e = Strings::base64UrlDecode($key_info[2]);
|
|
||||||
|
|
||||||
$this->logger->info('Key details', ['info' => $key_info]);
|
|
||||||
|
|
||||||
$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.
|
||||||
|
|
||||||
|
|
|
@ -23,11 +23,9 @@ namespace Friendica\Module;
|
||||||
|
|
||||||
use Friendica\BaseModule;
|
use Friendica\BaseModule;
|
||||||
use Friendica\Core\System;
|
use Friendica\Core\System;
|
||||||
use Friendica\DI;
|
|
||||||
use Friendica\Model\User;
|
use Friendica\Model\User;
|
||||||
use Friendica\Network\HTTPException\BadRequestException;
|
use Friendica\Network\HTTPException\BadRequestException;
|
||||||
use Friendica\Util\Crypto;
|
use Friendica\Protocol\Salmon;
|
||||||
use Friendica\Util\Strings;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* prints the public RSA key of a user
|
* prints the public RSA key of a user
|
||||||
|
@ -47,9 +45,10 @@ class PublicRSAKey extends BaseModule
|
||||||
throw new BadRequestException();
|
throw new BadRequestException();
|
||||||
}
|
}
|
||||||
|
|
||||||
Crypto::pemToMe($user['spubkey'], $modulus, $exponent);
|
System::httpExit(
|
||||||
|
Salmon::salmonKey($user['spubkey']),
|
||||||
$content = 'RSA' . '.' . Strings::base64UrlEncode($modulus, true) . '.' . Strings::base64UrlEncode($exponent, true);
|
Response::TYPE_BLANK,
|
||||||
System::httpExit($content, Response::TYPE_BLANK, 'application/magic-public-key');
|
'application/magic-public-key'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,7 @@ use Friendica\Protocol\ActivityNamespace;
|
||||||
use Friendica\Protocol\ActivityPub;
|
use Friendica\Protocol\ActivityPub;
|
||||||
use Friendica\Protocol\Email;
|
use Friendica\Protocol\Email;
|
||||||
use Friendica\Protocol\Feed;
|
use Friendica\Protocol\Feed;
|
||||||
|
use Friendica\Protocol\Salmon;
|
||||||
use Friendica\Util\Crypto;
|
use Friendica\Util\Crypto;
|
||||||
use Friendica\Util\DateTimeFormat;
|
use Friendica\Util\DateTimeFormat;
|
||||||
use Friendica\Util\Network;
|
use Friendica\Util\Network;
|
||||||
|
@ -1512,12 +1513,10 @@ class Probe
|
||||||
$pubkey = $curlResult->getBody();
|
$pubkey = $curlResult->getBody();
|
||||||
}
|
}
|
||||||
|
|
||||||
$key = explode('.', $pubkey);
|
try {
|
||||||
|
$data['pubkey'] = Salmon::magicKeyToPem($pubkey);
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
|
||||||
if (sizeof($key) >= 3) {
|
|
||||||
$m = Strings::base64UrlDecode($key[1]);
|
|
||||||
$e = Strings::base64UrlDecode($key[2]);
|
|
||||||
$data['pubkey'] = Crypto::meToPem($m, $e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,9 +25,11 @@ use Friendica\Core\Logger;
|
||||||
use Friendica\DI;
|
use Friendica\DI;
|
||||||
use Friendica\Network\HTTPClient\Client\HttpClientAccept;
|
use Friendica\Network\HTTPClient\Client\HttpClientAccept;
|
||||||
use Friendica\Network\Probe;
|
use Friendica\Network\Probe;
|
||||||
|
use Friendica\Protocol\Salmon\Format\Magic;
|
||||||
use Friendica\Util\Crypto;
|
use Friendica\Util\Crypto;
|
||||||
use Friendica\Util\Strings;
|
use Friendica\Util\Strings;
|
||||||
use Friendica\Util\XML;
|
use Friendica\Util\XML;
|
||||||
|
use phpseclib3\Crypt\PublicKeyLoader;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Salmon Protocol class
|
* Salmon Protocol class
|
||||||
|
@ -243,7 +245,19 @@ class Salmon
|
||||||
*/
|
*/
|
||||||
public static function salmonKey(string $pubkey): string
|
public static function salmonKey(string $pubkey): string
|
||||||
{
|
{
|
||||||
Crypto::pemToMe($pubkey, $modulus, $exponent);
|
\phpseclib3\Crypt\RSA::addFileFormat(Magic::class);
|
||||||
return 'RSA' . '.' . Strings::base64UrlEncode($modulus, true) . '.' . Strings::base64UrlEncode($exponent, true);
|
|
||||||
|
return PublicKeyLoader::load($pubkey)->toString('Magic');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $magic Magic key format starting with "RSA."
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function magicKeyToPem(string $magic): string
|
||||||
|
{
|
||||||
|
\phpseclib3\Crypt\RSA::addFileFormat(Magic::class);
|
||||||
|
|
||||||
|
return (string) PublicKeyLoader::load($magic);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
77
src/Protocol/Salmon/Format/Magic.php
Normal file
77
src/Protocol/Salmon/Format/Magic.php
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @copyright Copyright (C) 2010-2022, the Friendica project
|
||||||
|
*
|
||||||
|
* @license GNU AGPL version 3 or any later version
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Friendica\Protocol\Salmon\Format;
|
||||||
|
|
||||||
|
use Friendica\Util\Strings;
|
||||||
|
use phpseclib3\Math\BigInteger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This custom public RSA key format class is meant to be used with the \phpseclib3\Crypto\RSA::addFileFormat method.
|
||||||
|
*
|
||||||
|
* It handles Salmon's specific magic key string starting with "RSA." and which MIME type is application/magic-key or
|
||||||
|
* application/magic-public-key
|
||||||
|
*
|
||||||
|
* @see https://web.archive.org/web/20160506073138/http://salmon-protocol.googlecode.com:80/svn/trunk/draft-panzer-magicsig-01.html#anchor13
|
||||||
|
*/
|
||||||
|
class Magic
|
||||||
|
{
|
||||||
|
public static function load($key, $password = ''): array
|
||||||
|
{
|
||||||
|
if (!is_string($key)) {
|
||||||
|
throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key));
|
||||||
|
}
|
||||||
|
|
||||||
|
$key_info = explode('.', $key);
|
||||||
|
|
||||||
|
if (count($key_info) !== 3) {
|
||||||
|
throw new \UnexpectedValueException('Key should have three components separated by periods');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($key_info[0] !== 'RSA') {
|
||||||
|
throw new \UnexpectedValueException('Key first component should be "RSA"');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (preg_match('#[+/]#', $key_info[1])
|
||||||
|
|| preg_match('#[+/]#', $key_info[1])
|
||||||
|
) {
|
||||||
|
throw new \UnexpectedValueException('Wrong encoding, expecting Base64URLencoding');
|
||||||
|
}
|
||||||
|
|
||||||
|
$m = Strings::base64UrlDecode($key_info[1]);
|
||||||
|
$e = Strings::base64UrlDecode($key_info[2]);
|
||||||
|
|
||||||
|
if (!$m || !$e) {
|
||||||
|
throw new \UnexpectedValueException('Base64 decoding produced an error');
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
'modulus' => new BigInteger($m, 256),
|
||||||
|
'publicExponent' => new BigInteger($e, 256),
|
||||||
|
'isPublicKey' => true,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function savePublicKey(BigInteger $n, BigInteger $e, array $options = []): string
|
||||||
|
{
|
||||||
|
return 'RSA.' . Strings::base64UrlEncode($n->toBytes(), true) . '.' . Strings::base64UrlEncode($e->toBytes(), true);
|
||||||
|
}
|
||||||
|
}
|
|
@ -21,14 +21,11 @@
|
||||||
|
|
||||||
namespace Friendica\Util;
|
namespace Friendica\Util;
|
||||||
|
|
||||||
use Exception;
|
|
||||||
use Friendica\Core\Hook;
|
use Friendica\Core\Hook;
|
||||||
use Friendica\Core\Logger;
|
use Friendica\Core\Logger;
|
||||||
use Friendica\Core\System;
|
use Friendica\Core\System;
|
||||||
use Friendica\DI;
|
use Friendica\DI;
|
||||||
use ParagonIE\ConstantTime\Base64UrlSafe;
|
use phpseclib3\Crypt\PublicKeyLoader;
|
||||||
use phpseclib\Crypt\RSA;
|
|
||||||
use phpseclib\Math\BigInteger;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Crypto class
|
* Crypto class
|
||||||
|
@ -66,22 +63,6 @@ class Crypto
|
||||||
return openssl_verify($data, $sig, $key, (($alg == 'sha1') ? OPENSSL_ALGO_SHA1 : $alg));
|
return openssl_verify($data, $sig, $key, (($alg == 'sha1') ? OPENSSL_ALGO_SHA1 : $alg));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
/**
|
|
||||||
* @param string $m modulo
|
|
||||||
* @param string $e exponent
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public static function meToPem($m, $e)
|
|
||||||
{
|
|
||||||
$rsa = new RSA();
|
|
||||||
$rsa->loadKey([
|
|
||||||
'e' => new BigInteger($e, 256),
|
|
||||||
'n' => new BigInteger($m, 256)
|
|
||||||
]);
|
|
||||||
return $rsa->getPublicKey();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transform RSA public keys to standard PEM output
|
* Transform RSA public keys to standard PEM output
|
||||||
*
|
*
|
||||||
|
@ -91,29 +72,7 @@ class Crypto
|
||||||
*/
|
*/
|
||||||
public static function rsaToPem(string $key)
|
public static function rsaToPem(string $key)
|
||||||
{
|
{
|
||||||
$rsa = new RSA();
|
return (string)PublicKeyLoader::load($key);
|
||||||
$rsa->setPublicKey($key);
|
|
||||||
|
|
||||||
return $rsa->getPublicKey(RSA::PUBLIC_FORMAT_PKCS8);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extracts the modulo and exponent reference from a public PEM key
|
|
||||||
*
|
|
||||||
* @param string $key public PEM key
|
|
||||||
* @param string $modulus (ref) modulo reference
|
|
||||||
* @param string $exponent (ref) exponent reference
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public static function pemToMe(string $key, &$modulus, &$exponent)
|
|
||||||
{
|
|
||||||
$rsa = new RSA();
|
|
||||||
$rsa->loadKey($key);
|
|
||||||
$rsa->setPublicKey();
|
|
||||||
|
|
||||||
$modulus = $rsa->modulus->toBytes();
|
|
||||||
$exponent = $rsa->exponent->toBytes();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -152,50 +111,6 @@ class Crypto
|
||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new elliptic curve key pair
|
|
||||||
*
|
|
||||||
* @return array with the elements "prvkey", "pubkey", "vapid-public" and "vapid-private"
|
|
||||||
*/
|
|
||||||
public static function newECKeypair()
|
|
||||||
{
|
|
||||||
$openssl_options = [
|
|
||||||
'curve_name' => 'prime256v1',
|
|
||||||
'private_key_type' => OPENSSL_KEYTYPE_EC
|
|
||||||
];
|
|
||||||
|
|
||||||
$conf = DI::config()->get('system', 'openssl_conf_file');
|
|
||||||
if ($conf) {
|
|
||||||
$openssl_options['config'] = $conf;
|
|
||||||
}
|
|
||||||
$result = openssl_pkey_new($openssl_options);
|
|
||||||
|
|
||||||
if (empty($result)) {
|
|
||||||
throw new Exception('Key creation failed');
|
|
||||||
}
|
|
||||||
|
|
||||||
$response = ['prvkey' => '', 'pubkey' => ''];
|
|
||||||
|
|
||||||
// Get private key
|
|
||||||
openssl_pkey_export($result, $response['prvkey']);
|
|
||||||
|
|
||||||
// Get public key
|
|
||||||
$pkey = openssl_pkey_get_details($result);
|
|
||||||
$response['pubkey'] = $pkey['key'];
|
|
||||||
|
|
||||||
// Create VAPID keys
|
|
||||||
// @see https://github.com/web-push-libs/web-push-php/blob/256a18b2a2411469c94943725fb6eccb9681bd75/src/Utils.php#L60-L62
|
|
||||||
$hexString = '04';
|
|
||||||
$hexString .= str_pad(bin2hex($pkey['ec']['x']), 64, '0', STR_PAD_LEFT);
|
|
||||||
$hexString .= str_pad(bin2hex($pkey['ec']['y']), 64, '0', STR_PAD_LEFT);
|
|
||||||
$response['vapid-public'] = Base64UrlSafe::encode(hex2bin($hexString));
|
|
||||||
|
|
||||||
// @see https://github.com/web-push-libs/web-push-php/blob/256a18b2a2411469c94943725fb6eccb9681bd75/src/VAPID.php
|
|
||||||
$response['vapid-private'] = Base64UrlSafe::encode(hex2bin(str_pad(bin2hex($pkey['ec']['d']), 64, '0', STR_PAD_LEFT)));
|
|
||||||
|
|
||||||
return $response;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encrypt a string with 'aes-256-cbc' cipher method.
|
* Encrypt a string with 'aes-256-cbc' cipher method.
|
||||||
*
|
*
|
||||||
|
|
|
@ -23,6 +23,7 @@ namespace Friendica\Util;
|
||||||
|
|
||||||
use Friendica\Content\ContactSelector;
|
use Friendica\Content\ContactSelector;
|
||||||
use Friendica\Core\Logger;
|
use Friendica\Core\Logger;
|
||||||
|
use ParagonIE\ConstantTime\Base64;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class handles string functions
|
* This class handles string functions
|
||||||
|
@ -245,16 +246,17 @@ class Strings
|
||||||
* @param string $s URL to encode
|
* @param string $s URL to encode
|
||||||
* @param boolean $strip_padding Optional. Default false
|
* @param boolean $strip_padding Optional. Default false
|
||||||
* @return string Encoded URL
|
* @return string Encoded URL
|
||||||
|
* @see https://web.archive.org/web/20160506073138/http://salmon-protocol.googlecode.com:80/svn/trunk/draft-panzer-magicsig-01.html#params
|
||||||
*/
|
*/
|
||||||
public static function base64UrlEncode(string $s, bool $strip_padding = false): string
|
public static function base64UrlEncode(string $s, bool $strip_padding = false): string
|
||||||
{
|
{
|
||||||
$s = strtr(base64_encode($s), '+/', '-_');
|
|
||||||
|
|
||||||
if ($strip_padding) {
|
if ($strip_padding) {
|
||||||
$s = str_replace('=', '', $s);
|
$s = Base64::encodeUnpadded($s);
|
||||||
|
} else {
|
||||||
|
$s = Base64::encode($s);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $s;
|
return strtr($s, '+/', '-_');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -263,26 +265,11 @@ class Strings
|
||||||
* @param string $s URL to decode
|
* @param string $s URL to decode
|
||||||
* @return string Decoded URL
|
* @return string Decoded URL
|
||||||
* @throws \Exception
|
* @throws \Exception
|
||||||
|
* @see https://web.archive.org/web/20160506073138/http://salmon-protocol.googlecode.com:80/svn/trunk/draft-panzer-magicsig-01.html#params
|
||||||
*/
|
*/
|
||||||
public static function base64UrlDecode(string $s): string
|
public static function base64UrlDecode(string $s): string
|
||||||
{
|
{
|
||||||
/*
|
return Base64::decode(strtr($s, '-_', '+/'));
|
||||||
* // Placeholder for new rev of salmon which strips base64 padding.
|
|
||||||
* // PHP base64_decode handles the un-padded input without requiring this step
|
|
||||||
* // Uncomment if you find you need it.
|
|
||||||
*
|
|
||||||
* $l = strlen($s);
|
|
||||||
* if (!strpos($s,'=')) {
|
|
||||||
* $m = $l % 4;
|
|
||||||
* if ($m == 2)
|
|
||||||
* $s .= '==';
|
|
||||||
* if ($m == 3)
|
|
||||||
* $s .= '=';
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
return base64_decode(strtr($s, '-_', '+/'));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
1
tests/datasets/crypto/rsa/salmon-public-magic
Normal file
1
tests/datasets/crypto/rsa/salmon-public-magic
Normal file
|
@ -0,0 +1 @@
|
||||||
|
RSA.tvsoBZbLUvqWs-0d8C5hVQLjLCjjxyZb17Rm8_9FDqBYUigBSFDcJCzG27FM-zuddwpgJB0vDuPKQnt59kKRsw.AQAB
|
4
tests/datasets/crypto/rsa/salmon-public-pem
Normal file
4
tests/datasets/crypto/rsa/salmon-public-pem
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
-----BEGIN PUBLIC KEY-----
|
||||||
|
MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBALb7KAWWy1L6lrPtHfAuYVUC4ywo48cm
|
||||||
|
W9e0ZvP/RQ6gWFIoAUhQ3CQsxtuxTPs7nXcKYCQdLw7jykJ7efZCkbMCAwEAAQ==
|
||||||
|
-----END PUBLIC KEY-----
|
105
tests/src/Protocol/SalmonTest.php
Normal file
105
tests/src/Protocol/SalmonTest.php
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @copyright Copyright (C) 2010-2022, the Friendica project
|
||||||
|
*
|
||||||
|
* @license GNU AGPL version 3 or any later version
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Friendica\Test\src\Protocol;
|
||||||
|
|
||||||
|
use Friendica\Protocol\Salmon;
|
||||||
|
|
||||||
|
class SalmonTest extends \PHPUnit\Framework\TestCase
|
||||||
|
{
|
||||||
|
public function dataMagic(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'salmon' => [
|
||||||
|
'magic' => file_get_contents(__DIR__ . '/../../datasets/crypto/rsa/salmon-public-magic'),
|
||||||
|
'pem' => file_get_contents(__DIR__ . '/../../datasets/crypto/rsa/salmon-public-pem'),
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider dataMagic
|
||||||
|
*
|
||||||
|
* @param $magic
|
||||||
|
* @param $pem
|
||||||
|
* @return void
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
|
public function testSalmonKey($magic, $pem)
|
||||||
|
{
|
||||||
|
$this->assertEquals($magic, Salmon::salmonKey($pem));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider dataMagic
|
||||||
|
*
|
||||||
|
* @param $magic
|
||||||
|
* @param $pem
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function testMagicKeyToPem($magic, $pem)
|
||||||
|
{
|
||||||
|
$this->assertEquals($pem, Salmon::magicKeyToPem($magic));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function dataMagicFailure(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'empty string' => [
|
||||||
|
'magic' => '',
|
||||||
|
],
|
||||||
|
'Missing algo' => [
|
||||||
|
'magic' => 'tvsoBZbLUvqWs-0d8C5hVQLjLCjjxyZb17Rm8_9FDqBYUigBSFDcJCzG27FM-zuddwpgJB0vDuPKQnt59kKRsw.AQAB',
|
||||||
|
],
|
||||||
|
'Missing modulus' => [
|
||||||
|
'magic' => 'RSA.AQAB',
|
||||||
|
],
|
||||||
|
'Missing exponent' => [
|
||||||
|
'magic' => 'RSA.tvsoBZbLUvqWs-0d8C5hVQLjLCjjxyZb17Rm8_9FDqBYUigBSFDcJCzG27FM-zuddwpgJB0vDuPKQnt59kKRsw',
|
||||||
|
],
|
||||||
|
'Missing key parts' => [
|
||||||
|
'magic' => 'RSA.',
|
||||||
|
],
|
||||||
|
'Too many parts' => [
|
||||||
|
'magic' => 'RSA.tvsoBZbLUvqWs-0d8C5hVQLjLCjjxyZb17Rm8_9FDqBYUigBSFDcJCzG27FM-zuddwpgJB0vDuPKQnt59kKRsw.AQAB.AQAB',
|
||||||
|
],
|
||||||
|
'Wrong encoding' => [
|
||||||
|
'magic' => 'RSA.tvsoBZbLUvqWs-0d8C5hVQLjLCjjxyZb17Rm8/9FDqBYUigBSFDcJCzG27FM+zuddwpgJB0vDuPKQnt59kKRsw.AQAB',
|
||||||
|
],
|
||||||
|
'Wrong algo' => [
|
||||||
|
'magic' => 'ECDSA.tvsoBZbLUvqWs-0d8C5hVQLjLCjjxyZb17Rm8_9FDqBYUigBSFDcJCzG27FM-zuddwpgJB0vDuPKQnt59kKRsw.AQAB',
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider dataMagicFailure
|
||||||
|
*
|
||||||
|
* @param $magic
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function testMagicKeyToPemFailure($magic)
|
||||||
|
{
|
||||||
|
$this->expectException(\Throwable::class);
|
||||||
|
|
||||||
|
Salmon::magicKeyToPem($magic);
|
||||||
|
}
|
||||||
|
}
|
|
@ -65,7 +65,7 @@ class CryptoTest extends TestCase
|
||||||
self::assertEquals(11111111, $test);
|
self::assertEquals(11111111, $test);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function dataRsa()
|
public function dataRsa(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'diaspora' => [
|
'diaspora' => [
|
||||||
|
@ -92,34 +92,6 @@ class CryptoTest extends TestCase
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @dataProvider dataPEM
|
|
||||||
*/
|
|
||||||
public function testPemToMe(string $key)
|
|
||||||
{
|
|
||||||
Crypto::pemToMe($key, $m, $e);
|
|
||||||
|
|
||||||
$expectedRSA = new RSA();
|
|
||||||
$expectedRSA->loadKey([
|
|
||||||
'e' => new BigInteger($e, 256),
|
|
||||||
'n' => new BigInteger($m, 256)
|
|
||||||
]);
|
|
||||||
|
|
||||||
self::assertEquals($expectedRSA->getPublicKey(), $key);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @dataProvider dataPEM
|
|
||||||
*/
|
|
||||||
public function testMeToPem(string $key)
|
|
||||||
{
|
|
||||||
Crypto::pemToMe($key, $m, $e);
|
|
||||||
|
|
||||||
$checkKey = Crypto::meToPem($m, $e);
|
|
||||||
|
|
||||||
self::assertEquals($key, $checkKey);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in a new issue