"npm-asset/moment": "^2.24",
"npm-asset/perfect-scrollbar": "0.6.16",
"npm-asset/textcomplete": "^0.18.2",
- "npm-asset/typeahead.js": "^0.11.1"
+ "npm-asset/typeahead.js": "^0.11.1",
+ "phpseclib/phpseclib": "^2.0"
},
"repositories": [
{
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "7d1fe40c28d815b56d0b5cb323860b26",
+ "content-hash": "ffe94190e166cebf80601fc3d6d26be0",
"packages": [
{
"name": "asika/simple-console",
"homepage": "http://pear.php.net/package/Text_LanguageDetect",
"time": "2020-05-17T12:19:40+00:00"
},
+ {
+ "name": "phpseclib/phpseclib",
+ "version": "2.0.29",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phpseclib/phpseclib.git",
+ "reference": "497856a8d997f640b4a516062f84228a772a48a8"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/497856a8d997f640b4a516062f84228a772a48a8",
+ "reference": "497856a8d997f640b4a516062f84228a772a48a8",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "require-dev": {
+ "phing/phing": "~2.7",
+ "phpunit/phpunit": "^4.8.35|^5.7|^6.0",
+ "squizlabs/php_codesniffer": "~2.0"
+ },
+ "suggest": {
+ "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-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."
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "phpseclib/bootstrap.php"
+ ],
+ "psr-4": {
+ "phpseclib\\": "phpseclib/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Jim Wigginton",
+ "email": "terrafrost@php.net",
+ "role": "Lead Developer"
+ },
+ {
+ "name": "Patrick Monnerat",
+ "email": "pm@datasphere.ch",
+ "role": "Developer"
+ },
+ {
+ "name": "Andreas Fischer",
+ "email": "bantu@phpbb.com",
+ "role": "Developer"
+ },
+ {
+ "name": "Hans-Jürgen Petrich",
+ "email": "petrich@tronic-media.com",
+ "role": "Developer"
+ },
+ {
+ "name": "Graham Campbell",
+ "email": "graham@alt-three.com",
+ "role": "Developer"
+ }
+ ],
+ "description": "PHP Secure Communications Library - Pure-PHP implementations of RSA, AES, SSH2, SFTP, X.509 etc.",
+ "homepage": "http://phpseclib.sourceforge.net",
+ "keywords": [
+ "BigInteger",
+ "aes",
+ "asn.1",
+ "asn1",
+ "blowfish",
+ "crypto",
+ "cryptography",
+ "encryption",
+ "rsa",
+ "security",
+ "sftp",
+ "signature",
+ "signing",
+ "ssh",
+ "twofish",
+ "x.509",
+ "x509"
+ ],
+ "funding": [
+ {
+ "url": "https://github.com/terrafrost",
+ "type": "github"
+ },
+ {
+ "url": "https://www.patreon.com/phpseclib",
+ "type": "patreon"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/phpseclib/phpseclib",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2020-09-08T04:24:43+00:00"
+ },
{
"name": "pragmarx/google2fa",
"version": "v5.0.0",
+++ /dev/null
-<?php
-
-// ASN.1 parsing library
-// Attribution: http://www.krisbailey.com
-// license: unknown
-// modified: Mike Macgrivin mike@macgirvin.com 6-oct-2010 to support Salmon auto-discovery
-// modified: Tobias Diekershoff 28-jul-2016 adding an intval in line 162 to make PHP7 happy
-// from openssl public keys
-
-
-class ASN_BASE {
- public $asnData = null;
- private $cursor = 0;
- private $parent = null;
-
- public static $ASN_MARKERS = array(
- 'ASN_UNIVERSAL' => 0x00,
- 'ASN_APPLICATION' => 0x40,
- 'ASN_CONTEXT' => 0x80,
- 'ASN_PRIVATE' => 0xC0,
-
- 'ASN_PRIMITIVE' => 0x00,
- 'ASN_CONSTRUCTOR' => 0x20,
-
- 'ASN_LONG_LEN' => 0x80,
- 'ASN_EXTENSION_ID' => 0x1F,
- 'ASN_BIT' => 0x80,
- );
-
- public static $ASN_TYPES = array(
- 1 => 'ASN_BOOLEAN',
- 2 => 'ASN_INTEGER',
- 3 => 'ASN_BIT_STR',
- 4 => 'ASN_OCTET_STR',
- 5 => 'ASN_NULL',
- 6 => 'ASN_OBJECT_ID',
- 9 => 'ASN_REAL',
- 10 => 'ASN_ENUMERATED',
- 13 => 'ASN_RELATIVE_OID',
- 48 => 'ASN_SEQUENCE',
- 49 => 'ASN_SET',
- 19 => 'ASN_PRINT_STR',
- 22 => 'ASN_IA5_STR',
- 23 => 'ASN_UTC_TIME',
- 24 => 'ASN_GENERAL_TIME',
- );
-
- function __construct($v = false)
- {
- if (false !== $v) {
- $this->asnData = $v;
- if (is_array($this->asnData)) {
- foreach ($this->asnData as $key => $value) {
- if (is_object($value)) {
- $this->asnData[$key]->setParent($this);
- }
- }
- } else {
- if (is_object($this->asnData)) {
- $this->asnData->setParent($this);
- }
- }
- }
- }
-
- public function setParent($parent)
- {
- if (false !== $parent) {
- $this->parent = $parent;
- }
- }
-
- /**
- * This function will take the markers and types arrays and
- * dynamically generate classes that extend this class for each one,
- * and also define constants for them.
- */
- public static function generateSubclasses()
- {
- define('ASN_BASE', 0);
- foreach (self::$ASN_MARKERS as $name => $bit)
- self::makeSubclass($name, $bit);
- foreach (self::$ASN_TYPES as $bit => $name)
- self::makeSubclass($name, $bit);
- }
-
- /**
- * Helper function for generateSubclasses()
- */
- public static function makeSubclass($name, $bit)
- {
- define($name, $bit);
- eval("class ".$name." extends ASN_BASE {}");
- }
-
- /**
- * This function reset's the internal cursor used for value iteration.
- */
- public function reset()
- {
- $this->cursor = 0;
- }
-
- /**
- * This function catches calls to get the value for the type, typeName, value, values, and data
- * from the object. For type calls we just return the class name or the value of the constant that
- * is named the same as the class.
- */
- public function __get($name)
- {
- if ('type' == $name) {
- // int flag of the data type
- return constant(get_class($this));
- } elseif ('typeName' == $name) {
- // name of the data type
- return get_class($this);
- } elseif ('value' == $name) {
- // will always return one value and can be iterated over with:
- // while ($v = $obj->value) { ...
- // because $this->asnData["invalid key"] will return false
- return is_array($this->asnData) ? $this->asnData[$this->cursor++] : $this->asnData;
- } elseif ('values' == $name) {
- // will always return an array
- return is_array($this->asnData) ? $this->asnData : array($this->asnData);
- } elseif ('data' == $name) {
- // will always return the raw data
- return $this->asnData;
- }
- }
-
- /**
- * Parse an ASN.1 binary string.
- *
- * This function takes a binary ASN.1 string and parses it into it's respective
- * pieces and returns it. It can optionally stop at any depth.
- *
- * @param string $string The binary ASN.1 String
- * @param int $level The current parsing depth level
- * @param int $maxLevel The max parsing depth level
- * @return ASN_BASE The array representation of the ASN.1 data contained in $string
- */
- public static function parseASNString($string=false, $level=1, $maxLevels=false){
- if (!class_exists('ASN_UNIVERSAL'))
- self::generateSubclasses();
- if ($level>$maxLevels && $maxLevels)
- return array(new ASN_BASE($string));
- $parsed = array();
- $endLength = strlen($string);
- $bigLength = $length = $type = $dtype = $p = 0;
- while ($p<$endLength){
- $type = ord($string[$p++]);
- $dtype = ($type & 192) >> 6;
- if ($type==0){ // if we are type 0, just continue
- } else {
- $length = ord($string[$p++]);
- if (($length & ASN_LONG_LEN)==ASN_LONG_LEN){
- $tempLength = 0;
- for ($x=0; $x<($length & (ASN_LONG_LEN-1)); $x++){
- $tempLength = @ord($string[$p++]) + ($tempLength * 256);
- }
- $length = $tempLength;
- }
- $data = substr($string, $p, intval($length));
- $parsed[] = self::parseASNData($type, $data, $level, $maxLevels);
- $p = $p + $length;
- }
- }
- return $parsed;
- }
-
- /**
- * Parse an ASN.1 field value.
- *
- * This function takes a binary ASN.1 value and parses it according to it's specified type
- *
- * @param int $type The type of data being provided
- * @param string $data The raw binary data string
- * @param int $level The current parsing depth
- * @param int $maxLevels The max parsing depth
- * @return mixed The data that was parsed from the raw binary data string
- */
- public static function parseASNData($type, $data, $level, $maxLevels){
- $type = $type%50; // strip out context
- switch ($type){
- default:
- return new ASN_BASE($data);
- case ASN_BOOLEAN:
- return new ASN_BOOLEAN((bool)$data);
- case ASN_INTEGER:
- return new ASN_INTEGER(strtr(base64_encode($data),'+/','-_'));
- case ASN_BIT_STR:
- return new ASN_BIT_STR(self::parseASNString($data, $level+1, $maxLevels));
- case ASN_OCTET_STR:
- return new ASN_OCTET_STR($data);
- case ASN_NULL:
- return new ASN_NULL(null);
- case ASN_REAL:
- return new ASN_REAL($data);
- case ASN_ENUMERATED:
- return new ASN_ENUMERATED(self::parseASNString($data, $level+1, $maxLevels));
- case ASN_RELATIVE_OID: // I don't really know how this works and don't have an example :-)
- // so, lets just return it ...
- return new ASN_RELATIVE_OID($data);
- case ASN_SEQUENCE:
- return new ASN_SEQUENCE(self::parseASNString($data, $level+1, $maxLevels));
- case ASN_SET:
- return new ASN_SET(self::parseASNString($data, $level+1, $maxLevels));
- case ASN_PRINT_STR:
- return new ASN_PRINT_STR($data);
- case ASN_IA5_STR:
- return new ASN_IA5_STR($data);
- case ASN_UTC_TIME:
- return new ASN_UTC_TIME($data);
- case ASN_GENERAL_TIME:
- return new ASN_GENERAL_TIME($data);
- case ASN_OBJECT_ID:
- return new ASN_OBJECT_ID(self::parseOID($data));
- }
- }
-
- /**
- * Parse an ASN.1 OID value.
- *
- * This takes the raw binary string that represents an OID value and parses it into its
- * dot notation form. example - 1.2.840.113549.1.1.5
- * look up OID's here: http://www.oid-info.com/
- * (the multi-byte OID section can be done in a more efficient way, I will fix it later)
- *
- * @param string $data The raw binary data string
- * @return string The OID contained in $data
- */
- public static function parseOID($string){
- $ret = floor(ord($string[0])/40).".";
- $ret .= (ord($string[0]) % 40);
- $build = array();
- $cs = 0;
-
- for ($i=1; $i<strlen($string); $i++){
- $v = ord($string[$i]);
- if ($v>127){
- $build[] = ord($string[$i])-ASN_BIT;
- } elseif ($build){
- // do the build here for multibyte values
- $build[] = ord($string[$i])-ASN_BIT;
- // you know, it seems there should be a better way to do this...
- $build = array_reverse($build);
- $num = 0;
- for ($x=0; $x<count($build); $x++){
- $mult = $x==0?1:pow(256, $x);
- if ($x+1==count($build)){
- $value = ((($build[$x] & (ASN_BIT-1)) >> $x)) * $mult;
- } else {
- $value = ((($build[$x] & (ASN_BIT-1)) >> $x) ^ ($build[$x+1] << (7 - $x) & 255)) * $mult;
- }
- $num += $value;
- }
- $ret .= ".".$num;
- $build = array(); // start over
- } else {
- $ret .= ".".$v;
- $build = array();
- }
- }
- return $ret;
- }
-
- public static function printASN($x, $indent=''){
- if (is_object($x)) {
- echo $indent.$x->typeName."\n";
- if (ASN_NULL == $x->type) return;
- if (is_array($x->data)) {
- while ($d = $x->value) {
- echo self::printASN($d, $indent.'. ');
- }
- $x->reset();
- } else {
- echo self::printASN($x->data, $indent.'. ');
- }
- } elseif (is_array($x)) {
- foreach ($x as $d) {
- echo self::printASN($d, $indent);
- }
- } else {
- if (preg_match('/[^[:print:]]/', $x)) // if we have non-printable characters that would
- $x = base64_encode($x); // mess up the console, then print the base64 of them...
- echo $indent.$x."\n";
- }
- }
-
-
-}
-
namespace Friendica\Module;
-use ASN_BASE;
use Friendica\BaseModule;
use Friendica\DI;
use Friendica\Model\User;
use Friendica\Network\HTTPException\BadRequestException;
+use Friendica\Util\Crypto;
+use Friendica\Util\Strings;
+use phpseclib\File\ASN1;
/**
* prints the public RSA key of a user
throw new BadRequestException();
}
- $lines = explode("\n", $user['spubkey']);
- unset($lines[0]);
- unset($lines[count($lines)]);
-
- $asnString = base64_decode(implode('', $lines));
- $asnBase = ASN_BASE::parseASNString($asnString);
-
- $m = $asnBase[0]->asnData[1]->asnData[0]->asnData[0]->asnData;
- $e = $asnBase[0]->asnData[1]->asnData[0]->asnData[1]->asnData;
+ Crypto::pemToMe($user['spubkey'], $modulus, $exponent);
header('Content-type: application/magic-public-key');
- echo 'RSA' . '.' . $m . '.' . $e;
+ echo 'RSA' . '.' . Strings::base64UrlEncode($modulus, true) . '.' . Strings::base64UrlEncode($exponent, true);
exit();
}
*/
public static function salmonKey($pubkey)
{
- Crypto::pemToMe($pubkey, $m, $e);
- return 'RSA' . '.' . Strings::base64UrlEncode($m, true) . '.' . Strings::base64UrlEncode($e, true);
+ Crypto::pemToMe($pubkey, $modulus, $exponent);
+ return 'RSA' . '.' . Strings::base64UrlEncode($modulus, true) . '.' . Strings::base64UrlEncode($exponent, true);
}
}
namespace Friendica\Util;
-use ASN_BASE;
use ASNValue;
use Friendica\Core\Hook;
use Friendica\Core\Logger;
use Friendica\Core\System;
use Friendica\DI;
+use phpseclib\Crypt\RSA;
/**
* Crypto class
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 $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 = [$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
}
/**
- * @param string $key key
- * @param string $m modulo reference
- * @param object $e exponent reference
- * @return void
- * @throws \Exception
- */
- 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 = Strings::base64UrlDecode($r[0]->asnData[0]->asnData);
- $e = Strings::base64UrlDecode($r[0]->asnData[1]->asnData);
- }
-
- /**
- * @param string $key key
- * @return string
- * @throws \Exception
+ * Transform RSA public keys to standard PEM output
+ *
+ * @param string $key A RSA public key
+ *
+ * @return string The PEM output of this key
*/
- public static function rsaToPem($key)
+ public static function rsaToPem(string $key)
{
- self::pubRsaToMe($key, $m, $e);
- return self::meToPem($m, $e);
- }
+ $publicKey = new RSA();
+ $publicKey->setPublicKey($key);
- /**
- * @param string $key key
- * @return string
- * @throws \Exception
- */
- private static function pemToRsa($key)
- {
- self::pemToMe($key, $m, $e);
- return self::meToRsa($m, $e);
+ return $publicKey->getPublicKey(RSA::PUBLIC_FORMAT_PKCS8);
}
/**
- * @param string $key key
- * @param string $m modulo reference
- * @param string $e exponent reference
+ * 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
- * @throws \Exception
*/
- public static function pemToMe($key, &$m, &$e)
+ public static function pemToMe(string $key, string &$modulus, string &$exponent)
{
- $lines = explode("\n", $key);
- unset($lines[0]);
- unset($lines[count($lines)]);
- $x = base64_decode(implode('', $lines));
-
- $r = ASN_BASE::parseASNString($x);
-
- if (isset($r[0])) {
- $m = Strings::base64UrlDecode($r[0]->asnData[1]->asnData[0]->asnData[0]->asnData);
- $e = Strings::base64UrlDecode($r[0]->asnData[1]->asnData[0]->asnData[1]->asnData);
- }
- }
+ $publicKey = new RSA();
+ $publicKey->loadKey($key);
+ $publicKey->setPublicKey();
- /**
- * @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;
+ $modulus = $publicKey->modulus->toBytes();
+ $exponent = $publicKey->exponent->toBytes();
}
/**
return openssl_decrypt($data, 'aes-256-cbc', str_pad($key, 32, "\0"), OPENSSL_RAW_DATA, str_pad($iv, 16, "\0"));
}
- /**
- * Encrypt a string with 'aes-256-ctr' cipher method.
- *
- * Ported from Hubzilla: https://framagit.org/hubzilla/core/blob/master/include/crypto.php
- *
- * @param string $data
- * @param string $key The key used for encryption.
- * @param string $iv A non-NULL Initialization Vector.
- *
- * @return string|boolean Encrypted string or false on failure.
- */
- private static function encryptAES256CTR($data, $key, $iv)
- {
- $key = substr($key, 0, 32);
- $iv = substr($iv, 0, 16);
- return openssl_encrypt($data, 'aes-256-ctr', str_pad($key, 32, "\0"), OPENSSL_RAW_DATA, str_pad($iv, 16, "\0"));
- }
-
- /**
- * Decrypt a string with 'aes-256-ctr' cipher method.
- *
- * Ported from Hubzilla: https://framagit.org/hubzilla/core/blob/master/include/crypto.php
- *
- * @param string $data
- * @param string $key The key used for decryption.
- * @param string $iv A non-NULL Initialization Vector.
- *
- * @return string|boolean Decrypted string or false on failure.
- */
- private static function decryptAES256CTR($data, $key, $iv)
- {
- $key = substr($key, 0, 32);
- $iv = substr($iv, 0, 16);
- return openssl_decrypt($data, 'aes-256-ctr', str_pad($key, 32, "\0"), OPENSSL_RAW_DATA, str_pad($iv, 16, "\0"));
- }
-
/**
*
* Ported from Hubzilla: https://framagit.org/hubzilla/core/blob/master/include/crypto.php
--- /dev/null
+-----BEGIN PUBLIC KEY-----\r
+MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDReSjW7O4u4tK+UGKwogyw4Dok\r
+j1Z4f70INc4CTlHk2sngzTa3uMzk1EU+9nYigqMfI1/DYoSCC0ZqikvZVGkrMJj6\r
+khM7orTasR4Av9Sn54rOQaM+raUC3JXd9AdkdXx1IBC71cAXVqIg/ERCrrUpxDxc\r
+E6VXs4mFWpDHJ4q01QIDAQAB\r
+-----END PUBLIC KEY-----
\ No newline at end of file
--- /dev/null
+LS0tLS1CRUdJTiBSU0EgUFVCTElDIEtFWS0tLS0tDQpNSUdKQW9HQkFORjVLTmJzN2k3aTByNVFZckNpRExEZ09pU1BWbmgvdlFnMXpnSk9VZVRheWVETk5yZTR6T1RVDQpSVDcyZGlLQ294OGpYOE5paElJTFJtcUtTOWxVYVNzd21QcVNFenVpdE5xeEhnQy8xS2ZuaXM1Qm96NnRwUUxjDQpsZDMwQjJSMWZIVWdFTHZWd0JkV29pRDhSRUt1dFNuRVBGd1RwVmV6aVlWYWtNY25pclRWQWdNQkFBRT0NCi0tLS0tRU5EIFJTQSBQVUJMSUMgS0VZLS0tLS0
\ No newline at end of file
*/
namespace Friendica\Util;
+use phpseclib\Crypt\RSA;
+use phpseclib\Math\BigInteger;
use PHPUnit\Framework\TestCase;
class CryptoTest extends TestCase
private function assertRandomInt($min, $max)
{
global $phpMock;
- $phpMock['random_int'] = function($mMin, $mMax) use ($min, $max) {
+ $phpMock['random_int'] = function ($mMin, $mMax) use ($min, $max) {
$this->assertEquals($min, $mMin);
$this->assertEquals($max, $mMax);
return 1;
$this->assertEquals(8, strlen($test));
$this->assertEquals(11111111, $test);
}
+
+ public function dataRsa()
+ {
+ return [
+ 'diaspora' => [
+ 'key' => file_get_contents(__DIR__ . '/../../datasets/crypto/rsa/diaspora-public-rsa-base64'),
+ 'expected' => file_get_contents(__DIR__ . '/../../datasets/crypto/rsa/diaspora-public-pem'),
+ ],
+ ];
+ }
+
+ /**
+ * @dataProvider dataRsa
+ */
+ public function testPubRsaToMe(string $key, string $expected)
+ {
+ $this->assertEquals($expected, Crypto::rsaToPem(base64_decode($key)));
+ }
+
+
+ public function datePem()
+ {
+ return [
+ 'diaspora' => [
+ 'key' => file_get_contents(__DIR__ . '/../../datasets/crypto/rsa/diaspora-public-pem'),
+ ],
+ ];
+ }
+
+ /**
+ * @dataProvider datePem
+ */
+ 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)
+ ]);
+
+ $this->assertEquals($expectedRSA->getPublicKey(), $key);
+ }
}
/**