Subversion Repositories oidplus

Rev

Rev 846 | Rev 1042 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. <?php
  2.  
  3. /**
  4.  * Pure-PHP (EC)DH implementation
  5.  *
  6.  * PHP version 5
  7.  *
  8.  * Here's an example of how to compute a shared secret with this library:
  9.  * <code>
  10.  * <?php
  11.  * include 'vendor/autoload.php';
  12.  *
  13.  * $ourPrivate = \phpseclib3\Crypt\DH::createKey();
  14.  * $secret = DH::computeSecret($ourPrivate, $theirPublic);
  15.  *
  16.  * ?>
  17.  * </code>
  18.  *
  19.  * @category  Crypt
  20.  * @package   DH
  21.  * @author    Jim Wigginton <terrafrost@php.net>
  22.  * @copyright 2016 Jim Wigginton
  23.  * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
  24.  * @link      http://phpseclib.sourceforge.net
  25.  */
  26.  
  27. namespace phpseclib3\Crypt;
  28.  
  29. use phpseclib3\Crypt\Common\AsymmetricKey;
  30. use phpseclib3\Crypt\DH\Parameters;
  31. use phpseclib3\Crypt\DH\PrivateKey;
  32. use phpseclib3\Crypt\DH\PublicKey;
  33. use phpseclib3\Exception\NoKeyLoadedException;
  34. use phpseclib3\Exception\UnsupportedOperationException;
  35. use phpseclib3\Math\BigInteger;
  36.  
  37. /**
  38.  * Pure-PHP (EC)DH implementation
  39.  *
  40.  * @package DH
  41.  * @author  Jim Wigginton <terrafrost@php.net>
  42.  * @access  public
  43.  */
  44. abstract class DH extends AsymmetricKey
  45. {
  46.     /**
  47.      * Algorithm Name
  48.      *
  49.      * @var string
  50.      * @access private
  51.      */
  52.     const ALGORITHM = 'DH';
  53.  
  54.     /**
  55.      * DH prime
  56.      *
  57.      * @var \phpseclib3\Math\BigInteger
  58.      * @access private
  59.      */
  60.     protected $prime;
  61.  
  62.     /**
  63.      * DH Base
  64.      *
  65.      * Prime divisor of p-1
  66.      *
  67.      * @var \phpseclib3\Math\BigInteger
  68.      * @access private
  69.      */
  70.     protected $base;
  71.  
  72.     /**
  73.      * Create DH parameters
  74.      *
  75.      * This method is a bit polymorphic. It can take any of the following:
  76.      *  - two BigInteger's (prime and base)
  77.      *  - an integer representing the size of the prime in bits (the base is assumed to be 2)
  78.      *  - a string (eg. diffie-hellman-group14-sha1)
  79.      *
  80.      * @access public
  81.      * @return Parameters
  82.      */
  83.     public static function createParameters(...$args)
  84.     {
  85.         $params = new Parameters();
  86.         if (count($args) == 2 && $args[0] instanceof BigInteger && $args[1] instanceof BigInteger) {
  87.             //if (!$args[0]->isPrime()) {
  88.             //    throw new \InvalidArgumentException('The first parameter should be a prime number');
  89.             //}
  90.             $params->prime = $args[0];
  91.             $params->base = $args[1];
  92.             return $params;
  93.         } elseif (count($args) == 1 && is_numeric($args[0])) {
  94.             $params->prime = BigInteger::randomPrime($args[0]);
  95.             $params->base = new BigInteger(2);
  96.             return $params;
  97.         } elseif (count($args) != 1 || !is_string($args[0])) {
  98.             throw new \InvalidArgumentException('Valid parameters are either: two BigInteger\'s (prime and base), a single integer (the length of the prime; base is assumed to be 2) or a string');
  99.         }
  100.         switch ($args[0]) {
  101.             // see http://tools.ietf.org/html/rfc2409#section-6.2 and
  102.             // http://tools.ietf.org/html/rfc2412, appendex E
  103.             case 'diffie-hellman-group1-sha1':
  104.                 $prime = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74' .
  105.                          '020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437' .
  106.                          '4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED' .
  107.                          'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF';
  108.                 break;
  109.             // see http://tools.ietf.org/html/rfc3526#section-3
  110.             case 'diffie-hellman-group14-sha1': // 2048-bit MODP Group
  111.             case 'diffie-hellman-group14-sha256':
  112.                 $prime = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74' .
  113.                          '020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437' .
  114.                          '4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED' .
  115.                          'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF05' .
  116.                          '98DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB' .
  117.                          '9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B' .
  118.                          'E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718' .
  119.                          '3995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF';
  120.                 break;
  121.             // see https://tools.ietf.org/html/rfc3526#section-4
  122.             case 'diffie-hellman-group15-sha512': // 3072-bit MODP Group
  123.                 $prime = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74' .
  124.                          '020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437' .
  125.                          '4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED' .
  126.                          'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF05' .
  127.                          '98DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB' .
  128.                          '9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B' .
  129.                          'E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718' .
  130.                          '3995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33' .
  131.                          'A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7' .
  132.                          'ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864' .
  133.                          'D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E2' .
  134.                          '08E24FA074E5AB3143DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF';
  135.                 break;
  136.             // see https://tools.ietf.org/html/rfc3526#section-5
  137.             case 'diffie-hellman-group16-sha512': // 4096-bit MODP Group
  138.                 $prime = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74' .
  139.                          '020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437' .
  140.                          '4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED' .
  141.                          'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF05' .
  142.                          '98DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB' .
  143.                          '9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B' .
  144.                          'E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718' .
  145.                          '3995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33' .
  146.                          'A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7' .
  147.                          'ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864' .
  148.                          'D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E2' .
  149.                          '08E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7' .
  150.                          '88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8' .
  151.                          'DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2' .
  152.                          '233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9' .
  153.                          '93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199FFFFFFFFFFFFFFFF';
  154.                 break;
  155.             // see https://tools.ietf.org/html/rfc3526#section-6
  156.             case 'diffie-hellman-group17-sha512': // 6144-bit MODP Group
  157.                 $prime = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74' .
  158.                          '020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437' .
  159.                          '4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED' .
  160.                          'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF05' .
  161.                          '98DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB' .
  162.                          '9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B' .
  163.                          'E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718' .
  164.                          '3995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33' .
  165.                          'A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7' .
  166.                          'ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864' .
  167.                          'D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E2' .
  168.                          '08E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7' .
  169.                          '88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8' .
  170.                          'DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2' .
  171.                          '233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9' .
  172.                          '93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C93402849236C3FAB4D27C7026' .
  173.                          'C1D4DCB2602646DEC9751E763DBA37BDF8FF9406AD9E530EE5DB382F413001AE' .
  174.                          'B06A53ED9027D831179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1B' .
  175.                          'DB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF5983CA01C64B92EC' .
  176.                          'F032EA15D1721D03F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E' .
  177.                          '59E7C97FBEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA' .
  178.                          'CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58BB7C5DA76' .
  179.                          'F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632387FE8D76E3C0468' .
  180.                          '043E8F663F4860EE12BF2D5B0B7474D6E694F91E6DCC4024FFFFFFFFFFFFFFFF';
  181.                 break;
  182.             // see https://tools.ietf.org/html/rfc3526#section-7
  183.             case 'diffie-hellman-group18-sha512': // 8192-bit MODP Group
  184.                 $prime = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74' .
  185.                          '020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437' .
  186.                          '4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED' .
  187.                          'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF05' .
  188.                          '98DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB' .
  189.                          '9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B' .
  190.                          'E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718' .
  191.                          '3995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33' .
  192.                          'A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7' .
  193.                          'ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864' .
  194.                          'D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E2' .
  195.                          '08E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7' .
  196.                          '88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8' .
  197.                          'DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2' .
  198.                          '233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9' .
  199.                          '93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C93402849236C3FAB4D27C7026' .
  200.                          'C1D4DCB2602646DEC9751E763DBA37BDF8FF9406AD9E530EE5DB382F413001AE' .
  201.                          'B06A53ED9027D831179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1B' .
  202.                          'DB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF5983CA01C64B92EC' .
  203.                          'F032EA15D1721D03F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E' .
  204.                          '59E7C97FBEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA' .
  205.                          'CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58BB7C5DA76' .
  206.                          'F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632387FE8D76E3C0468' .
  207.                          '043E8F663F4860EE12BF2D5B0B7474D6E694F91E6DBE115974A3926F12FEE5E4' .
  208.                          '38777CB6A932DF8CD8BEC4D073B931BA3BC832B68D9DD300741FA7BF8AFC47ED' .
  209.                          '2576F6936BA424663AAB639C5AE4F5683423B4742BF1C978238F16CBE39D652D' .
  210.                          'E3FDB8BEFC848AD922222E04A4037C0713EB57A81A23F0C73473FC646CEA306B' .
  211.                          '4BCBC8862F8385DDFA9D4B7FA2C087E879683303ED5BDD3A062B3CF5B3A278A6' .
  212.                          '6D2A13F83F44F82DDF310EE074AB6A364597E899A0255DC164F31CC50846851D' .
  213.                          'F9AB48195DED7EA1B1D510BD7EE74D73FAF36BC31ECFA268359046F4EB879F92' .
  214.                          '4009438B481C6CD7889A002ED5EE382BC9190DA6FC026E479558E4475677E9AA' .
  215.                          '9E3050E2765694DFC81F56E880B96E7160C980DD98EDD3DFFFFFFFFFFFFFFFFF';
  216.                 break;
  217.             default:
  218.                 throw new \InvalidArgumentException('Invalid named prime provided');
  219.         }
  220.  
  221.         $params->prime = new BigInteger($prime, 16);
  222.         $params->base = new BigInteger(2);
  223.  
  224.         return $params;
  225.     }
  226.  
  227.     /**
  228.      * Create public / private key pair.
  229.      *
  230.      * The rationale for the second parameter is described in http://tools.ietf.org/html/rfc4419#section-6.2 :
  231.      *
  232.      * "To increase the speed of the key exchange, both client and server may
  233.      *  reduce the size of their private exponents.  It should be at least
  234.      *  twice as long as the key material that is generated from the shared
  235.      *  secret.  For more details, see the paper by van Oorschot and Wiener
  236.      *  [VAN-OORSCHOT]."
  237.      *
  238.      * $length is in bits
  239.      *
  240.      * @param Parameters $params
  241.      * @param int $length optional
  242.      * @access public
  243.      * @return DH\PrivateKey
  244.      */
  245.     public static function createKey(Parameters $params, $length = 0)
  246.     {
  247.         $one = new BigInteger(1);
  248.         if ($length) {
  249.             $max = $one->bitwise_leftShift($length);
  250.             $max = $max->subtract($one);
  251.         } else {
  252.             $max = $params->prime->subtract($one);
  253.         }
  254.  
  255.         $key = new PrivateKey();
  256.         $key->prime = $params->prime;
  257.         $key->base = $params->base;
  258.         $key->privateKey = BigInteger::randomRange($one, $max);
  259.         $key->publicKey = $key->base->powMod($key->privateKey, $key->prime);
  260.         return $key;
  261.     }
  262.  
  263.     /**
  264.      * Compute Shared Secret
  265.      *
  266.      * @param PrivateKey|EC $private
  267.      * @param PublicKey|BigInteger|string $public
  268.      * @access public
  269.      * @return mixed
  270.      */
  271.     public static function computeSecret($private, $public)
  272.     {
  273.         if ($private instanceof PrivateKey) { // DH\PrivateKey
  274.             switch (true) {
  275.                 case $public instanceof PublicKey:
  276.                     if (!$private->prime->equals($public->prime) || !$private->base->equals($public->base)) {
  277.                         throw new \InvalidArgumentException('The public and private key do not share the same prime and / or base numbers');
  278.                     }
  279.                     return $public->publicKey->powMod($private->privateKey, $private->prime)->toBytes(true);
  280.                 case is_string($public):
  281.                     $public = new BigInteger($public, -256);
  282.                     // fall-through
  283.                 case $public instanceof BigInteger:
  284.                     return $public->powMod($private->privateKey, $private->prime)->toBytes(true);
  285.                 default:
  286.                     throw new \InvalidArgumentException('$public needs to be an instance of DH\PublicKey, a BigInteger or a string');
  287.             }
  288.         }
  289.  
  290.         if ($private instanceof EC\PrivateKey) {
  291.             switch (true) {
  292.                 case $public instanceof EC\PublicKey:
  293.                     $public = $public->getEncodedCoordinates();
  294.                     // fall-through
  295.                 case is_string($public):
  296.                     $point = $private->multiply($public);
  297.                     switch ($private->getCurve()) {
  298.                         case 'Curve25519':
  299.                         case 'Curve448':
  300.                             $secret = $point;
  301.                             break;
  302.                         default:
  303.                             // according to https://www.secg.org/sec1-v2.pdf#page=33 only X is returned
  304.                             $secret = substr($point, 1, (strlen($point) - 1) >> 1);
  305.                     }
  306.                     /*
  307.                     if (($secret[0] & "\x80") === "\x80") {
  308.                         $secret = "\0$secret";
  309.                     }
  310.                     */
  311.                     return $secret;
  312.                 default:
  313.                     throw new \InvalidArgumentException('$public needs to be an instance of EC\PublicKey or a string (an encoded coordinate)');
  314.             }
  315.         }
  316.     }
  317.  
  318.     /**
  319.      * Load the key
  320.      *
  321.      * @param string $key
  322.      * @param string $password optional
  323.      * @return AsymmetricKey
  324.      */
  325.     public static function load($key, $password = false)
  326.     {
  327.         try {
  328.             return EC::load($key, $password);
  329.         } catch (NoKeyLoadedException $e) {
  330.         }
  331.  
  332.         return parent::load($key, $password);
  333.     }
  334.  
  335.     /**
  336.      * OnLoad Handler
  337.      *
  338.      * @return bool
  339.      * @access protected
  340.      * @param array $components
  341.      */
  342.     protected static function onLoad($components)
  343.     {
  344.         if (!isset($components['privateKey']) && !isset($components['publicKey'])) {
  345.             $new = new Parameters();
  346.         } else {
  347.             $new = isset($components['privateKey']) ?
  348.                 new PrivateKey() :
  349.                 new PublicKey();
  350.         }
  351.  
  352.         $new->prime = $components['prime'];
  353.         $new->base = $components['base'];
  354.  
  355.         if (isset($components['privateKey'])) {
  356.             $new->privateKey = $components['privateKey'];
  357.         }
  358.         if (isset($components['publicKey'])) {
  359.             $new->publicKey = $components['publicKey'];
  360.         }
  361.  
  362.         return $new;
  363.     }
  364.  
  365.     /**
  366.      * Determines which hashing function should be used
  367.      *
  368.      * @access public
  369.      * @param string $hash
  370.      */
  371.     public function withHash($hash)
  372.     {
  373.         throw new UnsupportedOperationException('DH does not use a hash algorithm');
  374.     }
  375.  
  376.     /**
  377.      * Returns the hash algorithm currently being used
  378.      *
  379.      * @access public
  380.      */
  381.     public function getHash()
  382.     {
  383.         throw new UnsupportedOperationException('DH does not use a hash algorithm');
  384.     }
  385.  
  386.     /**
  387.      * Returns the parameters
  388.      *
  389.      * A public / private key is only returned if the currently loaded "key" contains an x or y
  390.      * value.
  391.      *
  392.      * @see self::getPublicKey()
  393.      * @access public
  394.      * @return mixed
  395.      */
  396.     public function getParameters()
  397.     {
  398.         $type = self::validatePlugin('Keys', 'PKCS1', 'saveParameters');
  399.  
  400.         $key = $type::saveParameters($this->prime, $this->base);
  401.         return self::load($key, 'PKCS1');
  402.     }
  403. }
  404.