Skip to content

Commit 77d28c2

Browse files
committed
fixed pasargas RSA class bugs
1 parent fff5eb3 commit 77d28c2

File tree

3 files changed

+163
-159
lines changed

3 files changed

+163
-159
lines changed

composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,10 @@
1515
}
1616
],
1717
"require": {
18-
"php": ">=7.0.0",
18+
"php": ">=7.2",
1919
"ext-soap" : "*",
2020
"ext-json": "*",
21+
"ext-bcmath": "*",
2122
"illuminate/contracts": "~5.6.0|^6.0|^7.0|^8.0",
2223
"illuminate/database": "~5.6.0|^6.0|^7.0|^8.0",
2324
"illuminate/http": "~5.6.0|^6.0|^7.0|^8.0",

src/Adapter/Pasargad/RSA.php

Lines changed: 145 additions & 141 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
<?php
2+
23
namespace Tartan\Larapay\Adapter\Pasargad;
4+
35
define("BCCOMP_LARGER", 1);
46

57
/**
@@ -8,145 +10,147 @@
810
*/
911
class RSA
1012
{
11-
public static function rsa_encrypt ($message, $public_key, $modulus, $keylength)
12-
{
13-
$padded = RSA::add_PKCS1_padding($message, true, $keylength / 8);
14-
$number = RSA::binary_to_number($padded);
15-
$encrypted = RSA::pow_mod($number, $public_key, $modulus);
16-
$result = RSA::number_to_binary($encrypted, $keylength / 8);
17-
18-
return $result;
19-
}
20-
21-
public static function rsa_decrypt ($message, $private_key, $modulus, $keylength)
22-
{
23-
$number = RSA::binary_to_number($message);
24-
$decrypted = RSA::pow_mod($number, $private_key, $modulus);
25-
$result = RSA::number_to_binary($decrypted, $keylength / 8);
26-
27-
return RSA::remove_PKCS1_padding($result, $keylength / 8);
28-
}
29-
30-
public static function rsa_sign ($message, $private_key, $modulus, $keylength)
31-
{
32-
$padded = RSA::add_PKCS1_padding($message, false, $keylength / 8);
33-
$number = RSA::binary_to_number($padded);
34-
$signed = RSA::pow_mod($number, $private_key, $modulus);
35-
$result = RSA::number_to_binary($signed, $keylength / 8);
36-
37-
return $result;
38-
}
39-
40-
public static function rsa_verify ($message, $public_key, $modulus, $keylength)
41-
{
42-
return RSA::rsa_decrypt($message, $public_key, $modulus, $keylength);
43-
}
44-
45-
public static function rsa_kyp_verify ($message, $public_key, $modulus, $keylength)
46-
{
47-
$number = RSA::binary_to_number($message);
48-
$decrypted = RSA::pow_mod($number, $public_key, $modulus);
49-
$result = RSA::number_to_binary($decrypted, $keylength / 8);
50-
51-
return RSA::remove_KYP_padding($result, $keylength / 8);
52-
}
53-
54-
public static function pow_mod ($p, $q, $r)
55-
{
56-
$factors = array();
57-
$div = $q;
58-
$power_of_two = 0;
59-
while (bccomp($div, "0") == BCCOMP_LARGER) {
60-
$rem = bcmod($div, 2);
61-
$div = bcdiv($div, 2);
62-
if ($rem) array_push($factors, $power_of_two);
63-
$power_of_two++;
64-
}
65-
$partial_results = array();
66-
$part_res = $p;
67-
$idx = 0;
68-
foreach ($factors as $factor) {
69-
while ($idx < $factor) {
70-
$part_res = bcpow($part_res, "2");
71-
$part_res = bcmod($part_res, $r);
72-
$idx++;
73-
}
74-
array_push($partial_results, $part_res);
75-
}
76-
$result = "1";
77-
foreach ($partial_results as $part_res) {
78-
$result = bcmul($result, $part_res);
79-
$result = bcmod($result, $r);
80-
}
81-
82-
return $result;
83-
}
84-
85-
public static function add_PKCS1_padding ($data, $isPublicKey, $blocksize)
86-
{
87-
$pad_length = $blocksize - 3 - strlen($data);
88-
if ($isPublicKey) {
89-
$block_type = "\x02";
90-
$padding = "";
91-
for ($i = 0; $i < $pad_length; $i++) {
92-
$rnd = mt_rand(1, 255);
93-
$padding .= chr($rnd);
94-
}
95-
}
96-
else {
97-
$block_type = "\x01";
98-
$padding = str_repeat("\xFF", $pad_length);
99-
}
100-
101-
return "\x00" . $block_type . $padding . "\x00" . $data;
102-
}
103-
104-
public static function remove_PKCS1_padding ($data, $blocksize)
105-
{
106-
assert(strlen($data) == $blocksize);
107-
$data = substr($data, 1);
108-
if ($data{0} == '\0')
109-
die("Block type 0 not implemented.");
110-
assert(($data{0} == "\x01") || ($data{0} == "\x02"));
111-
$offset = strpos($data, "\0", 1);
112-
113-
return substr($data, $offset + 1);
114-
}
115-
116-
public static function remove_KYP_padding ($data, $blocksize)
117-
{
118-
assert(strlen($data) == $blocksize);
119-
$offset = strpos($data, "\0");
120-
121-
return substr($data, 0, $offset);
122-
}
123-
124-
public static function binary_to_number ($data)
125-
{
126-
$base = "256";
127-
$radix = "1";
128-
$result = "0";
129-
for ($i = strlen($data) - 1; $i >= 0; $i--) {
130-
$digit = ord($data{$i});
131-
$part_res = bcmul($digit, $radix);
132-
$result = bcadd($result, $part_res);
133-
$radix = bcmul($radix, $base);
134-
}
135-
136-
return $result;
137-
}
138-
139-
public static function number_to_binary ($number, $blocksize)
140-
{
141-
$base = "256";
142-
$result = "";
143-
$div = $number;
144-
while ($div > 0) {
145-
$mod = bcmod($div, $base);
146-
$div = bcdiv($div, $base);
147-
$result = chr($mod) . $result;
148-
}
149-
150-
return str_pad($result, $blocksize, "\x00", STR_PAD_LEFT);
151-
}
13+
public static function rsa_encrypt($message, $public_key, $modulus, $keylength)
14+
{
15+
$padded = RSA::add_PKCS1_padding($message, true, $keylength / 8);
16+
$number = RSA::binary_to_number($padded);
17+
$encrypted = RSA::pow_mod($number, $public_key, $modulus);
18+
$result = RSA::number_to_binary($encrypted, $keylength / 8);
19+
20+
return $result;
21+
}
22+
23+
public static function rsa_decrypt($message, $private_key, $modulus, $keylength)
24+
{
25+
$number = RSA::binary_to_number($message);
26+
$decrypted = RSA::pow_mod($number, $private_key, $modulus);
27+
$result = RSA::number_to_binary($decrypted, $keylength / 8);
28+
29+
return RSA::remove_PKCS1_padding($result, $keylength / 8);
30+
}
31+
32+
public static function rsa_sign($message, $private_key, $modulus, $keylength)
33+
{
34+
$padded = RSA::add_PKCS1_padding($message, false, $keylength / 8);
35+
$number = RSA::binary_to_number($padded);
36+
$signed = RSA::pow_mod($number, $private_key, $modulus);
37+
38+
return RSA::number_to_binary($signed, $keylength / 8);
39+
}
40+
41+
public static function rsa_verify($message, $public_key, $modulus, $keylength)
42+
{
43+
return RSA::rsa_decrypt($message, $public_key, $modulus, $keylength);
44+
}
45+
46+
public static function rsa_kyp_verify($message, $public_key, $modulus, $keylength)
47+
{
48+
$number = RSA::binary_to_number($message);
49+
$decrypted = RSA::pow_mod($number, $public_key, $modulus);
50+
$result = RSA::number_to_binary($decrypted, $keylength / 8);
51+
52+
return RSA::remove_KYP_padding($result, $keylength / 8);
53+
}
54+
55+
public static function pow_mod($p, $q, $r)
56+
{
57+
$factors = [];
58+
$div = $q;
59+
$power_of_two = 0;
60+
61+
while (bccomp($div, "0") === BCCOMP_LARGER) {
62+
$rem = bcmod($div, 2);
63+
$div = bcdiv($div, 2);
64+
if ($rem) {
65+
$factors[] = $power_of_two;
66+
}
67+
$power_of_two++;
68+
}
69+
$partial_results = [];
70+
$part_res = $p;
71+
$idx = 0;
72+
foreach ($factors as $factor) {
73+
while ($idx < $factor) {
74+
$part_res = bcpow($part_res, "2");
75+
$part_res = bcmod($part_res, $r);
76+
$idx++;
77+
}
78+
$partial_results [] = $part_res;
79+
}
80+
$result = "1";
81+
foreach ($partial_results as $part_res) {
82+
$result = bcmul($result, $part_res);
83+
$result = bcmod($result, $r);
84+
}
85+
86+
return $result;
87+
}
88+
89+
public static function add_PKCS1_padding($data, $isPublicKey, $blocksize)
90+
{
91+
$pad_length = $blocksize - 3 - strlen($data);
92+
if ($isPublicKey) {
93+
$block_type = "\x02";
94+
$padding = "";
95+
for ($i = 0; $i < $pad_length; $i++) {
96+
$rnd = random_int(1, 255);
97+
$padding .= chr($rnd);
98+
}
99+
} else {
100+
$block_type = "\x01";
101+
$padding = str_repeat("\xFF", $pad_length);
102+
}
103+
104+
return "\x00" . $block_type . $padding . "\x00" . $data;
105+
}
106+
107+
public static function remove_PKCS1_padding($data, $blocksize)
108+
{
109+
assert(strlen($data) == $blocksize);
110+
$data = substr($data, 1);
111+
if ($data{0} === '\0') {
112+
die("Block type 0 not implemented.");
113+
}
114+
assert(($data{0} === "\x01") || ($data{0} === "\x02"));
115+
$offset = strpos($data, "\0", 1);
116+
117+
return substr($data, $offset + 1);
118+
}
119+
120+
public static function remove_KYP_padding($data, $blocksize)
121+
{
122+
assert(strlen($data) == $blocksize);
123+
$offset = strpos($data, "\0");
124+
125+
return substr($data, 0, $offset);
126+
}
127+
128+
public static function binary_to_number($data)
129+
{
130+
$base = "256";
131+
$radix = "1";
132+
$result = "0";
133+
for ($i = strlen($data) - 1; $i >= 0; $i--) {
134+
$digit = ord($data{$i});
135+
$part_res = bcmul($digit, $radix);
136+
$result = bcadd($result, $part_res);
137+
$radix = bcmul($radix, $base);
138+
}
139+
140+
return $result;
141+
}
142+
143+
public static function number_to_binary($number, $blocksize)
144+
{
145+
$base = "256";
146+
$result = "";
147+
$div = $number;
148+
while ($div > 0) {
149+
$mod = bcmod($div, $base);
150+
$div = bcdiv($div, $base);
151+
$result = chr($mod) . $result;
152+
}
153+
154+
return str_pad($result, $blocksize, "\x00", STR_PAD_LEFT);
155+
}
152156
}

src/Adapter/Pasargad/RSAProcessor.php

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
<?php
22
namespace Tartan\Larapay\Adapter\Pasargad;
33

4+
class RSAKeyType
5+
{
6+
const XMLFile = 0;
7+
const XMLString = 1;
8+
}
9+
410
/**
511
* Class RSAProcessor
612
* @package Tartan\Larapay\Adapter\Pasargad
@@ -18,18 +24,17 @@ class RSAProcessor
1824
* @param null $xmlRsaKey
1925
* @param null $type
2026
*/
21-
public function __construct ($xmlRsaKey = null, $type = null)
27+
public function __construct ($xmlRsaKey = null, $keyType = null)
2228
{
2329
$xmlObj = null;
24-
if ($xmlRsaKey == null) {
25-
$xmlObj = simplexml_load_file("xmlfile/RSAKey.xml");
26-
}
27-
elseif ($type == RSAKeyType::XMLFile) {
28-
$xmlObj = simplexml_load_file($xmlRsaKey);
29-
}
30-
else {
31-
$xmlObj = simplexml_load_string($xmlRsaKey);
32-
}
30+
$keyType = is_null($keyType) ? null : strtolower($keyType);
31+
32+
if ($keyType === null || $keyType == RSAKeyType::XMLString) {
33+
$xmlObj = simplexml_load_string($xmlRsaKey);
34+
} elseif ($keyType == RSAKeyType::XMLFile) {
35+
$xmlObj = simplexml_load_string(file_get_contents($xmlRsaKey));
36+
}
37+
3338
$this->modulus = RSA::binary_to_number(base64_decode($xmlObj->Modulus));
3439
$this->public_key = RSA::binary_to_number(base64_decode($xmlObj->Exponent));
3540
$this->private_key = RSA::binary_to_number(base64_decode($xmlObj->D));
@@ -61,7 +66,7 @@ public function encrypt ($data)
6166
return base64_encode(RSA::rsa_encrypt($data, $this->public_key, $this->modulus, $this->key_length));
6267
}
6368

64-
public function dencrypt ($data)
69+
public function decrypt ($data)
6570
{
6671
return RSA::rsa_decrypt($data, $this->private_key, $this->modulus, $this->key_length);
6772
}
@@ -76,9 +81,3 @@ public function verify ($data)
7681
return RSA::rsa_verify($data, $this->public_key, $this->modulus, $this->key_length);
7782
}
7883
}
79-
80-
class RSAKeyType
81-
{
82-
const XMLFile = 0;
83-
const XMLString = 1;
84-
}

0 commit comments

Comments
 (0)