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