Subversion Repositories oidplus

Rev

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