Viel neues
This commit is contained in:
130
qa-tool/htdocs/oidc/phpseclib/Crypt/RSA/Formats/Keys/JWK.php
Normal file
130
qa-tool/htdocs/oidc/phpseclib/Crypt/RSA/Formats/Keys/JWK.php
Normal file
@@ -0,0 +1,130 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* JSON Web Key (RFC7517) Formatted RSA Handler
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @copyright 2015 Jim Wigginton
|
||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace phpseclib3\Crypt\RSA\Formats\Keys;
|
||||
|
||||
use phpseclib3\Common\Functions\Strings;
|
||||
use phpseclib3\Crypt\Common\Formats\Keys\JWK as Progenitor;
|
||||
use phpseclib3\Math\BigInteger;
|
||||
|
||||
/**
|
||||
* JWK Formatted RSA Handler
|
||||
*
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
*/
|
||||
abstract class JWK extends Progenitor
|
||||
{
|
||||
/**
|
||||
* Break a public or private key down into its constituent components
|
||||
*
|
||||
* @param string|array $key
|
||||
*/
|
||||
public static function load($key, ?string $password = null): array
|
||||
{
|
||||
$key = parent::loadHelper($key);
|
||||
|
||||
if ($key->kty != 'RSA') {
|
||||
throw new \RuntimeException('Only RSA JWK keys are supported');
|
||||
}
|
||||
|
||||
$count = $publicCount = 0;
|
||||
$vars = ['n', 'e', 'd', 'p', 'q', 'dp', 'dq', 'qi'];
|
||||
foreach ($vars as $var) {
|
||||
if (!isset($key->$var) || !is_string($key->$var)) {
|
||||
continue;
|
||||
}
|
||||
$count++;
|
||||
$value = new BigInteger(Strings::base64url_decode($key->$var), 256);
|
||||
switch ($var) {
|
||||
case 'n':
|
||||
$publicCount++;
|
||||
$components['modulus'] = $value;
|
||||
break;
|
||||
case 'e':
|
||||
$publicCount++;
|
||||
$components['publicExponent'] = $value;
|
||||
break;
|
||||
case 'd':
|
||||
$components['privateExponent'] = $value;
|
||||
break;
|
||||
case 'p':
|
||||
$components['primes'][1] = $value;
|
||||
break;
|
||||
case 'q':
|
||||
$components['primes'][2] = $value;
|
||||
break;
|
||||
case 'dp':
|
||||
$components['exponents'][1] = $value;
|
||||
break;
|
||||
case 'dq':
|
||||
$components['exponents'][2] = $value;
|
||||
break;
|
||||
case 'qi':
|
||||
$components['coefficients'][2] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
if ($count == count($vars)) {
|
||||
return $components + ['isPublicKey' => false];
|
||||
}
|
||||
|
||||
if ($count == 2 && $publicCount == 2) {
|
||||
return $components + ['isPublicKey' => true];
|
||||
}
|
||||
|
||||
throw new \UnexpectedValueException('Key does not have an appropriate number of RSA parameters');
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a private key to the appropriate format.
|
||||
*
|
||||
* @param string $password optional
|
||||
* @param array $options optional
|
||||
*/
|
||||
public static function savePrivateKey(BigInteger $n, BigInteger $e, BigInteger $d, array $primes, array $exponents, array $coefficients, ?string $password = null, array $options = []): string
|
||||
{
|
||||
if (count($primes) != 2) {
|
||||
throw new \InvalidArgumentException('JWK does not support multi-prime RSA keys');
|
||||
}
|
||||
|
||||
$key = [
|
||||
'kty' => 'RSA',
|
||||
'n' => Strings::base64url_encode($n->toBytes()),
|
||||
'e' => Strings::base64url_encode($e->toBytes()),
|
||||
'd' => Strings::base64url_encode($d->toBytes()),
|
||||
'p' => Strings::base64url_encode($primes[1]->toBytes()),
|
||||
'q' => Strings::base64url_encode($primes[2]->toBytes()),
|
||||
'dp' => Strings::base64url_encode($exponents[1]->toBytes()),
|
||||
'dq' => Strings::base64url_encode($exponents[2]->toBytes()),
|
||||
'qi' => Strings::base64url_encode($coefficients[2]->toBytes()),
|
||||
];
|
||||
|
||||
return self::wrapKey($key, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a public key to the appropriate format
|
||||
*/
|
||||
public static function savePublicKey(BigInteger $n, BigInteger $e, array $options = []): string
|
||||
{
|
||||
$key = [
|
||||
'kty' => 'RSA',
|
||||
'n' => Strings::base64url_encode($n->toBytes()),
|
||||
'e' => Strings::base64url_encode($e->toBytes()),
|
||||
];
|
||||
|
||||
return self::wrapKey($key, $options);
|
||||
}
|
||||
}
|
||||
210
qa-tool/htdocs/oidc/phpseclib/Crypt/RSA/Formats/Keys/MSBLOB.php
Normal file
210
qa-tool/htdocs/oidc/phpseclib/Crypt/RSA/Formats/Keys/MSBLOB.php
Normal file
@@ -0,0 +1,210 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Miccrosoft BLOB Formatted RSA Key Handler
|
||||
*
|
||||
* More info:
|
||||
*
|
||||
* https://msdn.microsoft.com/en-us/library/windows/desktop/aa375601(v=vs.85).aspx
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @copyright 2015 Jim Wigginton
|
||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace phpseclib3\Crypt\RSA\Formats\Keys;
|
||||
|
||||
use phpseclib3\Common\Functions\Strings;
|
||||
use phpseclib3\Exception\InvalidArgumentException;
|
||||
use phpseclib3\Exception\UnexpectedValueException;
|
||||
use phpseclib3\Exception\UnsupportedFormatException;
|
||||
use phpseclib3\Math\BigInteger;
|
||||
|
||||
/**
|
||||
* Microsoft BLOB Formatted RSA Key Handler
|
||||
*
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
*/
|
||||
abstract class MSBLOB
|
||||
{
|
||||
/**
|
||||
* Public/Private Key Pair
|
||||
*/
|
||||
public const PRIVATEKEYBLOB = 0x7;
|
||||
/**
|
||||
* Public Key
|
||||
*/
|
||||
public const PUBLICKEYBLOB = 0x6;
|
||||
/**
|
||||
* Public Key
|
||||
*/
|
||||
public const PUBLICKEYBLOBEX = 0xA;
|
||||
/**
|
||||
* RSA public key exchange algorithm
|
||||
*/
|
||||
public const CALG_RSA_KEYX = 0x0000A400;
|
||||
/**
|
||||
* RSA public key exchange algorithm
|
||||
*/
|
||||
public const CALG_RSA_SIGN = 0x00002400;
|
||||
/**
|
||||
* Public Key
|
||||
*/
|
||||
public const RSA1 = 0x31415352;
|
||||
/**
|
||||
* Private Key
|
||||
*/
|
||||
public const RSA2 = 0x32415352;
|
||||
|
||||
/**
|
||||
* Break a public or private key down into its constituent components
|
||||
*
|
||||
* @param string|array $key
|
||||
*/
|
||||
public static function load($key, ?string $password = null): array
|
||||
{
|
||||
if (!Strings::is_stringable($key)) {
|
||||
throw new UnexpectedValueException('Key should be a string - not a ' . gettype($key));
|
||||
}
|
||||
|
||||
$key = Strings::base64_decode($key);
|
||||
|
||||
if (!is_string($key)) {
|
||||
throw new UnexpectedValueException('Base64 decoding produced an error');
|
||||
}
|
||||
if (strlen($key) < 20) {
|
||||
throw new UnexpectedValueException('Key appears to be malformed');
|
||||
}
|
||||
|
||||
// PUBLICKEYSTRUC publickeystruc
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa387453(v=vs.85).aspx
|
||||
extract(unpack('atype/aversion/vreserved/Valgo', Strings::shift($key, 8)));
|
||||
/**
|
||||
* @var string $type
|
||||
* @var string $version
|
||||
* @var integer $reserved
|
||||
* @var integer $algo
|
||||
*/
|
||||
switch (ord($type)) {
|
||||
case self::PUBLICKEYBLOB:
|
||||
case self::PUBLICKEYBLOBEX:
|
||||
$publickey = true;
|
||||
break;
|
||||
case self::PRIVATEKEYBLOB:
|
||||
$publickey = false;
|
||||
break;
|
||||
default:
|
||||
throw new UnexpectedValueException('Key appears to be malformed');
|
||||
}
|
||||
|
||||
$components = ['isPublicKey' => $publickey];
|
||||
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa375549(v=vs.85).aspx
|
||||
switch ($algo) {
|
||||
case self::CALG_RSA_KEYX:
|
||||
case self::CALG_RSA_SIGN:
|
||||
break;
|
||||
default:
|
||||
throw new UnexpectedValueException('Key appears to be malformed');
|
||||
}
|
||||
|
||||
// RSAPUBKEY rsapubkey
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa387685(v=vs.85).aspx
|
||||
// could do V for pubexp but that's unsigned 32-bit whereas some PHP installs only do signed 32-bit
|
||||
extract(unpack('Vmagic/Vbitlen/a4pubexp', Strings::shift($key, 12)));
|
||||
/**
|
||||
* @var integer $magic
|
||||
* @var integer $bitlen
|
||||
* @var string $pubexp
|
||||
*/
|
||||
switch ($magic) {
|
||||
case self::RSA2:
|
||||
$components['isPublicKey'] = false;
|
||||
// fall-through
|
||||
case self::RSA1:
|
||||
break;
|
||||
default:
|
||||
throw new UnexpectedValueException('Key appears to be malformed');
|
||||
}
|
||||
|
||||
$baseLength = $bitlen / 16;
|
||||
if (strlen($key) != 2 * $baseLength && strlen($key) != 9 * $baseLength) {
|
||||
throw new UnexpectedValueException('Key appears to be malformed');
|
||||
}
|
||||
|
||||
$components[$components['isPublicKey'] ? 'publicExponent' : 'privateExponent'] = new BigInteger(strrev($pubexp), 256);
|
||||
// BYTE modulus[rsapubkey.bitlen/8]
|
||||
$components['modulus'] = new BigInteger(strrev(Strings::shift($key, $bitlen / 8)), 256);
|
||||
|
||||
if ($publickey) {
|
||||
return $components;
|
||||
}
|
||||
|
||||
$components['isPublicKey'] = false;
|
||||
|
||||
// BYTE prime1[rsapubkey.bitlen/16]
|
||||
$components['primes'] = [1 => new BigInteger(strrev(Strings::shift($key, $bitlen / 16)), 256)];
|
||||
// BYTE prime2[rsapubkey.bitlen/16]
|
||||
$components['primes'][] = new BigInteger(strrev(Strings::shift($key, $bitlen / 16)), 256);
|
||||
// BYTE exponent1[rsapubkey.bitlen/16]
|
||||
$components['exponents'] = [1 => new BigInteger(strrev(Strings::shift($key, $bitlen / 16)), 256)];
|
||||
// BYTE exponent2[rsapubkey.bitlen/16]
|
||||
$components['exponents'][] = new BigInteger(strrev(Strings::shift($key, $bitlen / 16)), 256);
|
||||
// BYTE coefficient[rsapubkey.bitlen/16]
|
||||
$components['coefficients'] = [2 => new BigInteger(strrev(Strings::shift($key, $bitlen / 16)), 256)];
|
||||
if (isset($components['privateExponent'])) {
|
||||
$components['publicExponent'] = $components['privateExponent'];
|
||||
}
|
||||
// BYTE privateExponent[rsapubkey.bitlen/8]
|
||||
$components['privateExponent'] = new BigInteger(strrev(Strings::shift($key, $bitlen / 8)), 256);
|
||||
|
||||
return $components;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a private key to the appropriate format.
|
||||
*/
|
||||
public static function savePrivateKey(BigInteger $n, BigInteger $e, BigInteger $d, array $primes, array $exponents, array $coefficients, ?string $password = null): string
|
||||
{
|
||||
if (count($primes) != 2) {
|
||||
throw new InvalidArgumentException('MSBLOB does not support multi-prime RSA keys');
|
||||
}
|
||||
|
||||
if (!empty($password) && is_string($password)) {
|
||||
throw new UnsupportedFormatException('MSBLOB private keys do not support encryption');
|
||||
}
|
||||
|
||||
$n = strrev($n->toBytes());
|
||||
$e = str_pad(strrev($e->toBytes()), 4, "\0");
|
||||
$key = pack('aavV', chr(self::PRIVATEKEYBLOB), chr(2), 0, self::CALG_RSA_KEYX);
|
||||
$key .= pack('VVa*', self::RSA2, 8 * strlen($n), $e);
|
||||
$key .= $n;
|
||||
$key .= strrev($primes[1]->toBytes());
|
||||
$key .= strrev($primes[2]->toBytes());
|
||||
$key .= strrev($exponents[1]->toBytes());
|
||||
$key .= strrev($exponents[2]->toBytes());
|
||||
$key .= strrev($coefficients[2]->toBytes());
|
||||
$key .= strrev($d->toBytes());
|
||||
|
||||
return Strings::base64_encode($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a public key to the appropriate format
|
||||
*/
|
||||
public static function savePublicKey(BigInteger $n, BigInteger $e): string
|
||||
{
|
||||
$n = strrev($n->toBytes());
|
||||
$e = str_pad(strrev($e->toBytes()), 4, "\0");
|
||||
$key = pack('aavV', chr(self::PUBLICKEYBLOB), chr(2), 0, self::CALG_RSA_KEYX);
|
||||
$key .= pack('VVa*', self::RSA1, 8 * strlen($n), $e);
|
||||
$key .= $n;
|
||||
|
||||
return Strings::base64_encode($key);
|
||||
}
|
||||
}
|
||||
120
qa-tool/htdocs/oidc/phpseclib/Crypt/RSA/Formats/Keys/OpenSSH.php
Normal file
120
qa-tool/htdocs/oidc/phpseclib/Crypt/RSA/Formats/Keys/OpenSSH.php
Normal file
@@ -0,0 +1,120 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* OpenSSH Formatted RSA Key Handler
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* Place in $HOME/.ssh/authorized_keys
|
||||
*
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @copyright 2015 Jim Wigginton
|
||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace phpseclib3\Crypt\RSA\Formats\Keys;
|
||||
|
||||
use phpseclib3\Common\Functions\Strings;
|
||||
use phpseclib3\Crypt\Common\Formats\Keys\OpenSSH as Progenitor;
|
||||
use phpseclib3\Exception\RuntimeException;
|
||||
use phpseclib3\Math\BigInteger;
|
||||
|
||||
/**
|
||||
* OpenSSH Formatted RSA Key Handler
|
||||
*
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
*/
|
||||
abstract class OpenSSH extends Progenitor
|
||||
{
|
||||
/**
|
||||
* Supported Key Types
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected static $types = ['ssh-rsa'];
|
||||
|
||||
/**
|
||||
* Break a public or private key down into its constituent components
|
||||
*
|
||||
* @param string|array $key
|
||||
*/
|
||||
public static function load($key, ?string $password = null): array
|
||||
{
|
||||
static $one;
|
||||
if (!isset($one)) {
|
||||
$one = new BigInteger(1);
|
||||
}
|
||||
|
||||
$parsed = parent::load($key, $password);
|
||||
|
||||
if (isset($parsed['paddedKey'])) {
|
||||
[$type] = Strings::unpackSSH2('s', $parsed['paddedKey']);
|
||||
if ($type != $parsed['type']) {
|
||||
throw new RuntimeException("The public and private keys are not of the same type ($type vs $parsed[type])");
|
||||
}
|
||||
|
||||
$primes = $coefficients = [];
|
||||
|
||||
[
|
||||
$modulus,
|
||||
$publicExponent,
|
||||
$privateExponent,
|
||||
$coefficients[2],
|
||||
$primes[1],
|
||||
$primes[2],
|
||||
$comment,
|
||||
] = Strings::unpackSSH2('i6s', $parsed['paddedKey']);
|
||||
|
||||
$temp = $primes[1]->subtract($one);
|
||||
$exponents = [1 => $publicExponent->modInverse($temp)];
|
||||
$temp = $primes[2]->subtract($one);
|
||||
$exponents[] = $publicExponent->modInverse($temp);
|
||||
|
||||
$isPublicKey = false;
|
||||
|
||||
return compact('publicExponent', 'modulus', 'privateExponent', 'primes', 'coefficients', 'exponents', 'comment', 'isPublicKey');
|
||||
}
|
||||
|
||||
[$publicExponent, $modulus] = Strings::unpackSSH2('ii', $parsed['publicKey']);
|
||||
|
||||
return [
|
||||
'isPublicKey' => true,
|
||||
'modulus' => $modulus,
|
||||
'publicExponent' => $publicExponent,
|
||||
'comment' => $parsed['comment'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a public key to the appropriate format
|
||||
*
|
||||
* @param array $options optional
|
||||
*/
|
||||
public static function savePublicKey(BigInteger $n, BigInteger $e, array $options = []): string
|
||||
{
|
||||
$RSAPublicKey = Strings::packSSH2('sii', 'ssh-rsa', $e, $n);
|
||||
|
||||
if ($options['binary'] ?? self::$binary) {
|
||||
return $RSAPublicKey;
|
||||
}
|
||||
|
||||
$comment = $options['comment'] ?? self::$comment;
|
||||
$RSAPublicKey = 'ssh-rsa ' . base64_encode($RSAPublicKey) . ' ' . $comment;
|
||||
|
||||
return $RSAPublicKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a private key to the appropriate format.
|
||||
*/
|
||||
public static function savePrivateKey(BigInteger $n, BigInteger $e, BigInteger $d, array $primes, array $exponents, array $coefficients, ?string $password = null, array $options = []): string
|
||||
{
|
||||
$publicKey = self::savePublicKey($n, $e, ['binary' => true]);
|
||||
$privateKey = Strings::packSSH2('si6', 'ssh-rsa', $n, $e, $d, $coefficients[2], $primes[1], $primes[2]);
|
||||
|
||||
return self::wrapPrivateKey($publicKey, $privateKey, $password, $options);
|
||||
}
|
||||
}
|
||||
152
qa-tool/htdocs/oidc/phpseclib/Crypt/RSA/Formats/Keys/PKCS1.php
Normal file
152
qa-tool/htdocs/oidc/phpseclib/Crypt/RSA/Formats/Keys/PKCS1.php
Normal file
@@ -0,0 +1,152 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PKCS#1 Formatted RSA Key Handler
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* Used by File/X509.php
|
||||
*
|
||||
* Processes keys with the following headers:
|
||||
*
|
||||
* -----BEGIN RSA PRIVATE KEY-----
|
||||
* -----BEGIN RSA PUBLIC KEY-----
|
||||
*
|
||||
* Analogous to ssh-keygen's pem format (as specified by -m)
|
||||
*
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @copyright 2015 Jim Wigginton
|
||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace phpseclib3\Crypt\RSA\Formats\Keys;
|
||||
|
||||
use phpseclib3\Common\Functions\Strings;
|
||||
use phpseclib3\Crypt\Common\Formats\Keys\PKCS1 as Progenitor;
|
||||
use phpseclib3\Exception\RuntimeException;
|
||||
use phpseclib3\Exception\UnexpectedValueException;
|
||||
use phpseclib3\File\ASN1;
|
||||
use phpseclib3\File\ASN1\Maps;
|
||||
use phpseclib3\Math\BigInteger;
|
||||
|
||||
/**
|
||||
* PKCS#1 Formatted RSA Key Handler
|
||||
*
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
*/
|
||||
abstract class PKCS1 extends Progenitor
|
||||
{
|
||||
/**
|
||||
* Break a public or private key down into its constituent components
|
||||
*
|
||||
* @param string|array $key
|
||||
* @param string|false $password
|
||||
*/
|
||||
public static function load($key, ?string $password = null): array
|
||||
{
|
||||
if (!Strings::is_stringable($key)) {
|
||||
throw new UnexpectedValueException('Key should be a string - not a ' . gettype($key));
|
||||
}
|
||||
|
||||
if (str_contains($key, 'PUBLIC')) {
|
||||
$components = ['isPublicKey' => true];
|
||||
} elseif (str_contains($key, 'PRIVATE')) {
|
||||
$components = ['isPublicKey' => false];
|
||||
} else {
|
||||
$components = [];
|
||||
}
|
||||
|
||||
$key = parent::load($key, $password);
|
||||
|
||||
$decoded = ASN1::decodeBER($key);
|
||||
if (!$decoded) {
|
||||
throw new RuntimeException('Unable to decode BER');
|
||||
}
|
||||
|
||||
$key = ASN1::asn1map($decoded[0], Maps\RSAPrivateKey::MAP);
|
||||
if (is_array($key)) {
|
||||
$components += [
|
||||
'modulus' => $key['modulus'],
|
||||
'publicExponent' => $key['publicExponent'],
|
||||
'privateExponent' => $key['privateExponent'],
|
||||
'primes' => [1 => $key['prime1'], $key['prime2']],
|
||||
'exponents' => [1 => $key['exponent1'], $key['exponent2']],
|
||||
'coefficients' => [2 => $key['coefficient']],
|
||||
];
|
||||
if ($key['version'] == 'multi') {
|
||||
foreach ($key['otherPrimeInfos'] as $primeInfo) {
|
||||
$components['primes'][] = $primeInfo['prime'];
|
||||
$components['exponents'][] = $primeInfo['exponent'];
|
||||
$components['coefficients'][] = $primeInfo['coefficient'];
|
||||
}
|
||||
}
|
||||
if (!isset($components['isPublicKey'])) {
|
||||
$components['isPublicKey'] = false;
|
||||
}
|
||||
return $components;
|
||||
}
|
||||
|
||||
$key = ASN1::asn1map($decoded[0], Maps\RSAPublicKey::MAP);
|
||||
|
||||
if (!is_array($key)) {
|
||||
throw new RuntimeException('Unable to perform ASN1 mapping');
|
||||
}
|
||||
|
||||
if (!isset($components['isPublicKey'])) {
|
||||
$components['isPublicKey'] = true;
|
||||
}
|
||||
|
||||
return $components + $key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a private key to the appropriate format.
|
||||
*
|
||||
* @param string|false $password
|
||||
* @param array $options optional
|
||||
*/
|
||||
public static function savePrivateKey(BigInteger $n, BigInteger $e, BigInteger $d, array $primes, array $exponents, array $coefficients, ?string $password = null, array $options = []): string
|
||||
{
|
||||
$num_primes = count($primes);
|
||||
$key = [
|
||||
'version' => $num_primes == 2 ? 'two-prime' : 'multi',
|
||||
'modulus' => $n,
|
||||
'publicExponent' => $e,
|
||||
'privateExponent' => $d,
|
||||
'prime1' => $primes[1],
|
||||
'prime2' => $primes[2],
|
||||
'exponent1' => $exponents[1],
|
||||
'exponent2' => $exponents[2],
|
||||
'coefficient' => $coefficients[2],
|
||||
];
|
||||
for ($i = 3; $i <= $num_primes; $i++) {
|
||||
$key['otherPrimeInfos'][] = [
|
||||
'prime' => $primes[$i],
|
||||
'exponent' => $exponents[$i],
|
||||
'coefficient' => $coefficients[$i],
|
||||
];
|
||||
}
|
||||
|
||||
$key = ASN1::encodeDER($key, Maps\RSAPrivateKey::MAP);
|
||||
|
||||
return self::wrapPrivateKey($key, 'RSA', $password, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a public key to the appropriate format
|
||||
*/
|
||||
public static function savePublicKey(BigInteger $n, BigInteger $e): string
|
||||
{
|
||||
$key = [
|
||||
'modulus' => $n,
|
||||
'publicExponent' => $e,
|
||||
];
|
||||
|
||||
$key = ASN1::encodeDER($key, Maps\RSAPublicKey::MAP);
|
||||
|
||||
return self::wrapPublicKey($key, 'RSA');
|
||||
}
|
||||
}
|
||||
109
qa-tool/htdocs/oidc/phpseclib/Crypt/RSA/Formats/Keys/PKCS8.php
Normal file
109
qa-tool/htdocs/oidc/phpseclib/Crypt/RSA/Formats/Keys/PKCS8.php
Normal file
@@ -0,0 +1,109 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PKCS#8 Formatted RSA Key Handler
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* Used by PHP's openssl_public_encrypt() and openssl's rsautl (when -pubin is set)
|
||||
*
|
||||
* Processes keys with the following headers:
|
||||
*
|
||||
* -----BEGIN ENCRYPTED PRIVATE KEY-----
|
||||
* -----BEGIN PRIVATE KEY-----
|
||||
* -----BEGIN PUBLIC KEY-----
|
||||
*
|
||||
* Analogous to ssh-keygen's pkcs8 format (as specified by -m). Although PKCS8
|
||||
* is specific to private keys it's basically creating a DER-encoded wrapper
|
||||
* for keys. This just extends that same concept to public keys (much like ssh-keygen)
|
||||
*
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @copyright 2015 Jim Wigginton
|
||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace phpseclib3\Crypt\RSA\Formats\Keys;
|
||||
|
||||
use phpseclib3\Crypt\Common\Formats\Keys\PKCS8 as Progenitor;
|
||||
use phpseclib3\File\ASN1;
|
||||
use phpseclib3\Math\BigInteger;
|
||||
|
||||
/**
|
||||
* PKCS#8 Formatted RSA Key Handler
|
||||
*
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
*/
|
||||
abstract class PKCS8 extends Progenitor
|
||||
{
|
||||
/**
|
||||
* OID Name
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public const OID_NAME = 'rsaEncryption';
|
||||
|
||||
/**
|
||||
* OID Value
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public const OID_VALUE = '1.2.840.113549.1.1.1';
|
||||
|
||||
/**
|
||||
* Child OIDs loaded
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected static $childOIDsLoaded = false;
|
||||
|
||||
/**
|
||||
* Break a public or private key down into its constituent components
|
||||
*
|
||||
* @param string|array $key
|
||||
*/
|
||||
public static function load($key, ?string $password = null): array
|
||||
{
|
||||
$key = parent::load($key, $password);
|
||||
|
||||
if (isset($key['privateKey'])) {
|
||||
$components['isPublicKey'] = false;
|
||||
$type = 'private';
|
||||
} else {
|
||||
$components['isPublicKey'] = true;
|
||||
$type = 'public';
|
||||
}
|
||||
|
||||
$result = $components + PKCS1::load($key[$type . 'Key']);
|
||||
|
||||
if (isset($key['meta'])) {
|
||||
$result['meta'] = $key['meta'];
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a private key to the appropriate format.
|
||||
*/
|
||||
public static function savePrivateKey(BigInteger $n, BigInteger $e, BigInteger $d, array $primes, array $exponents, array $coefficients, ?string $password = null, array $options = []): string
|
||||
{
|
||||
$key = PKCS1::savePrivateKey($n, $e, $d, $primes, $exponents, $coefficients);
|
||||
$key = ASN1::extractBER($key);
|
||||
return self::wrapPrivateKey($key, [], null, $password, null, '', $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a public key to the appropriate format
|
||||
*
|
||||
* @param array $options optional
|
||||
*/
|
||||
public static function savePublicKey(BigInteger $n, BigInteger $e, array $options = []): string
|
||||
{
|
||||
$key = PKCS1::savePublicKey($n, $e);
|
||||
$key = ASN1::extractBER($key);
|
||||
return self::wrapPublicKey($key, null);
|
||||
}
|
||||
}
|
||||
225
qa-tool/htdocs/oidc/phpseclib/Crypt/RSA/Formats/Keys/PSS.php
Normal file
225
qa-tool/htdocs/oidc/phpseclib/Crypt/RSA/Formats/Keys/PSS.php
Normal file
@@ -0,0 +1,225 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PKCS#8 Formatted RSA-PSS Key Handler
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* Used by PHP's openssl_public_encrypt() and openssl's rsautl (when -pubin is set)
|
||||
*
|
||||
* Processes keys with the following headers:
|
||||
*
|
||||
* -----BEGIN ENCRYPTED PRIVATE KEY-----
|
||||
* -----BEGIN PRIVATE KEY-----
|
||||
* -----BEGIN PUBLIC KEY-----
|
||||
*
|
||||
* Analogous to "openssl genpkey -algorithm rsa-pss".
|
||||
*
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @copyright 2015 Jim Wigginton
|
||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace phpseclib3\Crypt\RSA\Formats\Keys;
|
||||
|
||||
use phpseclib3\Common\Functions\Strings;
|
||||
use phpseclib3\Crypt\Common\Formats\Keys\PKCS8 as Progenitor;
|
||||
use phpseclib3\Exception\UnexpectedValueException;
|
||||
use phpseclib3\File\ASN1;
|
||||
use phpseclib3\File\ASN1\Maps;
|
||||
use phpseclib3\Math\BigInteger;
|
||||
|
||||
/**
|
||||
* PKCS#8 Formatted RSA-PSS Key Handler
|
||||
*
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
*/
|
||||
abstract class PSS extends Progenitor
|
||||
{
|
||||
/**
|
||||
* OID Name
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public const OID_NAME = 'id-RSASSA-PSS';
|
||||
|
||||
/**
|
||||
* OID Value
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public const OID_VALUE = '1.2.840.113549.1.1.10';
|
||||
|
||||
/**
|
||||
* OIDs loaded
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private static $oidsLoaded = false;
|
||||
|
||||
/**
|
||||
* Child OIDs loaded
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected static $childOIDsLoaded = false;
|
||||
|
||||
/**
|
||||
* Initialize static variables
|
||||
*/
|
||||
private static function initialize_static_variables(): void
|
||||
{
|
||||
if (!self::$oidsLoaded) {
|
||||
ASN1::loadOIDs([
|
||||
'md2' => '1.2.840.113549.2.2',
|
||||
'md4' => '1.2.840.113549.2.4',
|
||||
'md5' => '1.2.840.113549.2.5',
|
||||
'id-sha1' => '1.3.14.3.2.26',
|
||||
'id-sha256' => '2.16.840.1.101.3.4.2.1',
|
||||
'id-sha384' => '2.16.840.1.101.3.4.2.2',
|
||||
'id-sha512' => '2.16.840.1.101.3.4.2.3',
|
||||
'id-sha224' => '2.16.840.1.101.3.4.2.4',
|
||||
'id-sha512/224' => '2.16.840.1.101.3.4.2.5',
|
||||
'id-sha512/256' => '2.16.840.1.101.3.4.2.6',
|
||||
|
||||
'id-mgf1' => '1.2.840.113549.1.1.8',
|
||||
]);
|
||||
self::$oidsLoaded = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Break a public or private key down into its constituent components
|
||||
*
|
||||
* @param string|array $key
|
||||
*/
|
||||
public static function load($key, ?string $password = null): array
|
||||
{
|
||||
self::initialize_static_variables();
|
||||
|
||||
if (!Strings::is_stringable($key)) {
|
||||
throw new UnexpectedValueException('Key should be a string - not a ' . gettype($key));
|
||||
}
|
||||
|
||||
$components = ['isPublicKey' => str_contains($key, 'PUBLIC')];
|
||||
|
||||
$key = parent::load($key, $password);
|
||||
|
||||
$type = isset($key['privateKey']) ? 'private' : 'public';
|
||||
|
||||
$result = $components + PKCS1::load($key[$type . 'Key']);
|
||||
|
||||
if (isset($key[$type . 'KeyAlgorithm']['parameters'])) {
|
||||
$decoded = ASN1::decodeBER($key[$type . 'KeyAlgorithm']['parameters']);
|
||||
if ($decoded === false) {
|
||||
throw new UnexpectedValueException('Unable to decode parameters');
|
||||
}
|
||||
$params = ASN1::asn1map($decoded[0], Maps\RSASSA_PSS_params::MAP);
|
||||
} else {
|
||||
$params = [];
|
||||
}
|
||||
|
||||
if (isset($params['maskGenAlgorithm']['parameters'])) {
|
||||
$decoded = ASN1::decodeBER($params['maskGenAlgorithm']['parameters']);
|
||||
if ($decoded === false) {
|
||||
throw new UnexpectedValueException('Unable to decode parameters');
|
||||
}
|
||||
$params['maskGenAlgorithm']['parameters'] = ASN1::asn1map($decoded[0], Maps\HashAlgorithm::MAP);
|
||||
} else {
|
||||
$params['maskGenAlgorithm'] = [
|
||||
'algorithm' => 'id-mgf1',
|
||||
'parameters' => ['algorithm' => 'id-sha1'],
|
||||
];
|
||||
}
|
||||
|
||||
if (!isset($params['hashAlgorithm']['algorithm'])) {
|
||||
$params['hashAlgorithm']['algorithm'] = 'id-sha1';
|
||||
}
|
||||
|
||||
$result['hash'] = str_replace('id-', '', $params['hashAlgorithm']['algorithm']);
|
||||
$result['MGFHash'] = str_replace('id-', '', $params['maskGenAlgorithm']['parameters']['algorithm']);
|
||||
if (isset($params['saltLength'])) {
|
||||
$result['saltLength'] = (int) $params['saltLength']->toString();
|
||||
}
|
||||
|
||||
if (isset($key['meta'])) {
|
||||
$result['meta'] = $key['meta'];
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a private key to the appropriate format.
|
||||
*/
|
||||
public static function savePrivateKey(BigInteger $n, BigInteger $e, BigInteger $d, array $primes, array $exponents, array $coefficients, ?string $password = null, array $options = []): string
|
||||
{
|
||||
self::initialize_static_variables();
|
||||
|
||||
$key = PKCS1::savePrivateKey($n, $e, $d, $primes, $exponents, $coefficients);
|
||||
$key = ASN1::extractBER($key);
|
||||
$params = self::savePSSParams($options);
|
||||
return self::wrapPrivateKey($key, [], $params, $password, null, '', $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a public key to the appropriate format
|
||||
*
|
||||
* @param array $options optional
|
||||
*/
|
||||
public static function savePublicKey(BigInteger $n, BigInteger $e, array $options = []): string
|
||||
{
|
||||
self::initialize_static_variables();
|
||||
|
||||
$key = PKCS1::savePublicKey($n, $e);
|
||||
$key = ASN1::extractBER($key);
|
||||
$params = self::savePSSParams($options);
|
||||
return self::wrapPublicKey($key, $params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes PSS parameters
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function savePSSParams(array $options)
|
||||
{
|
||||
/*
|
||||
The trailerField field is an integer. It provides
|
||||
compatibility with IEEE Std 1363a-2004 [P1363A]. The value
|
||||
MUST be 1, which represents the trailer field with hexadecimal
|
||||
value 0xBC. Other trailer fields, including the trailer field
|
||||
composed of HashID concatenated with 0xCC that is specified in
|
||||
IEEE Std 1363a, are not supported. Implementations that
|
||||
perform signature generation MUST omit the trailerField field,
|
||||
indicating that the default trailer field value was used.
|
||||
Implementations that perform signature validation MUST
|
||||
recognize both a present trailerField field with value 1 and an
|
||||
absent trailerField field.
|
||||
|
||||
source: https://tools.ietf.org/html/rfc4055#page-9
|
||||
*/
|
||||
$params = [
|
||||
'trailerField' => new BigInteger(1),
|
||||
];
|
||||
if (isset($options['hash'])) {
|
||||
$params['hashAlgorithm']['algorithm'] = 'id-' . $options['hash'];
|
||||
}
|
||||
if (isset($options['MGFHash'])) {
|
||||
$temp = ['algorithm' => 'id-' . $options['MGFHash']];
|
||||
$temp = ASN1::encodeDER($temp, Maps\HashAlgorithm::MAP);
|
||||
$params['maskGenAlgorithm'] = [
|
||||
'algorithm' => 'id-mgf1',
|
||||
'parameters' => new ASN1\Element($temp),
|
||||
];
|
||||
}
|
||||
if (isset($options['saltLength'])) {
|
||||
$params['saltLength'] = new BigInteger($options['saltLength']);
|
||||
}
|
||||
|
||||
return new ASN1\Element(ASN1::encodeDER($params, Maps\RSASSA_PSS_params::MAP));
|
||||
}
|
||||
}
|
||||
111
qa-tool/htdocs/oidc/phpseclib/Crypt/RSA/Formats/Keys/PuTTY.php
Normal file
111
qa-tool/htdocs/oidc/phpseclib/Crypt/RSA/Formats/Keys/PuTTY.php
Normal file
@@ -0,0 +1,111 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PuTTY Formatted RSA Key Handler
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @copyright 2015 Jim Wigginton
|
||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace phpseclib3\Crypt\RSA\Formats\Keys;
|
||||
|
||||
use phpseclib3\Common\Functions\Strings;
|
||||
use phpseclib3\Crypt\Common\Formats\Keys\PuTTY as Progenitor;
|
||||
use phpseclib3\Exception\InvalidArgumentException;
|
||||
use phpseclib3\Exception\UnexpectedValueException;
|
||||
use phpseclib3\Math\BigInteger;
|
||||
|
||||
/**
|
||||
* PuTTY Formatted RSA Key Handler
|
||||
*
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
*/
|
||||
abstract class PuTTY extends Progenitor
|
||||
{
|
||||
/**
|
||||
* Public Handler
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public const PUBLIC_HANDLER = 'phpseclib3\Crypt\RSA\Formats\Keys\OpenSSH';
|
||||
|
||||
/**
|
||||
* Algorithm Identifier
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected static $types = ['ssh-rsa'];
|
||||
|
||||
/**
|
||||
* Break a public or private key down into its constituent components
|
||||
*
|
||||
* @param array|string $key
|
||||
* @param string|false $password
|
||||
* @return array|false
|
||||
*/
|
||||
public static function load($key, $password)
|
||||
{
|
||||
static $one;
|
||||
if (!isset($one)) {
|
||||
$one = new BigInteger(1);
|
||||
}
|
||||
|
||||
$components = parent::load($key, $password);
|
||||
if (!isset($components['private'])) {
|
||||
return $components;
|
||||
}
|
||||
extract($components);
|
||||
unset($components['public'], $components['private']);
|
||||
|
||||
$isPublicKey = false;
|
||||
|
||||
$result = Strings::unpackSSH2('ii', $public);
|
||||
if ($result === false) {
|
||||
throw new UnexpectedValueException('Key appears to be malformed');
|
||||
}
|
||||
[$publicExponent, $modulus] = $result;
|
||||
|
||||
$result = Strings::unpackSSH2('iiii', $private);
|
||||
if ($result === false) {
|
||||
throw new UnexpectedValueException('Key appears to be malformed');
|
||||
}
|
||||
$primes = $coefficients = [];
|
||||
[$privateExponent, $primes[1], $primes[2], $coefficients[2]] = $result;
|
||||
|
||||
$temp = $primes[1]->subtract($one);
|
||||
$exponents = [1 => $publicExponent->modInverse($temp)];
|
||||
$temp = $primes[2]->subtract($one);
|
||||
$exponents[] = $publicExponent->modInverse($temp);
|
||||
|
||||
return compact('publicExponent', 'modulus', 'privateExponent', 'primes', 'coefficients', 'exponents', 'comment', 'isPublicKey');
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a private key to the appropriate format.
|
||||
*/
|
||||
public static function savePrivateKey(BigInteger $n, BigInteger $e, BigInteger $d, array $primes, array $exponents, array $coefficients, ?string $password = null, array $options = []): string
|
||||
{
|
||||
if (count($primes) != 2) {
|
||||
throw new InvalidArgumentException('PuTTY does not support multi-prime RSA keys');
|
||||
}
|
||||
|
||||
$public = Strings::packSSH2('ii', $e, $n);
|
||||
$private = Strings::packSSH2('iiii', $d, $primes[1], $primes[2], $coefficients[2]);
|
||||
|
||||
return self::wrapPrivateKey($public, $private, 'ssh-rsa', $password, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a public key to the appropriate format
|
||||
*/
|
||||
public static function savePublicKey(BigInteger $n, BigInteger $e): string
|
||||
{
|
||||
return self::wrapPublicKey(Strings::packSSH2('ii', $e, $n), 'ssh-rsa');
|
||||
}
|
||||
}
|
||||
166
qa-tool/htdocs/oidc/phpseclib/Crypt/RSA/Formats/Keys/Raw.php
Normal file
166
qa-tool/htdocs/oidc/phpseclib/Crypt/RSA/Formats/Keys/Raw.php
Normal file
@@ -0,0 +1,166 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Raw RSA Key Handler
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* An array containing two \phpseclib3\Math\BigInteger objects.
|
||||
*
|
||||
* The exponent can be indexed with any of the following:
|
||||
*
|
||||
* 0, e, exponent, publicExponent
|
||||
*
|
||||
* The modulus can be indexed with any of the following:
|
||||
*
|
||||
* 1, n, modulo, modulus
|
||||
*
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @copyright 2015 Jim Wigginton
|
||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace phpseclib3\Crypt\RSA\Formats\Keys;
|
||||
|
||||
use phpseclib3\Exception\UnexpectedValueException;
|
||||
use phpseclib3\Exception\UnsupportedFormatException;
|
||||
use phpseclib3\Math\BigInteger;
|
||||
|
||||
/**
|
||||
* Raw RSA Key Handler
|
||||
*
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
*/
|
||||
abstract class Raw
|
||||
{
|
||||
/**
|
||||
* Break a public or private key down into its constituent components
|
||||
*
|
||||
* @param string|array $key
|
||||
*/
|
||||
public static function load($key, ?string $password = null): array
|
||||
{
|
||||
if (!is_array($key)) {
|
||||
throw new UnexpectedValueException('Key should be a array - not a ' . gettype($key));
|
||||
}
|
||||
|
||||
$key = array_change_key_case($key, CASE_LOWER);
|
||||
|
||||
$components = ['isPublicKey' => false];
|
||||
|
||||
foreach (['e', 'exponent', 'publicexponent', 0, 'privateexponent', 'd'] as $index) {
|
||||
if (isset($key[$index])) {
|
||||
$components['publicExponent'] = $key[$index];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (['n', 'modulo', 'modulus', 1] as $index) {
|
||||
if (isset($key[$index])) {
|
||||
$components['modulus'] = $key[$index];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isset($components['publicExponent']) || !isset($components['modulus'])) {
|
||||
throw new UnexpectedValueException('Modulus / exponent not present');
|
||||
}
|
||||
|
||||
if (isset($key['primes'])) {
|
||||
$components['primes'] = $key['primes'];
|
||||
} elseif (isset($key['p']) && isset($key['q'])) {
|
||||
$indices = [
|
||||
['p', 'q'],
|
||||
['prime1', 'prime2'],
|
||||
];
|
||||
foreach ($indices as $index) {
|
||||
[$i0, $i1] = $index;
|
||||
if (isset($key[$i0]) && isset($key[$i1])) {
|
||||
$components['primes'] = [1 => $key[$i0], $key[$i1]];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($key['exponents'])) {
|
||||
$components['exponents'] = $key['exponents'];
|
||||
} else {
|
||||
$indices = [
|
||||
['dp', 'dq'],
|
||||
['exponent1', 'exponent2'],
|
||||
];
|
||||
foreach ($indices as $index) {
|
||||
[$i0, $i1] = $index;
|
||||
if (isset($key[$i0]) && isset($key[$i1])) {
|
||||
$components['exponents'] = [1 => $key[$i0], $key[$i1]];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($key['coefficients'])) {
|
||||
$components['coefficients'] = $key['coefficients'];
|
||||
} else {
|
||||
foreach (['inverseq', 'q\'', 'coefficient'] as $index) {
|
||||
if (isset($key[$index])) {
|
||||
$components['coefficients'] = [2 => $key[$index]];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!isset($components['primes'])) {
|
||||
$components['isPublicKey'] = true;
|
||||
return $components;
|
||||
}
|
||||
|
||||
if (!isset($components['exponents'])) {
|
||||
$one = new BigInteger(1);
|
||||
$temp = $components['primes'][1]->subtract($one);
|
||||
$exponents = [1 => $components['publicExponent']->modInverse($temp)];
|
||||
$temp = $components['primes'][2]->subtract($one);
|
||||
$exponents[] = $components['publicExponent']->modInverse($temp);
|
||||
$components['exponents'] = $exponents;
|
||||
}
|
||||
|
||||
if (!isset($components['coefficients'])) {
|
||||
$components['coefficients'] = [2 => $components['primes'][2]->modInverse($components['primes'][1])];
|
||||
}
|
||||
|
||||
foreach (['privateexponent', 'd'] as $index) {
|
||||
if (isset($key[$index])) {
|
||||
$components['privateExponent'] = $key[$index];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $components;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a private key to the appropriate format.
|
||||
*/
|
||||
public static function savePrivateKey(BigInteger $n, BigInteger $e, BigInteger $d, array $primes, array $exponents, array $coefficients, ?string $password = null, array $options = []): string
|
||||
{
|
||||
if (!empty($password) && is_string($password)) {
|
||||
throw new UnsupportedFormatException('Raw private keys do not support encryption');
|
||||
}
|
||||
|
||||
return serialize([
|
||||
'e' => clone $e,
|
||||
'n' => clone $n,
|
||||
'd' => clone $d,
|
||||
'primes' => array_map(fn ($var) => clone $var, $primes),
|
||||
'exponents' => array_map(fn ($var) => clone $var, $exponents),
|
||||
'coefficients' => array_map(fn ($var) => clone $var, $coefficients),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a public key to the appropriate format
|
||||
*/
|
||||
public static function savePublicKey(BigInteger $n, BigInteger $e): array
|
||||
{
|
||||
return ['e' => clone $e, 'n' => clone $n];
|
||||
}
|
||||
}
|
||||
162
qa-tool/htdocs/oidc/phpseclib/Crypt/RSA/Formats/Keys/XML.php
Normal file
162
qa-tool/htdocs/oidc/phpseclib/Crypt/RSA/Formats/Keys/XML.php
Normal file
@@ -0,0 +1,162 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* XML Formatted RSA Key Handler
|
||||
*
|
||||
* More info:
|
||||
*
|
||||
* http://www.w3.org/TR/xmldsig-core/#sec-RSAKeyValue
|
||||
* http://www.w3.org/TR/xkms2/#XKMS_2_0_Paragraph_269
|
||||
* http://en.wikipedia.org/wiki/XML_Signature
|
||||
* http://en.wikipedia.org/wiki/XKMS
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @copyright 2015 Jim Wigginton
|
||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace phpseclib3\Crypt\RSA\Formats\Keys;
|
||||
|
||||
use phpseclib3\Common\Functions\Strings;
|
||||
use phpseclib3\Exception\BadConfigurationException;
|
||||
use phpseclib3\Exception\InvalidArgumentException;
|
||||
use phpseclib3\Exception\UnexpectedValueException;
|
||||
use phpseclib3\Exception\UnsupportedFormatException;
|
||||
use phpseclib3\Math\BigInteger;
|
||||
|
||||
/**
|
||||
* XML Formatted RSA Key Handler
|
||||
*
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
*/
|
||||
abstract class XML
|
||||
{
|
||||
/**
|
||||
* Break a public or private key down into its constituent components
|
||||
*
|
||||
* @param string|array $key
|
||||
*/
|
||||
public static function load($key): array
|
||||
{
|
||||
if (!Strings::is_stringable($key)) {
|
||||
throw new UnexpectedValueException('Key should be a string - not a ' . gettype($key));
|
||||
}
|
||||
|
||||
if (!class_exists('DOMDocument')) {
|
||||
throw new BadConfigurationException('The dom extension is not setup correctly on this system');
|
||||
}
|
||||
|
||||
$components = [
|
||||
'isPublicKey' => false,
|
||||
'primes' => [],
|
||||
'exponents' => [],
|
||||
'coefficients' => [],
|
||||
];
|
||||
|
||||
$use_errors = libxml_use_internal_errors(true);
|
||||
|
||||
$dom = new \DOMDocument();
|
||||
if (substr($key, 0, 5) != '<?xml') {
|
||||
$key = '<xml>' . $key . '</xml>';
|
||||
}
|
||||
if (!$dom->loadXML($key)) {
|
||||
libxml_use_internal_errors($use_errors);
|
||||
throw new UnexpectedValueException('Key does not appear to contain XML');
|
||||
}
|
||||
$xpath = new \DOMXPath($dom);
|
||||
$keys = ['modulus', 'exponent', 'p', 'q', 'dp', 'dq', 'inverseq', 'd'];
|
||||
foreach ($keys as $key) {
|
||||
// $dom->getElementsByTagName($key) is case-sensitive
|
||||
$temp = $xpath->query("//*[translate(local-name(), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz')='$key']");
|
||||
if (!$temp->length) {
|
||||
continue;
|
||||
}
|
||||
$value = new BigInteger(Strings::base64_decode($temp->item(0)->nodeValue), 256);
|
||||
switch ($key) {
|
||||
case 'modulus':
|
||||
$components['modulus'] = $value;
|
||||
break;
|
||||
case 'exponent':
|
||||
$components['publicExponent'] = $value;
|
||||
break;
|
||||
case 'p':
|
||||
$components['primes'][1] = $value;
|
||||
break;
|
||||
case 'q':
|
||||
$components['primes'][2] = $value;
|
||||
break;
|
||||
case 'dp':
|
||||
$components['exponents'][1] = $value;
|
||||
break;
|
||||
case 'dq':
|
||||
$components['exponents'][2] = $value;
|
||||
break;
|
||||
case 'inverseq':
|
||||
$components['coefficients'][2] = $value;
|
||||
break;
|
||||
case 'd':
|
||||
$components['privateExponent'] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
libxml_use_internal_errors($use_errors);
|
||||
|
||||
foreach ($components as $key => $value) {
|
||||
if (is_array($value) && !count($value)) {
|
||||
unset($components[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($components['modulus']) && isset($components['publicExponent'])) {
|
||||
if (count($components) == 3) {
|
||||
$components['isPublicKey'] = true;
|
||||
}
|
||||
return $components;
|
||||
}
|
||||
|
||||
throw new UnexpectedValueException('Modulus / exponent not present');
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a private key to the appropriate format.
|
||||
*
|
||||
* @param string $password optional
|
||||
*/
|
||||
public static function savePrivateKey(BigInteger $n, BigInteger $e, BigInteger $d, array $primes, array $exponents, array $coefficients, string $password = ''): string
|
||||
{
|
||||
if (count($primes) != 2) {
|
||||
throw new InvalidArgumentException('XML does not support multi-prime RSA keys');
|
||||
}
|
||||
|
||||
if (!empty($password) && is_string($password)) {
|
||||
throw new UnsupportedFormatException('XML private keys do not support encryption');
|
||||
}
|
||||
|
||||
return "<RSAKeyPair>\r\n" .
|
||||
' <Modulus>' . Strings::base64_encode($n->toBytes()) . "</Modulus>\r\n" .
|
||||
' <Exponent>' . Strings::base64_encode($e->toBytes()) . "</Exponent>\r\n" .
|
||||
' <P>' . Strings::base64_encode($primes[1]->toBytes()) . "</P>\r\n" .
|
||||
' <Q>' . Strings::base64_encode($primes[2]->toBytes()) . "</Q>\r\n" .
|
||||
' <DP>' . Strings::base64_encode($exponents[1]->toBytes()) . "</DP>\r\n" .
|
||||
' <DQ>' . Strings::base64_encode($exponents[2]->toBytes()) . "</DQ>\r\n" .
|
||||
' <InverseQ>' . Strings::base64_encode($coefficients[2]->toBytes()) . "</InverseQ>\r\n" .
|
||||
' <D>' . Strings::base64_encode($d->toBytes()) . "</D>\r\n" .
|
||||
'</RSAKeyPair>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a public key to the appropriate format
|
||||
*/
|
||||
public static function savePublicKey(BigInteger $n, BigInteger $e): string
|
||||
{
|
||||
return "<RSAKeyValue>\r\n" .
|
||||
' <Modulus>' . Strings::base64_encode($n->toBytes()) . "</Modulus>\r\n" .
|
||||
' <Exponent>' . Strings::base64_encode($e->toBytes()) . "</Exponent>\r\n" .
|
||||
'</RSAKeyValue>';
|
||||
}
|
||||
}
|
||||
514
qa-tool/htdocs/oidc/phpseclib/Crypt/RSA/PrivateKey.php
Normal file
514
qa-tool/htdocs/oidc/phpseclib/Crypt/RSA/PrivateKey.php
Normal file
@@ -0,0 +1,514 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* RSA Private Key
|
||||
*
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @copyright 2015 Jim Wigginton
|
||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace phpseclib3\Crypt\RSA;
|
||||
|
||||
use phpseclib3\Crypt\Common;
|
||||
use phpseclib3\Crypt\Random;
|
||||
use phpseclib3\Crypt\RSA;
|
||||
use phpseclib3\Crypt\RSA\Formats\Keys\PSS;
|
||||
use phpseclib3\Exception\LengthException;
|
||||
use phpseclib3\Exception\OutOfRangeException;
|
||||
use phpseclib3\Exception\RuntimeException;
|
||||
use phpseclib3\Exception\UnsupportedFormatException;
|
||||
use phpseclib3\Math\BigInteger;
|
||||
|
||||
/**
|
||||
* Raw RSA Key Handler
|
||||
*
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
*/
|
||||
final class PrivateKey extends RSA implements Common\PrivateKey
|
||||
{
|
||||
use Common\Traits\PasswordProtected;
|
||||
|
||||
/**
|
||||
* Primes for Chinese Remainder Theorem (ie. p and q)
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $primes;
|
||||
|
||||
/**
|
||||
* Exponents for Chinese Remainder Theorem (ie. dP and dQ)
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $exponents;
|
||||
|
||||
/**
|
||||
* Coefficients for Chinese Remainder Theorem (ie. qInv)
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $coefficients;
|
||||
|
||||
/**
|
||||
* Private Exponent
|
||||
*
|
||||
* @var BigInteger
|
||||
*/
|
||||
protected $privateExponent;
|
||||
|
||||
/**
|
||||
* RSADP
|
||||
*
|
||||
* See {@link http://tools.ietf.org/html/rfc3447#section-5.1.2 RFC3447#section-5.1.2}.
|
||||
*
|
||||
* @return bool|BigInteger
|
||||
*/
|
||||
private function rsadp(BigInteger $c)
|
||||
{
|
||||
if ($c->compare(self::$zero) < 0 || $c->compare($this->modulus) > 0) {
|
||||
throw new OutOfRangeException('Ciphertext representative out of range');
|
||||
}
|
||||
return $this->exponentiate($c);
|
||||
}
|
||||
|
||||
/**
|
||||
* RSASP1
|
||||
*
|
||||
* See {@link http://tools.ietf.org/html/rfc3447#section-5.2.1 RFC3447#section-5.2.1}.
|
||||
*
|
||||
* @return bool|BigInteger
|
||||
*/
|
||||
private function rsasp1(BigInteger $m)
|
||||
{
|
||||
if ($m->compare(self::$zero) < 0 || $m->compare($this->modulus) > 0) {
|
||||
throw new OutOfRangeException('Signature representative out of range');
|
||||
}
|
||||
return $this->exponentiate($m);
|
||||
}
|
||||
|
||||
/**
|
||||
* Exponentiate
|
||||
*/
|
||||
protected function exponentiate(BigInteger $x): BigInteger
|
||||
{
|
||||
switch (true) {
|
||||
case empty($this->primes):
|
||||
case $this->primes[1]->equals(self::$zero):
|
||||
case empty($this->coefficients):
|
||||
case $this->coefficients[2]->equals(self::$zero):
|
||||
case empty($this->exponents):
|
||||
case $this->exponents[1]->equals(self::$zero):
|
||||
return $x->modPow($this->exponent, $this->modulus);
|
||||
}
|
||||
|
||||
$num_primes = count($this->primes);
|
||||
|
||||
if (!static::$enableBlinding) {
|
||||
$m_i = [
|
||||
1 => $x->modPow($this->exponents[1], $this->primes[1]),
|
||||
2 => $x->modPow($this->exponents[2], $this->primes[2]),
|
||||
];
|
||||
$h = $m_i[1]->subtract($m_i[2]);
|
||||
$h = $h->multiply($this->coefficients[2]);
|
||||
[, $h] = $h->divide($this->primes[1]);
|
||||
$m = $m_i[2]->add($h->multiply($this->primes[2]));
|
||||
|
||||
$r = $this->primes[1];
|
||||
for ($i = 3; $i <= $num_primes; $i++) {
|
||||
$m_i = $x->modPow($this->exponents[$i], $this->primes[$i]);
|
||||
|
||||
$r = $r->multiply($this->primes[$i - 1]);
|
||||
|
||||
$h = $m_i->subtract($m);
|
||||
$h = $h->multiply($this->coefficients[$i]);
|
||||
[, $h] = $h->divide($this->primes[$i]);
|
||||
|
||||
$m = $m->add($r->multiply($h));
|
||||
}
|
||||
} else {
|
||||
$smallest = $this->primes[1];
|
||||
for ($i = 2; $i <= $num_primes; $i++) {
|
||||
if ($smallest->compare($this->primes[$i]) > 0) {
|
||||
$smallest = $this->primes[$i];
|
||||
}
|
||||
}
|
||||
|
||||
$r = BigInteger::randomRange(self::$one, $smallest->subtract(self::$one));
|
||||
|
||||
$m_i = [
|
||||
1 => $this->blind($x, $r, 1),
|
||||
2 => $this->blind($x, $r, 2),
|
||||
];
|
||||
$h = $m_i[1]->subtract($m_i[2]);
|
||||
$h = $h->multiply($this->coefficients[2]);
|
||||
[, $h] = $h->divide($this->primes[1]);
|
||||
$m = $m_i[2]->add($h->multiply($this->primes[2]));
|
||||
|
||||
$r = $this->primes[1];
|
||||
for ($i = 3; $i <= $num_primes; $i++) {
|
||||
$m_i = $this->blind($x, $r, $i);
|
||||
|
||||
$r = $r->multiply($this->primes[$i - 1]);
|
||||
|
||||
$h = $m_i->subtract($m);
|
||||
$h = $h->multiply($this->coefficients[$i]);
|
||||
[, $h] = $h->divide($this->primes[$i]);
|
||||
|
||||
$m = $m->add($r->multiply($h));
|
||||
}
|
||||
}
|
||||
|
||||
return $m;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs RSA Blinding
|
||||
*
|
||||
* Protects against timing attacks by employing RSA Blinding.
|
||||
* Returns $x->modPow($this->exponents[$i], $this->primes[$i])
|
||||
*/
|
||||
private function blind(BigInteger $x, BigInteger $r, int $i): BigInteger
|
||||
{
|
||||
$x = $x->multiply($r->modPow($this->publicExponent, $this->primes[$i]));
|
||||
$x = $x->modPow($this->exponents[$i], $this->primes[$i]);
|
||||
|
||||
$r = $r->modInverse($this->primes[$i]);
|
||||
$x = $x->multiply($r);
|
||||
[, $x] = $x->divide($this->primes[$i]);
|
||||
|
||||
return $x;
|
||||
}
|
||||
|
||||
/**
|
||||
* EMSA-PSS-ENCODE
|
||||
*
|
||||
* See {@link http://tools.ietf.org/html/rfc3447#section-9.1.1 RFC3447#section-9.1.1}.
|
||||
*
|
||||
* @throws RuntimeException on encoding error
|
||||
*/
|
||||
private function emsa_pss_encode(string $m, int $emBits): string
|
||||
{
|
||||
// if $m is larger than two million terrabytes and you're using sha1, PKCS#1 suggests a "Label too long" error
|
||||
// be output.
|
||||
|
||||
$emLen = ($emBits + 1) >> 3; // ie. ceil($emBits / 8)
|
||||
$sLen = $this->sLen !== null ? $this->sLen : $this->hLen;
|
||||
|
||||
$mHash = $this->hash->hash($m);
|
||||
if ($emLen < $this->hLen + $sLen + 2) {
|
||||
throw new LengthException('RSA modulus too short');
|
||||
}
|
||||
|
||||
$salt = Random::string($sLen);
|
||||
$m2 = "\0\0\0\0\0\0\0\0" . $mHash . $salt;
|
||||
$h = $this->hash->hash($m2);
|
||||
$ps = str_repeat(chr(0), $emLen - $sLen - $this->hLen - 2);
|
||||
$db = $ps . chr(1) . $salt;
|
||||
$dbMask = $this->mgf1($h, $emLen - $this->hLen - 1); // ie. stlren($db)
|
||||
$maskedDB = $db ^ $dbMask;
|
||||
$maskedDB[0] = ~chr(0xFF << ($emBits & 7)) & $maskedDB[0];
|
||||
$em = $maskedDB . $h . chr(0xBC);
|
||||
|
||||
return $em;
|
||||
}
|
||||
|
||||
/**
|
||||
* RSASSA-PSS-SIGN
|
||||
*
|
||||
* See {@link http://tools.ietf.org/html/rfc3447#section-8.1.1 RFC3447#section-8.1.1}.
|
||||
*
|
||||
* @return bool|string
|
||||
*/
|
||||
private function rsassa_pss_sign(string $m)
|
||||
{
|
||||
// EMSA-PSS encoding
|
||||
|
||||
$em = $this->emsa_pss_encode($m, 8 * $this->k - 1);
|
||||
|
||||
// RSA signature
|
||||
|
||||
$m = $this->os2ip($em);
|
||||
$s = $this->rsasp1($m);
|
||||
$s = $this->i2osp($s, $this->k);
|
||||
|
||||
// Output the signature S
|
||||
|
||||
return $s;
|
||||
}
|
||||
|
||||
/**
|
||||
* RSASSA-PKCS1-V1_5-SIGN
|
||||
*
|
||||
* See {@link http://tools.ietf.org/html/rfc3447#section-8.2.1 RFC3447#section-8.2.1}.
|
||||
*
|
||||
* @return bool|string
|
||||
* @throws LengthException if the RSA modulus is too short
|
||||
*/
|
||||
private function rsassa_pkcs1_v1_5_sign(string $m)
|
||||
{
|
||||
// EMSA-PKCS1-v1_5 encoding
|
||||
|
||||
// If the encoding operation outputs "intended encoded message length too short," output "RSA modulus
|
||||
// too short" and stop.
|
||||
try {
|
||||
$em = $this->emsa_pkcs1_v1_5_encode($m, $this->k);
|
||||
} catch (\LengthException $e) {
|
||||
throw new LengthException('RSA modulus too short');
|
||||
}
|
||||
|
||||
// RSA signature
|
||||
|
||||
$m = $this->os2ip($em);
|
||||
$s = $this->rsasp1($m);
|
||||
$s = $this->i2osp($s, $this->k);
|
||||
|
||||
// Output the signature S
|
||||
|
||||
return $s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a signature
|
||||
*
|
||||
* @see self::verify()
|
||||
* @param string $message
|
||||
* @return string
|
||||
*/
|
||||
public function sign($message)
|
||||
{
|
||||
switch ($this->signaturePadding) {
|
||||
case self::SIGNATURE_PKCS1:
|
||||
case self::SIGNATURE_RELAXED_PKCS1:
|
||||
return $this->rsassa_pkcs1_v1_5_sign($message);
|
||||
//case self::SIGNATURE_PSS:
|
||||
default:
|
||||
return $this->rsassa_pss_sign($message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* RSAES-PKCS1-V1_5-DECRYPT
|
||||
*
|
||||
* See {@link http://tools.ietf.org/html/rfc3447#section-7.2.2 RFC3447#section-7.2.2}.
|
||||
*
|
||||
* @return bool|string
|
||||
*/
|
||||
private function rsaes_pkcs1_v1_5_decrypt(string $c)
|
||||
{
|
||||
// Length checking
|
||||
|
||||
if (strlen($c) != $this->k) { // or if k < 11
|
||||
throw new LengthException('Ciphertext representative too long');
|
||||
}
|
||||
|
||||
// RSA decryption
|
||||
|
||||
$c = $this->os2ip($c);
|
||||
$m = $this->rsadp($c);
|
||||
$em = $this->i2osp($m, $this->k);
|
||||
|
||||
// EME-PKCS1-v1_5 decoding
|
||||
|
||||
if (ord($em[0]) != 0 || ord($em[1]) > 2) {
|
||||
throw new RuntimeException('Decryption error');
|
||||
}
|
||||
|
||||
$ps = substr($em, 2, strpos($em, chr(0), 2) - 2);
|
||||
$m = substr($em, strlen($ps) + 3);
|
||||
|
||||
if (strlen($ps) < 8) {
|
||||
throw new RuntimeException('Decryption error');
|
||||
}
|
||||
|
||||
// Output M
|
||||
|
||||
return $m;
|
||||
}
|
||||
|
||||
/**
|
||||
* RSAES-OAEP-DECRYPT
|
||||
*
|
||||
* See {@link http://tools.ietf.org/html/rfc3447#section-7.1.2 RFC3447#section-7.1.2}. The fact that the error
|
||||
* messages aren't distinguishable from one another hinders debugging, but, to quote from RFC3447#section-7.1.2:
|
||||
*
|
||||
* Note. Care must be taken to ensure that an opponent cannot
|
||||
* distinguish the different error conditions in Step 3.g, whether by
|
||||
* error message or timing, or, more generally, learn partial
|
||||
* information about the encoded message EM. Otherwise an opponent may
|
||||
* be able to obtain useful information about the decryption of the
|
||||
* ciphertext C, leading to a chosen-ciphertext attack such as the one
|
||||
* observed by Manger [36].
|
||||
*
|
||||
* @return bool|string
|
||||
*/
|
||||
private function rsaes_oaep_decrypt(string $c)
|
||||
{
|
||||
// Length checking
|
||||
|
||||
// if $l is larger than two million terrabytes and you're using sha1, PKCS#1 suggests a "Label too long" error
|
||||
// be output.
|
||||
|
||||
if (strlen($c) != $this->k || $this->k < 2 * $this->hLen + 2) {
|
||||
throw new LengthException('Ciphertext representative too long');
|
||||
}
|
||||
|
||||
// RSA decryption
|
||||
|
||||
$c = $this->os2ip($c);
|
||||
$m = $this->rsadp($c);
|
||||
$em = $this->i2osp($m, $this->k);
|
||||
|
||||
// EME-OAEP decoding
|
||||
|
||||
$lHash = $this->hash->hash($this->label);
|
||||
$y = ord($em[0]);
|
||||
$maskedSeed = substr($em, 1, $this->hLen);
|
||||
$maskedDB = substr($em, $this->hLen + 1);
|
||||
$seedMask = $this->mgf1($maskedDB, $this->hLen);
|
||||
$seed = $maskedSeed ^ $seedMask;
|
||||
$dbMask = $this->mgf1($seed, $this->k - $this->hLen - 1);
|
||||
$db = $maskedDB ^ $dbMask;
|
||||
$lHash2 = substr($db, 0, $this->hLen);
|
||||
$m = substr($db, $this->hLen);
|
||||
$hashesMatch = hash_equals($lHash, $lHash2);
|
||||
$leadingZeros = 1;
|
||||
$patternMatch = 0;
|
||||
$offset = 0;
|
||||
for ($i = 0; $i < strlen($m); $i++) {
|
||||
$patternMatch |= $leadingZeros & ($m[$i] === "\1");
|
||||
$leadingZeros &= $m[$i] === "\0";
|
||||
$offset += $patternMatch ? 0 : 1;
|
||||
}
|
||||
|
||||
// we do | instead of || to avoid https://en.wikipedia.org/wiki/Short-circuit_evaluation
|
||||
// to protect against timing attacks
|
||||
if (!$hashesMatch | !$patternMatch) {
|
||||
throw new RuntimeException('Decryption error');
|
||||
}
|
||||
|
||||
// Output the message M
|
||||
|
||||
return substr($m, $offset + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Raw Encryption / Decryption
|
||||
*
|
||||
* Doesn't use padding and is not recommended.
|
||||
*
|
||||
* @return bool|string
|
||||
* @throws LengthException if strlen($m) > $this->k
|
||||
*/
|
||||
private function raw_encrypt(string $m)
|
||||
{
|
||||
if (strlen($m) > $this->k) {
|
||||
throw new LengthException('Ciphertext representative too long');
|
||||
}
|
||||
|
||||
$temp = $this->os2ip($m);
|
||||
$temp = $this->rsadp($temp);
|
||||
return $this->i2osp($temp, $this->k);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decryption
|
||||
*
|
||||
* @return bool|string
|
||||
* @see self::encrypt()
|
||||
*/
|
||||
public function decrypt(string $ciphertext)
|
||||
{
|
||||
switch ($this->encryptionPadding) {
|
||||
case self::ENCRYPTION_NONE:
|
||||
return $this->raw_encrypt($ciphertext);
|
||||
case self::ENCRYPTION_PKCS1:
|
||||
return $this->rsaes_pkcs1_v1_5_decrypt($ciphertext);
|
||||
//case self::ENCRYPTION_OAEP:
|
||||
default:
|
||||
return $this->rsaes_oaep_decrypt($ciphertext);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the public key
|
||||
*/
|
||||
public function getPublicKey(): RSA
|
||||
{
|
||||
$type = self::validatePlugin('Keys', 'PKCS8', 'savePublicKey');
|
||||
if (empty($this->modulus) || empty($this->publicExponent)) {
|
||||
throw new RuntimeException('Public key components not found');
|
||||
}
|
||||
|
||||
$key = $type::savePublicKey($this->modulus, $this->publicExponent);
|
||||
return RSA::loadFormat('PKCS8', $key)
|
||||
->withHash($this->hash->getHash())
|
||||
->withMGFHash($this->mgfHash->getHash())
|
||||
->withSaltLength($this->sLen)
|
||||
->withLabel($this->label)
|
||||
->withPadding($this->signaturePadding | $this->encryptionPadding);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the private key
|
||||
*
|
||||
* @param array $options optional
|
||||
*/
|
||||
public function toString(string $type, array $options = []): string
|
||||
{
|
||||
$type = self::validatePlugin(
|
||||
'Keys',
|
||||
$type,
|
||||
empty($this->primes) ? 'savePublicKey' : 'savePrivateKey'
|
||||
);
|
||||
|
||||
if ($type == PSS::class) {
|
||||
if ($this->signaturePadding == self::SIGNATURE_PSS) {
|
||||
$options += [
|
||||
'hash' => $this->hash->getHash(),
|
||||
'MGFHash' => $this->mgfHash->getHash(),
|
||||
'saltLength' => $this->getSaltLength(),
|
||||
];
|
||||
} else {
|
||||
throw new UnsupportedFormatException('The PSS format can only be used when the signature method has been explicitly set to PSS');
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($this->primes)) {
|
||||
return $type::savePublicKey($this->modulus, $this->exponent, $options);
|
||||
}
|
||||
|
||||
return $type::savePrivateKey($this->modulus, $this->publicExponent, $this->exponent, $this->primes, $this->exponents, $this->coefficients, $this->password, $options);
|
||||
|
||||
/*
|
||||
$key = $type::savePrivateKey($this->modulus, $this->publicExponent, $this->exponent, $this->primes, $this->exponents, $this->coefficients, $this->password, $options);
|
||||
if ($key !== false || count($this->primes) == 2) {
|
||||
return $key;
|
||||
}
|
||||
|
||||
$nSize = $this->getSize() >> 1;
|
||||
|
||||
$primes = [1 => clone self::$one, clone self::$one];
|
||||
$i = 1;
|
||||
foreach ($this->primes as $prime) {
|
||||
$primes[$i] = $primes[$i]->multiply($prime);
|
||||
if ($primes[$i]->getLength() >= $nSize) {
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
|
||||
$exponents = [];
|
||||
$coefficients = [2 => $primes[2]->modInverse($primes[1])];
|
||||
|
||||
foreach ($primes as $i => $prime) {
|
||||
$temp = $prime->subtract(self::$one);
|
||||
$exponents[$i] = $this->modulus->modInverse($temp);
|
||||
}
|
||||
|
||||
return $type::savePrivateKey($this->modulus, $this->publicExponent, $this->exponent, $primes, $exponents, $coefficients, $this->password, $options);
|
||||
*/
|
||||
}
|
||||
}
|
||||
491
qa-tool/htdocs/oidc/phpseclib/Crypt/RSA/PublicKey.php
Normal file
491
qa-tool/htdocs/oidc/phpseclib/Crypt/RSA/PublicKey.php
Normal file
@@ -0,0 +1,491 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* RSA Public Key
|
||||
*
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @copyright 2015 Jim Wigginton
|
||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace phpseclib3\Crypt\RSA;
|
||||
|
||||
use phpseclib3\Common\Functions\Strings;
|
||||
use phpseclib3\Crypt\Common;
|
||||
use phpseclib3\Crypt\Hash;
|
||||
use phpseclib3\Crypt\Random;
|
||||
use phpseclib3\Crypt\RSA;
|
||||
use phpseclib3\Crypt\RSA\Formats\Keys\PSS;
|
||||
use phpseclib3\Exception\LengthException;
|
||||
use phpseclib3\Exception\OutOfRangeException;
|
||||
use phpseclib3\Exception\UnsupportedAlgorithmException;
|
||||
use phpseclib3\Exception\UnsupportedFormatException;
|
||||
use phpseclib3\File\ASN1;
|
||||
use phpseclib3\File\ASN1\Maps\DigestInfo;
|
||||
use phpseclib3\Math\BigInteger;
|
||||
|
||||
/**
|
||||
* Raw RSA Key Handler
|
||||
*
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
*/
|
||||
final class PublicKey extends RSA implements Common\PublicKey
|
||||
{
|
||||
use Common\Traits\Fingerprint;
|
||||
|
||||
/**
|
||||
* Exponentiate
|
||||
*/
|
||||
private function exponentiate(BigInteger $x): BigInteger
|
||||
{
|
||||
return $x->modPow($this->exponent, $this->modulus);
|
||||
}
|
||||
|
||||
/**
|
||||
* RSAVP1
|
||||
*
|
||||
* See {@link http://tools.ietf.org/html/rfc3447#section-5.2.2 RFC3447#section-5.2.2}.
|
||||
*
|
||||
* @return bool|BigInteger
|
||||
*/
|
||||
private function rsavp1(BigInteger $s)
|
||||
{
|
||||
if ($s->compare(self::$zero) < 0 || $s->compare($this->modulus) > 0) {
|
||||
return false;
|
||||
}
|
||||
return $this->exponentiate($s);
|
||||
}
|
||||
|
||||
/**
|
||||
* RSASSA-PKCS1-V1_5-VERIFY
|
||||
*
|
||||
* See {@link http://tools.ietf.org/html/rfc3447#section-8.2.2 RFC3447#section-8.2.2}.
|
||||
*
|
||||
* @throws LengthException if the RSA modulus is too short
|
||||
*/
|
||||
private function rsassa_pkcs1_v1_5_verify(string $m, string $s): bool
|
||||
{
|
||||
// Length checking
|
||||
|
||||
if (strlen($s) != $this->k) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// RSA verification
|
||||
|
||||
$s = $this->os2ip($s);
|
||||
$m2 = $this->rsavp1($s);
|
||||
if ($m2 === false) {
|
||||
return false;
|
||||
}
|
||||
$em = $this->i2osp($m2, $this->k);
|
||||
if ($em === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// EMSA-PKCS1-v1_5 encoding
|
||||
|
||||
$exception = false;
|
||||
|
||||
// If the encoding operation outputs "intended encoded message length too short," output "RSA modulus
|
||||
// too short" and stop.
|
||||
try {
|
||||
$em2 = $this->emsa_pkcs1_v1_5_encode($m, $this->k);
|
||||
$r1 = hash_equals($em, $em2);
|
||||
} catch (\LengthException $e) {
|
||||
$exception = true;
|
||||
}
|
||||
|
||||
try {
|
||||
$em3 = $this->emsa_pkcs1_v1_5_encode_without_null($m, $this->k);
|
||||
$r2 = hash_equals($em, $em3);
|
||||
} catch (\LengthException $e) {
|
||||
$exception = true;
|
||||
} catch (UnsupportedAlgorithmException $e) {
|
||||
$r2 = false;
|
||||
}
|
||||
|
||||
if ($exception) {
|
||||
throw new LengthException('RSA modulus too short');
|
||||
}
|
||||
|
||||
// Compare
|
||||
return $r1 || $r2;
|
||||
}
|
||||
|
||||
/**
|
||||
* RSASSA-PKCS1-V1_5-VERIFY (relaxed matching)
|
||||
*
|
||||
* Per {@link http://tools.ietf.org/html/rfc3447#page-43 RFC3447#page-43} PKCS1 v1.5
|
||||
* specified the use BER encoding rather than DER encoding that PKCS1 v2.0 specified.
|
||||
* This means that under rare conditions you can have a perfectly valid v1.5 signature
|
||||
* that fails to validate with _rsassa_pkcs1_v1_5_verify(). PKCS1 v2.1 also recommends
|
||||
* that if you're going to validate these types of signatures you "should indicate
|
||||
* whether the underlying BER encoding is a DER encoding and hence whether the signature
|
||||
* is valid with respect to the specification given in [PKCS1 v2.0+]". so if you do
|
||||
* $rsa->getLastPadding() and get RSA::PADDING_RELAXED_PKCS1 back instead of
|
||||
* RSA::PADDING_PKCS1... that means BER encoding was used.
|
||||
*/
|
||||
private function rsassa_pkcs1_v1_5_relaxed_verify(string $m, string $s): bool
|
||||
{
|
||||
// Length checking
|
||||
|
||||
if (strlen($s) != $this->k) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// RSA verification
|
||||
|
||||
$s = $this->os2ip($s);
|
||||
$m2 = $this->rsavp1($s);
|
||||
if ($m2 === false) {
|
||||
return false;
|
||||
}
|
||||
$em = $this->i2osp($m2, $this->k);
|
||||
if ($em === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Strings::shift($em, 2) != "\0\1") {
|
||||
return false;
|
||||
}
|
||||
|
||||
$em = ltrim($em, "\xFF");
|
||||
if (Strings::shift($em) != "\0") {
|
||||
return false;
|
||||
}
|
||||
|
||||
$decoded = ASN1::decodeBER($em);
|
||||
if (!is_array($decoded) || empty($decoded[0]) || strlen($em) > $decoded[0]['length']) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static $oids;
|
||||
if (!isset($oids)) {
|
||||
$oids = [
|
||||
'md2' => '1.2.840.113549.2.2',
|
||||
'md4' => '1.2.840.113549.2.4', // from PKCS1 v1.5
|
||||
'md5' => '1.2.840.113549.2.5',
|
||||
'id-sha1' => '1.3.14.3.2.26',
|
||||
'id-sha256' => '2.16.840.1.101.3.4.2.1',
|
||||
'id-sha384' => '2.16.840.1.101.3.4.2.2',
|
||||
'id-sha512' => '2.16.840.1.101.3.4.2.3',
|
||||
// from PKCS1 v2.2
|
||||
'id-sha224' => '2.16.840.1.101.3.4.2.4',
|
||||
'id-sha512/224' => '2.16.840.1.101.3.4.2.5',
|
||||
'id-sha512/256' => '2.16.840.1.101.3.4.2.6',
|
||||
];
|
||||
ASN1::loadOIDs($oids);
|
||||
}
|
||||
|
||||
$decoded = ASN1::asn1map($decoded[0], DigestInfo::MAP);
|
||||
if (!isset($decoded) || $decoded === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!isset($oids[$decoded['digestAlgorithm']['algorithm']])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isset($decoded['digestAlgorithm']['parameters']) && $decoded['digestAlgorithm']['parameters'] !== ['null' => '']) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$hash = $decoded['digestAlgorithm']['algorithm'];
|
||||
$hash = substr($hash, 0, 3) == 'id-' ?
|
||||
substr($hash, 3) :
|
||||
$hash;
|
||||
$hash = new Hash($hash);
|
||||
$em = $hash->hash($m);
|
||||
$em2 = $decoded['digest'];
|
||||
|
||||
return hash_equals($em, $em2);
|
||||
}
|
||||
|
||||
/**
|
||||
* EMSA-PSS-VERIFY
|
||||
*
|
||||
* See {@link http://tools.ietf.org/html/rfc3447#section-9.1.2 RFC3447#section-9.1.2}.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function emsa_pss_verify(string $m, string $em, int $emBits)
|
||||
{
|
||||
// if $m is larger than two million terrabytes and you're using sha1, PKCS#1 suggests a "Label too long" error
|
||||
// be output.
|
||||
|
||||
$emLen = ($emBits + 7) >> 3; // ie. ceil($emBits / 8);
|
||||
$sLen = $this->sLen !== null ? $this->sLen : $this->hLen;
|
||||
|
||||
$mHash = $this->hash->hash($m);
|
||||
if ($emLen < $this->hLen + $sLen + 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($em[-1] != chr(0xBC)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$maskedDB = substr($em, 0, -$this->hLen - 1);
|
||||
$h = substr($em, -$this->hLen - 1, $this->hLen);
|
||||
$temp = chr(0xFF << ($emBits & 7));
|
||||
if ((~$maskedDB[0] & $temp) != $temp) {
|
||||
return false;
|
||||
}
|
||||
$dbMask = $this->mgf1($h, $emLen - $this->hLen - 1);
|
||||
$db = $maskedDB ^ $dbMask;
|
||||
$db[0] = ~chr(0xFF << ($emBits & 7)) & $db[0];
|
||||
$temp = $emLen - $this->hLen - $sLen - 2;
|
||||
if (substr($db, 0, $temp) != str_repeat(chr(0), $temp) || ord($db[$temp]) != 1) {
|
||||
return false;
|
||||
}
|
||||
$salt = substr($db, $temp + 1); // should be $sLen long
|
||||
$m2 = "\0\0\0\0\0\0\0\0" . $mHash . $salt;
|
||||
$h2 = $this->hash->hash($m2);
|
||||
return hash_equals($h, $h2);
|
||||
}
|
||||
|
||||
/**
|
||||
* RSASSA-PSS-VERIFY
|
||||
*
|
||||
* See {@link http://tools.ietf.org/html/rfc3447#section-8.1.2 RFC3447#section-8.1.2}.
|
||||
*
|
||||
* @return bool|string
|
||||
*/
|
||||
private function rsassa_pss_verify(string $m, string $s)
|
||||
{
|
||||
// Length checking
|
||||
|
||||
if (strlen($s) != $this->k) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// RSA verification
|
||||
|
||||
$modBits = strlen($this->modulus->toBits());
|
||||
|
||||
$s2 = $this->os2ip($s);
|
||||
$m2 = $this->rsavp1($s2);
|
||||
$em = $this->i2osp($m2, $this->k);
|
||||
if ($em === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// EMSA-PSS verification
|
||||
|
||||
return $this->emsa_pss_verify($m, $em, $modBits - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies a signature
|
||||
*
|
||||
* @see self::sign()
|
||||
* @param string $message
|
||||
* @param string $signature
|
||||
* @return bool
|
||||
*/
|
||||
public function verify($message, $signature)
|
||||
{
|
||||
switch ($this->signaturePadding) {
|
||||
case self::SIGNATURE_RELAXED_PKCS1:
|
||||
return $this->rsassa_pkcs1_v1_5_relaxed_verify($message, $signature);
|
||||
case self::SIGNATURE_PKCS1:
|
||||
return $this->rsassa_pkcs1_v1_5_verify($message, $signature);
|
||||
//case self::SIGNATURE_PSS:
|
||||
default:
|
||||
return $this->rsassa_pss_verify($message, $signature);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* RSAES-PKCS1-V1_5-ENCRYPT
|
||||
*
|
||||
* See {@link http://tools.ietf.org/html/rfc3447#section-7.2.1 RFC3447#section-7.2.1}.
|
||||
*
|
||||
* @param bool $pkcs15_compat optional
|
||||
* @return bool|string
|
||||
* @throws LengthException if strlen($m) > $this->k - 11
|
||||
*/
|
||||
private function rsaes_pkcs1_v1_5_encrypt(string $m, bool $pkcs15_compat = false)
|
||||
{
|
||||
$mLen = strlen($m);
|
||||
|
||||
// Length checking
|
||||
|
||||
if ($mLen > $this->k - 11) {
|
||||
throw new LengthException('Message too long');
|
||||
}
|
||||
|
||||
// EME-PKCS1-v1_5 encoding
|
||||
|
||||
$psLen = $this->k - $mLen - 3;
|
||||
$ps = '';
|
||||
while (strlen($ps) != $psLen) {
|
||||
$temp = Random::string($psLen - strlen($ps));
|
||||
$temp = str_replace("\x00", '', $temp);
|
||||
$ps .= $temp;
|
||||
}
|
||||
$type = 2;
|
||||
$em = chr(0) . chr($type) . $ps . chr(0) . $m;
|
||||
|
||||
// RSA encryption
|
||||
$m = $this->os2ip($em);
|
||||
$c = $this->rsaep($m);
|
||||
$c = $this->i2osp($c, $this->k);
|
||||
|
||||
// Output the ciphertext C
|
||||
|
||||
return $c;
|
||||
}
|
||||
|
||||
/**
|
||||
* RSAES-OAEP-ENCRYPT
|
||||
*
|
||||
* See {@link http://tools.ietf.org/html/rfc3447#section-7.1.1 RFC3447#section-7.1.1} and
|
||||
* {http://en.wikipedia.org/wiki/Optimal_Asymmetric_Encryption_Padding OAES}.
|
||||
*
|
||||
* @throws LengthException if strlen($m) > $this->k - 2 * $this->hLen - 2
|
||||
*/
|
||||
private function rsaes_oaep_encrypt(string $m): string
|
||||
{
|
||||
$mLen = strlen($m);
|
||||
|
||||
// Length checking
|
||||
|
||||
// if $l is larger than two million terrabytes and you're using sha1, PKCS#1 suggests a "Label too long" error
|
||||
// be output.
|
||||
|
||||
if ($mLen > $this->k - 2 * $this->hLen - 2) {
|
||||
throw new LengthException('Message too long');
|
||||
}
|
||||
|
||||
// EME-OAEP encoding
|
||||
|
||||
$lHash = $this->hash->hash($this->label);
|
||||
$ps = str_repeat(chr(0), $this->k - $mLen - 2 * $this->hLen - 2);
|
||||
$db = $lHash . $ps . chr(1) . $m;
|
||||
$seed = Random::string($this->hLen);
|
||||
$dbMask = $this->mgf1($seed, $this->k - $this->hLen - 1);
|
||||
$maskedDB = $db ^ $dbMask;
|
||||
$seedMask = $this->mgf1($maskedDB, $this->hLen);
|
||||
$maskedSeed = $seed ^ $seedMask;
|
||||
$em = chr(0) . $maskedSeed . $maskedDB;
|
||||
|
||||
// RSA encryption
|
||||
|
||||
$m = $this->os2ip($em);
|
||||
$c = $this->rsaep($m);
|
||||
$c = $this->i2osp($c, $this->k);
|
||||
|
||||
// Output the ciphertext C
|
||||
|
||||
return $c;
|
||||
}
|
||||
|
||||
/**
|
||||
* RSAEP
|
||||
*
|
||||
* See {@link http://tools.ietf.org/html/rfc3447#section-5.1.1 RFC3447#section-5.1.1}.
|
||||
*
|
||||
* @return bool|BigInteger
|
||||
*/
|
||||
private function rsaep(BigInteger $m)
|
||||
{
|
||||
if ($m->compare(self::$zero) < 0 || $m->compare($this->modulus) > 0) {
|
||||
throw new OutOfRangeException('Message representative out of range');
|
||||
}
|
||||
return $this->exponentiate($m);
|
||||
}
|
||||
|
||||
/**
|
||||
* Raw Encryption / Decryption
|
||||
*
|
||||
* Doesn't use padding and is not recommended.
|
||||
*
|
||||
* @return bool|string
|
||||
* @throws LengthException if strlen($m) > $this->k
|
||||
*/
|
||||
private function raw_encrypt(string $m)
|
||||
{
|
||||
if (strlen($m) > $this->k) {
|
||||
throw new LengthException('Message too long');
|
||||
}
|
||||
|
||||
$temp = $this->os2ip($m);
|
||||
$temp = $this->rsaep($temp);
|
||||
return $this->i2osp($temp, $this->k);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encryption
|
||||
*
|
||||
* Both self::PADDING_OAEP and self::PADDING_PKCS1 both place limits on how long $plaintext can be.
|
||||
* If $plaintext exceeds those limits it will be broken up so that it does and the resultant ciphertext's will
|
||||
* be concatenated together.
|
||||
*
|
||||
* @return bool|string
|
||||
* @throws LengthException if the RSA modulus is too short
|
||||
* @see self::decrypt()
|
||||
*/
|
||||
public function encrypt(string $plaintext)
|
||||
{
|
||||
switch ($this->encryptionPadding) {
|
||||
case self::ENCRYPTION_NONE:
|
||||
return $this->raw_encrypt($plaintext);
|
||||
case self::ENCRYPTION_PKCS1:
|
||||
return $this->rsaes_pkcs1_v1_5_encrypt($plaintext);
|
||||
//case self::ENCRYPTION_OAEP:
|
||||
default:
|
||||
return $this->rsaes_oaep_encrypt($plaintext);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the public key
|
||||
*
|
||||
* The public key is only returned under two circumstances - if the private key had the public key embedded within it
|
||||
* or if the public key was set via setPublicKey(). If the currently loaded key is supposed to be the public key this
|
||||
* function won't return it since this library, for the most part, doesn't distinguish between public and private keys.
|
||||
*
|
||||
* @param array $options optional
|
||||
*/
|
||||
public function toString(string $type, array $options = []): string
|
||||
{
|
||||
$type = self::validatePlugin('Keys', $type, 'savePublicKey');
|
||||
|
||||
if ($type == PSS::class) {
|
||||
if ($this->signaturePadding == self::SIGNATURE_PSS) {
|
||||
$options += [
|
||||
'hash' => $this->hash->getHash(),
|
||||
'MGFHash' => $this->mgfHash->getHash(),
|
||||
'saltLength' => $this->getSaltLength(),
|
||||
];
|
||||
} else {
|
||||
throw new UnsupportedFormatException('The PSS format can only be used when the signature method has been explicitly set to PSS');
|
||||
}
|
||||
}
|
||||
|
||||
return $type::savePublicKey($this->modulus, $this->publicExponent, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a public key to a private key
|
||||
*/
|
||||
public function asPrivateKey(): RSA
|
||||
{
|
||||
$new = new PrivateKey();
|
||||
$new->exponent = $this->exponent;
|
||||
$new->modulus = $this->modulus;
|
||||
$new->k = $this->k;
|
||||
$new->format = $this->format;
|
||||
return $new
|
||||
->withHash($this->hash->getHash())
|
||||
->withMGFHash($this->mgfHash->getHash())
|
||||
->withSaltLength($this->sLen)
|
||||
->withLabel($this->label)
|
||||
->withPadding($this->signaturePadding | $this->encryptionPadding);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user