mirror of
https://github.com/danog/tgseclib.git
synced 2024-11-30 04:39:02 +01:00
RSA: add preliminary support for RSA-PSS keys
This commit is contained in:
parent
89e41233e0
commit
8017c74429
@ -32,7 +32,7 @@ use phpseclib\Crypt\Common\Keys\PKCS8 as Progenitor;
|
||||
use phpseclib\File\ASN1;
|
||||
|
||||
/**
|
||||
* PKCS#1 Formatted RSA Key Handler
|
||||
* PKCS#8 Formatted RSA Key Handler
|
||||
*
|
||||
* @package RSA
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
|
149
phpseclib/Crypt/RSA/Keys/PSS.php
Normal file
149
phpseclib/Crypt/RSA/Keys/PSS.php
Normal file
@ -0,0 +1,149 @@
|
||||
<?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 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)
|
||||
*
|
||||
* @category Crypt
|
||||
* @package RSA
|
||||
* @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
|
||||
*/
|
||||
|
||||
namespace phpseclib\Crypt\RSA\Keys;
|
||||
|
||||
use phpseclib\Math\BigInteger;
|
||||
use phpseclib\Crypt\Common\Keys\PKCS8 as Progenitor;
|
||||
use phpseclib\File\ASN1;
|
||||
|
||||
/**
|
||||
* PKCS#8 Formatted RSA-PSS Key Handler
|
||||
*
|
||||
* @package RSA
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @access public
|
||||
*/
|
||||
abstract class PSS extends Progenitor
|
||||
{
|
||||
/**
|
||||
* OID Name
|
||||
*
|
||||
* @var string
|
||||
* @access private
|
||||
*/
|
||||
const OID_NAME = 'id-RSASSA-PSS';
|
||||
|
||||
/**
|
||||
* OID Value
|
||||
*
|
||||
* @var string
|
||||
* @access private
|
||||
*/
|
||||
const OID_VALUE = '1.2.840.113549.1.1.10';
|
||||
|
||||
/**
|
||||
* OIDs loaded
|
||||
*
|
||||
* @var bool
|
||||
* @access private
|
||||
*/
|
||||
private static $oidsLoaded = false;
|
||||
|
||||
/**
|
||||
* Child OIDs loaded
|
||||
*
|
||||
* @var bool
|
||||
* @access private
|
||||
*/
|
||||
protected static $childOIDsLoaded = false;
|
||||
|
||||
/**
|
||||
* Initialize static variables
|
||||
*/
|
||||
private static function initialize_static_variables()
|
||||
{
|
||||
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
|
||||
*
|
||||
* @access public
|
||||
* @param string $key
|
||||
* @param string $password optional
|
||||
* @return array
|
||||
*/
|
||||
public static function load($key, $password = '')
|
||||
{
|
||||
self::initialize_static_variables();
|
||||
|
||||
if (!is_string($key)) {
|
||||
throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key));
|
||||
}
|
||||
|
||||
$components = ['isPublicKey' => strpos($key, 'PUBLIC') !== false];
|
||||
|
||||
$key = parent::load($key, $password);
|
||||
|
||||
$type = isset($key['privateKey']) ? 'private' : 'public';
|
||||
|
||||
$result = $components + PKCS1::load($key[$type . 'Key']);
|
||||
|
||||
$decoded = ASN1::decodeBER($key[$type . 'KeyAlgorithm']['parameters']);
|
||||
if ($decoded === false) {
|
||||
throw new \UnexpectedValueException('Unable to decode parameters');
|
||||
}
|
||||
$params = ASN1::asn1map($decoded[0], ASN1\Maps\RSASSA_PSS_params::MAP);
|
||||
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], ASN1\Maps\HashAlgorithm::MAP);
|
||||
} else {
|
||||
$params['maskGenAlgorithm'] = [
|
||||
'algorithm' => 'id-mgf1',
|
||||
'parameters' => ['algorithm' => 'id-sha1']
|
||||
];
|
||||
}
|
||||
|
||||
$result['hash'] = str_replace('id-', '', $params['hashAlgorithm']['algorithm']);
|
||||
$result['MGFHash'] = str_replace('id-', '', $params['maskGenAlgorithm']['parameters']['algorithm']);
|
||||
$result['saltLength'] = (int) $params['saltLength']->toString();
|
||||
|
||||
if (isset($key['meta'])) {
|
||||
$result['meta'] = $key['meta'];
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
@ -642,9 +642,13 @@ abstract class ASN1
|
||||
case ASN1::TYPE_INTEGER:
|
||||
$map[$key] = new BigInteger($child['default']);
|
||||
break;
|
||||
//case self::TYPE_OBJECT_IDENTIFIER:
|
||||
// if (!isset(self::$reverseOIDs[$name])) {
|
||||
// return null;
|
||||
// }
|
||||
//case ASN1::TYPE_BOOLEAN:
|
||||
default:
|
||||
$map[$key] = $child['type'];
|
||||
$map[$key] = $child['default'];
|
||||
}
|
||||
} elseif (!isset($child['optional'])) {
|
||||
return null; // Syntax error.
|
||||
@ -1491,7 +1495,7 @@ abstract class ASN1
|
||||
* @param string $name
|
||||
* @return string
|
||||
*/
|
||||
static function getOID($name)
|
||||
public static function getOID($name)
|
||||
{
|
||||
return isset(self::$reverseOIDs[$name]) ? self::$reverseOIDs[$name] : $name;
|
||||
}
|
||||
|
30
phpseclib/File/ASN1/Maps/MaskGenAlgorithm.php
Normal file
30
phpseclib/File/ASN1/Maps/MaskGenAlgorithm.php
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* MaskGenAglorithm
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* @category File
|
||||
* @package ASN1
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @copyright 2016 Jim Wigginton
|
||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
||||
namespace phpseclib\File\ASN1\Maps;
|
||||
|
||||
use phpseclib\File\ASN1;
|
||||
|
||||
/**
|
||||
* MaskGenAglorithm
|
||||
*
|
||||
* @package ASN1
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @access public
|
||||
*/
|
||||
abstract class MaskGenAlgorithm
|
||||
{
|
||||
const MAP = AlgorithmIdentifier::MAP;
|
||||
}
|
62
phpseclib/File/ASN1/Maps/RSASSA_PSS_params.php
Normal file
62
phpseclib/File/ASN1/Maps/RSASSA_PSS_params.php
Normal file
@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* RSASSA_PSS_params
|
||||
*
|
||||
* As defined in https://tools.ietf.org/html/rfc4055#section-3.1
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* @category File
|
||||
* @package ASN1
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @copyright 2016 Jim Wigginton
|
||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
||||
namespace phpseclib\File\ASN1\Maps;
|
||||
|
||||
use phpseclib\File\ASN1;
|
||||
|
||||
/**
|
||||
* RSASSA_PSS_params
|
||||
*
|
||||
* @package ASN1
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @access public
|
||||
*/
|
||||
abstract class RSASSA_PSS_params
|
||||
{
|
||||
const MAP = [
|
||||
'type' => ASN1::TYPE_SEQUENCE,
|
||||
'children' => [
|
||||
'hashAlgorithm' => [
|
||||
'constant' => 0,
|
||||
'optional' => true,
|
||||
'explicit' => true,
|
||||
'default' => 'sha1Identifier'
|
||||
] + HashAlgorithm::MAP,
|
||||
'maskGenAlgorithm' => [
|
||||
'constant' => 1,
|
||||
'optional' => true,
|
||||
'explicit' => true,
|
||||
'default' => 'mgf1SHA1Identifier'
|
||||
] + MaskGenAlgorithm::MAP,
|
||||
'saltLength' => [
|
||||
'type' => ASN1::TYPE_INTEGER,
|
||||
'constant' => 2,
|
||||
'optional' => true,
|
||||
'explicit' => true,
|
||||
'default' => 20
|
||||
],
|
||||
'trailerField' => [
|
||||
'type' => ASN1::TYPE_INTEGER,
|
||||
'constant' => 3,
|
||||
'optional' => true,
|
||||
'explicit' => true,
|
||||
'default' => 1
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
@ -878,4 +878,41 @@ OFLPBrLe4Hw=
|
||||
$this->assertInstanceOf(PrivateKey::class, $rsa);
|
||||
$this->assertInstanceOf(PublicKey::class, $rsa->getPublicKey());
|
||||
}
|
||||
|
||||
public function testPSS()
|
||||
{
|
||||
$key = '-----BEGIN PRIVATE KEY-----
|
||||
MIIE7QIBADA9BgkqhkiG9w0BAQowMKANMAsGCWCGSAFlAwQCAaEaMBgGCSqGSIb3
|
||||
DQEBCDALBglghkgBZQMEAgOiAwIBBQSCBKcwggSjAgEAAoIBAQD6L3Z2XUPH7vRU
|
||||
1Xl5aLpW2jH/uhqOitRV2/1QAEQk6VasI2TjJefP6SmL+te71gE4PVTMpm0LoluR
|
||||
IzvQYgeLwDFUzLsn2r/H3lKlS/K0KL890aNPSNuHwKVYQsBd2OuSQQZ04xM1E0VN
|
||||
xELcW4Vc63FTyGzR4okQ2MGHQfxP/FoNNfaIxjyb7ly9feGNR3pIRcL2CEMfyZkq
|
||||
rEE3SxNoGTHMTbIhMGchWTrX1V+VykSgy9+KmD0AD8SwP3nFH3BNLeoLDhkU2L6L
|
||||
p9XYijx3RAvPeYRlMAyOpylRxXM5Z1oBmzaClDVE8mtJkMPpZshGbVwxbzrph8VA
|
||||
FBf3FzYFAgMBAAECggEAMu3Igq3Xp3KIQGC4erOMAzQlq3YaA9xU/ylqNofnV1A8
|
||||
uYv29Jp5xwQi1gD5O56D3wv1IDfcyNqDI1d1zKS3/oXgRO/sRV+tXKVwU3/TZ0NI
|
||||
MvBi+zfMoKThw8bK3A/VXI9qHg8/kLVcjUkfhzYGPvUau8B4Dn28AzbspnkTQMCq
|
||||
FpuC41a8UzOX7rvEKPTLp87fwI1u48ycDKVK0ZKjJMQQl3SbYaVIKZa4ctav/9wC
|
||||
e5LAnap55S0L13FdUHbGJKzUqIk61NgCr8Wo16AYCOULzTTNVE24jl2Dc1H+sk61
|
||||
b1FC/TxW9iWZx9givR1VgjG5fULbxwA/Mve7SYtfIQKBgQD+a/y8pxIPgBXb90Z4
|
||||
poCqRsgJVPmu6sQ8STb0WibtyD/IKECooGOpI16A/884kNyXkfcIwK6txnnPYbmv
|
||||
KlNHgSUnhEeavrHfeUmyyrQaTAs3I0iuL4stOSRHHPDD72PRSkPky6NMErX4F4Vv
|
||||
Y6jkFhwsNJetxf2qInJn5WZ6LQKBgQD7vL+KE0HHLZ3DVaP7pRMOx9FvkhrtmqLZ
|
||||
fSuMUweKqnAFHnkEPZFuyFRMoPL3cHaVLPkGmX8vK/GL/QECKPeDyE/jEFzGQV+L
|
||||
n4PeraS1jzu77uYzWcuKdabFQN939iZ2gV5MUB7Jt4zfURf26fH1UHku7rs/Mik3
|
||||
jLfE9elKOQKBgDzhFi8GQ1oWKiTifKhuHyefnEovXTev0ZkjY9UApYQMgMaiayZu
|
||||
iqp0Xi68B5ffggl60gP0J1hJv+gR2F7D3/2iN4PHMWMj8mgpG6t+ua35OE3PUZrs
|
||||
oX8Gx1mE4U/hPp9cB/b9i2uupoBhEHrg/A7oA4HIa+sXD2XgrEOULvtZAoGBAJ73
|
||||
RRkDKhGGG87jAMeDKXK2+elzoO+UK+wdX+ef8u48zLpe0Nq9ql4DwUAWjvd0HF39
|
||||
ZVAmlCsMm97jqMRdbFfaoZ/okD1dwOEhnRt8GbvRNE5sARBCTwcjXmnHmpZdaVKC
|
||||
RTL5kUeeUiYfRnvUpcdcxvm9JZ81pNOAV/fXtjb5AoGAUVm4enVSfvPupBsjydU4
|
||||
EHvU0Y0I2IH1FrnVF8TI/9Kpdu2W5bJN5XShb7j2CICIKTr7wVwn/a7VXscQKIVb
|
||||
XCy8+Rnt/jddXFeFEu9zHWyJX9W4fGIkyE4zfRPmTkVK4S599SUQkHdgClzAOMZU
|
||||
IBgv3a3Lyb+IQtT75LE1yjE=
|
||||
-----END PRIVATE KEY-----';
|
||||
|
||||
$rsa = PublicKeyLoader::load($key);
|
||||
$this->assertInstanceOf(PrivateKey::class, $rsa);
|
||||
$this->assertInstanceOf(PublicKey::class, $rsa->getPublicKey());
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user