[ Index ]

PHP Cross Reference of Joomla 4.2.2 documentation

title

Body

[close]

/libraries/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/Formats/Keys/ -> PKCS1.php (source)

   1  <?php
   2  
   3  /**
   4   * PKCS1 Formatted Key Handler
   5   *
   6   * PHP version 5
   7   *
   8   * @category  Crypt
   9   * @package   Common
  10   * @author    Jim Wigginton <[email protected]>
  11   * @copyright 2015 Jim Wigginton
  12   * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
  13   * @link      http://phpseclib.sourceforge.net
  14   */
  15  
  16  namespace phpseclib3\Crypt\Common\Formats\Keys;
  17  
  18  use ParagonIE\ConstantTime\Base64;
  19  use ParagonIE\ConstantTime\Hex;
  20  use phpseclib3\Common\Functions\Strings;
  21  use phpseclib3\Crypt\AES;
  22  use phpseclib3\Crypt\DES;
  23  use phpseclib3\Crypt\Random;
  24  use phpseclib3\Crypt\TripleDES;
  25  use phpseclib3\Exception\UnsupportedAlgorithmException;
  26  use phpseclib3\File\ASN1;
  27  
  28  /**
  29   * PKCS1 Formatted Key Handler
  30   *
  31   * @package RSA
  32   * @author  Jim Wigginton <[email protected]>
  33   * @access  public
  34   */
  35  abstract class PKCS1 extends PKCS
  36  {
  37      /**
  38       * Default encryption algorithm
  39       *
  40       * @var string
  41       * @access private
  42       */
  43      private static $defaultEncryptionAlgorithm = 'AES-128-CBC';
  44  
  45      /**
  46       * Sets the default encryption algorithm
  47       *
  48       * @access public
  49       * @param string $algo
  50       */
  51      public static function setEncryptionAlgorithm($algo)
  52      {
  53          self::$defaultEncryptionAlgorithm = $algo;
  54      }
  55  
  56      /**
  57       * Returns the mode constant corresponding to the mode string
  58       *
  59       * @access public
  60       * @param string $mode
  61       * @return int
  62       * @throws \UnexpectedValueException if the block cipher mode is unsupported
  63       */
  64      private static function getEncryptionMode($mode)
  65      {
  66          switch ($mode) {
  67              case 'CBC':
  68              case 'ECB':
  69              case 'CFB':
  70              case 'OFB':
  71              case 'CTR':
  72                  return $mode;
  73          }
  74          throw new \UnexpectedValueException('Unsupported block cipher mode of operation');
  75      }
  76  
  77      /**
  78       * Returns a cipher object corresponding to a string
  79       *
  80       * @access public
  81       * @param string $algo
  82       * @return string
  83       * @throws \UnexpectedValueException if the encryption algorithm is unsupported
  84       */
  85      private static function getEncryptionObject($algo)
  86      {
  87          $modes = '(CBC|ECB|CFB|OFB|CTR)';
  88          switch (true) {
  89              case preg_match("#^AES-(128|192|256)-$modes$#", $algo, $matches):
  90                  $cipher = new AES(self::getEncryptionMode($matches[2]));
  91                  $cipher->setKeyLength($matches[1]);
  92                  return $cipher;
  93              case preg_match("#^DES-EDE3-$modes$#", $algo, $matches):
  94                  return new TripleDES(self::getEncryptionMode($matches[1]));
  95              case preg_match("#^DES-$modes$#", $algo, $matches):
  96                  return new DES(self::getEncryptionMode($matches[1]));
  97              default:
  98                  throw new UnsupportedAlgorithmException($algo . ' is not a supported algorithm');
  99          }
 100      }
 101  
 102      /**
 103       * Generate a symmetric key for PKCS#1 keys
 104       *
 105       * @access private
 106       * @param string $password
 107       * @param string $iv
 108       * @param int $length
 109       * @return string
 110       */
 111      private static function generateSymmetricKey($password, $iv, $length)
 112      {
 113          $symkey = '';
 114          $iv = substr($iv, 0, 8);
 115          while (strlen($symkey) < $length) {
 116              $symkey .= md5($symkey . $password . $iv, true);
 117          }
 118          return substr($symkey, 0, $length);
 119      }
 120  
 121      /**
 122       * Break a public or private key down into its constituent components
 123       *
 124       * @access public
 125       * @param string $key
 126       * @param string $password optional
 127       * @return array
 128       */
 129      protected static function load($key, $password)
 130      {
 131          if (!Strings::is_stringable($key)) {
 132              throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key));
 133          }
 134  
 135          /* Although PKCS#1 proposes a format that public and private keys can use, encrypting them is
 136             "outside the scope" of PKCS#1.  PKCS#1 then refers you to PKCS#12 and PKCS#15 if you're wanting to
 137             protect private keys, however, that's not what OpenSSL* does.  OpenSSL protects private keys by adding
 138             two new "fields" to the key - DEK-Info and Proc-Type.  These fields are discussed here:
 139  
 140             http://tools.ietf.org/html/rfc1421#section-4.6.1.1
 141             http://tools.ietf.org/html/rfc1421#section-4.6.1.3
 142  
 143             DES-EDE3-CBC as an algorithm, however, is not discussed anywhere, near as I can tell.
 144             DES-CBC and DES-EDE are discussed in RFC1423, however, DES-EDE3-CBC isn't, nor is its key derivation
 145             function.  As is, the definitive authority on this encoding scheme isn't the IETF but rather OpenSSL's
 146             own implementation.  ie. the implementation *is* the standard and any bugs that may exist in that
 147             implementation are part of the standard, as well.
 148  
 149             * OpenSSL is the de facto standard.  It's utilized by OpenSSH and other projects */
 150          if (preg_match('#DEK-Info: (.+),(.+)#', $key, $matches)) {
 151              $iv = Hex::decode(trim($matches[2]));
 152              // remove the Proc-Type / DEK-Info sections as they're no longer needed
 153              $key = preg_replace('#^(?:Proc-Type|DEK-Info): .*#m', '', $key);
 154              $ciphertext = ASN1::extractBER($key);
 155              if ($ciphertext === false) {
 156                  $ciphertext = $key;
 157              }
 158              $crypto = self::getEncryptionObject($matches[1]);
 159              $crypto->setKey(self::generateSymmetricKey($password, $iv, $crypto->getKeyLength() >> 3));
 160              $crypto->setIV($iv);
 161              $key = $crypto->decrypt($ciphertext);
 162          } else {
 163              if (self::$format != self::MODE_DER) {
 164                  $decoded = ASN1::extractBER($key);
 165                  if ($decoded !== false) {
 166                      $key = $decoded;
 167                  } elseif (self::$format == self::MODE_PEM) {
 168                      throw new \UnexpectedValueException('Expected base64-encoded PEM format but was unable to decode base64 text');
 169                  }
 170              }
 171          }
 172  
 173          return $key;
 174      }
 175  
 176      /**
 177       * Wrap a private key appropriately
 178       *
 179       * @access public
 180       * @param string $key
 181       * @param string $type
 182       * @param string $password
 183       * @param array $options optional
 184       * @return string
 185       */
 186      protected static function wrapPrivateKey($key, $type, $password, array $options = [])
 187      {
 188          if (empty($password) || !is_string($password)) {
 189              return "-----BEGIN $type PRIVATE KEY-----\r\n" .
 190                     chunk_split(Base64::encode($key), 64) .
 191                     "-----END $type PRIVATE KEY-----";
 192          }
 193  
 194          $encryptionAlgorithm = isset($options['encryptionAlgorithm']) ? $options['encryptionAlgorithm'] : self::$defaultEncryptionAlgorithm;
 195  
 196          $cipher = self::getEncryptionObject($encryptionAlgorithm);
 197          $iv = Random::string($cipher->getBlockLength() >> 3);
 198          $cipher->setKey(self::generateSymmetricKey($password, $iv, $cipher->getKeyLength() >> 3));
 199          $cipher->setIV($iv);
 200          $iv = strtoupper(Hex::encode($iv));
 201          return "-----BEGIN $type PRIVATE KEY-----\r\n" .
 202                 "Proc-Type: 4,ENCRYPTED\r\n" .
 203                 "DEK-Info: " . $encryptionAlgorithm . ",$iv\r\n" .
 204                 "\r\n" .
 205                 chunk_split(Base64::encode($cipher->encrypt($key)), 64) .
 206                 "-----END $type PRIVATE KEY-----";
 207      }
 208  
 209      /**
 210       * Wrap a public key appropriately
 211       *
 212       * @access public
 213       * @param string $key
 214       * @param string $type
 215       * @return string
 216       */
 217      protected static function wrapPublicKey($key, $type)
 218      {
 219          return "-----BEGIN $type PUBLIC KEY-----\r\n" .
 220                 chunk_split(Base64::encode($key), 64) .
 221                 "-----END $type PUBLIC KEY-----";
 222      }
 223  }


Generated: Wed Sep 7 05:41:13 2022 Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer