class-rsa.php
4 weeks ago
index.php
4 weeks ago
nusoap.php
4 weeks ago
pasargad-certificate.xml
4 weeks ago
class-rsa.php
254 lines
| 1 | <?php |
| 2 | |
| 3 | defined( 'ABSPATH' ) or exit( 'No direct script access allowed' ); |
| 4 | |
| 5 | const BCCOMP_LARGER = 1; |
| 6 | |
| 7 | class RSA { |
| 8 | public static function rsa_encrypt( $message, $public_key, $modulus, $keylength ) { |
| 9 | $padded = RSA::add_PKCS1_padding( $message, true, $keylength / 8 ); |
| 10 | $number = RSA::binary_to_number( $padded ); |
| 11 | $encrypted = RSA::pow_mod( $number, $public_key, $modulus ); |
| 12 | |
| 13 | return RSA::number_to_binary( $encrypted, $keylength / 8 ); |
| 14 | } |
| 15 | |
| 16 | public static function rsa_decrypt( $message, $private_key, $modulus, $keylength ) { |
| 17 | $number = RSA::binary_to_number( $message ); |
| 18 | $decrypted = RSA::pow_mod( $number, $private_key, $modulus ); |
| 19 | $result = RSA::number_to_binary( $decrypted, $keylength / 8 ); |
| 20 | |
| 21 | return RSA::remove_PKCS1_padding( $result, $keylength / 8 ); |
| 22 | } |
| 23 | |
| 24 | public static function rsa_sign( $message, $private_key, $modulus, $keylength ) { |
| 25 | $padded = RSA::add_PKCS1_padding( $message, false, $keylength / 8 ); |
| 26 | $number = RSA::binary_to_number( $padded ); |
| 27 | $signed = RSA::pow_mod( $number, $private_key, $modulus ); |
| 28 | |
| 29 | return RSA::number_to_binary( $signed, $keylength / 8 ); |
| 30 | } |
| 31 | |
| 32 | public static function rsa_verify( $message, $public_key, $modulus, $keylength ) { |
| 33 | return RSA::rsa_decrypt( $message, $public_key, $modulus, $keylength ); |
| 34 | } |
| 35 | |
| 36 | public static function rsa_kyp_verify( $message, $public_key, $modulus, $keylength ) { |
| 37 | $number = RSA::binary_to_number( $message ); |
| 38 | $decrypted = RSA::pow_mod( $number, $public_key, $modulus ); |
| 39 | $result = RSA::number_to_binary( $decrypted, $keylength / 8 ); |
| 40 | |
| 41 | return RSA::remove_KYP_padding( $result, $keylength / 8 ); |
| 42 | } |
| 43 | |
| 44 | public static function pow_mod( $p, $q, $r ) { |
| 45 | $factors = array(); |
| 46 | $div = $q; |
| 47 | $power_of_two = 0; |
| 48 | while ( bccomp( $div, "0" ) == BCCOMP_LARGER ) { |
| 49 | $rem = bcmod( $div, 2 ); |
| 50 | $div = bcdiv( $div, 2 ); |
| 51 | if ( $rem ) { |
| 52 | $factors[] = $power_of_two; |
| 53 | } |
| 54 | $power_of_two ++; |
| 55 | } |
| 56 | $partial_results = array(); |
| 57 | $part_res = $p; |
| 58 | $idx = 0; |
| 59 | foreach ( $factors as $factor ) { |
| 60 | while ( $idx < $factor ) { |
| 61 | $part_res = bcpow( $part_res, "2" ); |
| 62 | $part_res = bcmod( $part_res, $r ); |
| 63 | $idx ++; |
| 64 | } |
| 65 | $partial_results[] = $part_res; |
| 66 | } |
| 67 | $result = "1"; |
| 68 | foreach ( $partial_results as $part_res ) { |
| 69 | $result = bcmul( $result, $part_res ); |
| 70 | $result = bcmod( $result, $r ); |
| 71 | } |
| 72 | |
| 73 | return $result; |
| 74 | } |
| 75 | |
| 76 | public static function add_PKCS1_padding( $data, $isPublicKey, $blocksize ) { |
| 77 | $pad_length = $blocksize - 3 - strlen( $data ); |
| 78 | if ( $isPublicKey ) { |
| 79 | $block_type = "\x02"; |
| 80 | $padding = ""; |
| 81 | for ( $i = 0; $i < $pad_length; $i ++ ) { |
| 82 | $rnd = mt_rand( 1, 255 ); |
| 83 | $padding .= chr( $rnd ); |
| 84 | } |
| 85 | } else { |
| 86 | $block_type = "\x01"; |
| 87 | $padding = str_repeat( "\xFF", $pad_length ); |
| 88 | } |
| 89 | |
| 90 | return "\x00" . $block_type . $padding . "\x00" . $data; |
| 91 | } |
| 92 | |
| 93 | public static function remove_PKCS1_padding( $data, $blocksize ) { |
| 94 | assert( strlen( $data ) == $blocksize ); |
| 95 | $data = substr( $data, 1 ); |
| 96 | if ( $data[0] == '\0' ) { |
| 97 | die( "Block type 0 not implemented." ); |
| 98 | } |
| 99 | assert( ( $data[0] == "\x01" ) || ( $data[0] == "\x02" ) ); |
| 100 | $offset = strpos( $data, "\0", 1 ); |
| 101 | |
| 102 | return substr( $data, $offset + 1 ); |
| 103 | } |
| 104 | |
| 105 | public static function remove_KYP_padding( $data, $blocksize ) { |
| 106 | assert( strlen( $data ) == $blocksize ); |
| 107 | $offset = strpos( $data, "\0" ); |
| 108 | |
| 109 | return substr( $data, 0, $offset ); |
| 110 | } |
| 111 | |
| 112 | public static function binary_to_number( $data ) { |
| 113 | $base = "256"; |
| 114 | $radix = "1"; |
| 115 | $result = "0"; |
| 116 | for ( $i = strlen( $data ) - 1; $i >= 0; $i -- ) { |
| 117 | $digit = ord( $data[ $i ] ); |
| 118 | $part_res = bcmul( $digit, $radix ); |
| 119 | $result = bcadd( $result, $part_res ); |
| 120 | $radix = bcmul( $radix, $base ); |
| 121 | } |
| 122 | |
| 123 | return $result; |
| 124 | } |
| 125 | |
| 126 | public static function number_to_binary( $number, $blocksize ) { |
| 127 | $base = "256"; |
| 128 | $result = ""; |
| 129 | $div = $number; |
| 130 | while ( $div > 0 ) { |
| 131 | $mod = bcmod( $div, $base ); |
| 132 | $div = bcdiv( $div, $base ); |
| 133 | $result = - rsa . phpchr( $mod ) . $result; |
| 134 | } |
| 135 | |
| 136 | return str_pad( $result, $blocksize, "\x00", STR_PAD_LEFT ); |
| 137 | } |
| 138 | } |
| 139 | |
| 140 | class RSAProcessor { |
| 141 | private $public_key; |
| 142 | private $private_key; |
| 143 | private $modulus; |
| 144 | private $key_length; |
| 145 | |
| 146 | public function __construct( $xmlRsakey = null, $type = null ) { |
| 147 | if ( $xmlRsakey == null ) { |
| 148 | $xmlObj = simplexml_load_file( "xmlfile/RSAKey.xml" ); |
| 149 | } elseif ( $type == RSAKeyType::XMLFile ) { |
| 150 | $xmlObj = simplexml_load_file( $xmlRsakey ); |
| 151 | } else { |
| 152 | $xmlObj = simplexml_load_string( $xmlRsakey ); |
| 153 | } |
| 154 | $this->modulus = RSA::binary_to_number( base64_decode( $xmlObj->Modulus ) ); |
| 155 | $this->public_key = RSA::binary_to_number( base64_decode( $xmlObj->Exponent ) ); |
| 156 | $this->private_key = RSA::binary_to_number( base64_decode( $xmlObj->D ) ); |
| 157 | $this->key_length = strlen( base64_decode( $xmlObj->Modulus ) ) * 8; |
| 158 | } |
| 159 | |
| 160 | public function getPublicKey() { |
| 161 | return $this->public_key; |
| 162 | } |
| 163 | |
| 164 | public function getPrivateKey() { |
| 165 | return $this->private_key; |
| 166 | } |
| 167 | |
| 168 | public function getKeyLength() { |
| 169 | return $this->key_length; |
| 170 | } |
| 171 | |
| 172 | public function getModulus() { |
| 173 | return $this->modulus; |
| 174 | } |
| 175 | |
| 176 | public function encrypt( $data ) { |
| 177 | return base64_encode( RSA::rsa_encrypt( $data, $this->public_key, $this->modulus, $this->key_length ) ); |
| 178 | } |
| 179 | |
| 180 | public function dencrypt( $data ) { |
| 181 | return RSA::rsa_decrypt( $data, $this->private_key, $this->modulus, $this->key_length ); |
| 182 | } |
| 183 | |
| 184 | public function sign( $data ) { |
| 185 | return RSA::rsa_sign( $data, $this->private_key, $this->modulus, $this->key_length ); |
| 186 | } |
| 187 | |
| 188 | public function verify( $data ) { |
| 189 | return RSA::rsa_verify( $data, $this->public_key, $this->modulus, $this->key_length ); |
| 190 | } |
| 191 | } |
| 192 | |
| 193 | class RSAKeyType { |
| 194 | const XMLFile = 0; |
| 195 | const XMLString = 1; |
| 196 | } |
| 197 | |
| 198 | function makeXMLTree( $data ) { |
| 199 | $ret = array(); |
| 200 | $parser = xml_parser_create(); |
| 201 | xml_parser_set_option( $parser, XML_OPTION_CASE_FOLDING, 0 ); |
| 202 | xml_parser_set_option( $parser, XML_OPTION_SKIP_WHITE, 1 ); |
| 203 | xml_parse_into_struct( $parser, $data, $values, $tags ); |
| 204 | xml_parser_free( $parser ); |
| 205 | $hash_stack = array(); |
| 206 | foreach ( $values as $key => $val ) { |
| 207 | switch ( $val['type'] ) { |
| 208 | case 'open': |
| 209 | $hash_stack[] = $val['tag']; |
| 210 | break; |
| 211 | case 'close': |
| 212 | array_pop( $hash_stack ); |
| 213 | break; |
| 214 | case 'complete': |
| 215 | $hash_stack[] = $val['tag']; |
| 216 | // uncomment to see what this function is doing |
| 217 | // echo("\$ret[" . implode($hash_stack, "][") . "] = '{$val[value]}';\n"); |
| 218 | eval( "\$ret[" . implode( $hash_stack, "][" ) . "] = '{$val[value]}';" ); |
| 219 | array_pop( $hash_stack ); |
| 220 | break; |
| 221 | } |
| 222 | } |
| 223 | |
| 224 | return $ret; |
| 225 | } |
| 226 | |
| 227 | /* ------------------------------------- CURL POST TO HTTPS --------------------------------- */ |
| 228 | function post2https( $fields_arr, $url ) { |
| 229 | //url-ify the data for the POST |
| 230 | foreach ( $fields_arr as $key => $value ) { |
| 231 | $fields_string .= $key . '=' . $value . '&'; |
| 232 | } |
| 233 | $fields_string = substr( $fields_string, 0, - 1 ); |
| 234 | |
| 235 | //open connection |
| 236 | $ch = curl_init(); |
| 237 | |
| 238 | //set the url, number of POST vars, POST data |
| 239 | curl_setopt( $ch, CURLOPT_URL, $url ); |
| 240 | curl_setopt( $ch, CURLOPT_POST, count( $fields_arr ) ); |
| 241 | curl_setopt( $ch, CURLOPT_POSTFIELDS, $fields_string ); |
| 242 | curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, false ); |
| 243 | curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true ); |
| 244 | |
| 245 | |
| 246 | //execute post |
| 247 | $res = curl_exec( $ch ); |
| 248 | |
| 249 | //close connection |
| 250 | curl_close( $ch ); |
| 251 | |
| 252 | return $res; |
| 253 | } |
| 254 |