1<?php 2 3/** 4 * OpenSSL Modular Exponentiation Engine 5 * 6 * PHP version 5 and 7 7 * 8 * @category Math 9 * @package BigInteger 10 * @author Jim Wigginton <terrafrost@php.net> 11 * @copyright 2017 Jim Wigginton 12 * @license http://www.opensource.org/licenses/mit-license.html MIT License 13 * @link http://pear.php.net/package/Math_BigInteger 14 */ 15 16namespace phpseclib3\Math\BigInteger\Engines; 17 18use phpseclib3\Crypt\RSA\Formats\Keys\PKCS8; 19use phpseclib3\Math\BigInteger; 20 21/** 22 * OpenSSL Modular Exponentiation Engine 23 * 24 * @package Engines 25 * @author Jim Wigginton <terrafrost@php.net> 26 * @access public 27 */ 28abstract class OpenSSL 29{ 30 /** 31 * Test for engine validity 32 * 33 * @return bool 34 */ 35 public static function isValidEngine() 36 { 37 return extension_loaded('openssl') && static::class != __CLASS__; 38 } 39 40 /** 41 * Performs modular exponentiation. 42 * 43 * @param Engine $x 44 * @param Engine $e 45 * @param Engine $n 46 * @return Engine 47 */ 48 public static function powModHelper(Engine $x, Engine $e, Engine $n) 49 { 50 if ($n->getLengthInBytes() < 31 || $n->getLengthInBytes() > 16384) { 51 throw new \OutOfRangeException('Only modulo between 31 and 16384 bits are accepted'); 52 } 53 54 $key = PKCS8::savePublicKey( 55 new BigInteger($n), 56 new BigInteger($e) 57 ); 58 59 $plaintext = str_pad($x->toBytes(), $n->getLengthInBytes(), "\0", STR_PAD_LEFT); 60 61 // this is easily prone to failure. if the modulo is a multiple of 2 or 3 or whatever it 62 // won't work and you'll get a "failure: error:0906D06C:PEM routines:PEM_read_bio:no start line" 63 // error. i suppose, for even numbers, we could do what PHP\Montgomery.php does, but then what 64 // about odd numbers divisible by 3, by 5, etc? 65 if (!openssl_public_encrypt($plaintext, $result, $key, OPENSSL_NO_PADDING)) { 66 throw new \UnexpectedValueException(openssl_error_string()); 67 } 68 69 $class = get_class($x); 70 return new $class($result, 256); 71 } 72} 73