PHP 7 中的 PKCS 1.5 RSA 加密库
Library for PKCS 1.5 RSA Encryption in PHP 7
有人知道在 PHP 7 中使用 public 密钥进行 PKCS 1.5 RSA 加密的方法吗?。我尝试过的每个 PHP 库看起来都用 OAEP 填充替换了加密填充,因为 PKCS 1.5 加密不再安全。 (Phpseclib equivalent to Java RSA Encryption) 。下面给出的是我到目前为止尝试过的 PHP 代码。我在这里做错了什么? PHP有什么办法可以完成这个任务吗?。我正在使用 CodeIgniter 3 PHP 框架。
<?php
defined('BASEPATH') or exit('No direct script access allowed');
use phpseclib3\Crypt\PublicKeyLoader;
use phpseclib3\Crypt\RSA;
class Welcome extends CI_Controller
{
/**
* Index Page for this controller.
*
* Maps to the following URL
* http://example.com/index.php/welcome
* - or -
* http://example.com/index.php/welcome/index
* - or -
* Since this controller is set as the default controller in
* config/routes.php, it's displayed at http://example.com/
*
* So any other public methods not prefixed with an underscore will
* map to /index.php/welcome/<method_name>
* @see https://codeigniter.com/user_guide/general/urls.html
*/
public function index()
{
$key = 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnzIrJng2dW9xPratyAE0nDm5qrnYxyw2lOVVtBgS7C01Aufw/+RDUnneZuHvYB0rU6LExdANvMzDvqNxVQeQNwd5Frrgtx1GV5yZaKuDMqSa6TtFfW/loaKHiLJyIKJTiig4zqjHi0mYI2+Z2Z4wDXx1J8R+Pv+poFShK8vj7Tgx5LwgE/cK7Iq/coTXWEQJrzEbbstBJIq5or5oWBhK0XqB0L3THZZDp3U2b3siIWBniRTU4hquKrwu2/JTmrTYfOAFdR8FRj3oJcFVaexsbhwpiA8RFoY043fhYKBzDz4NK8tFegYn3JIxq+7XReJJQjSKW8/LAxHAypG/aj3C8QIDAQAB';
$publicKey = "-----BEGIN PUBLIC KEY-----\n" . wordwrap($key, 64, "\n", true) . "\n-----END PUBLIC KEY-----";
$timestamp = new DateTime();
$timestamp = $timestamp->getTimestamp();
$tk = <token>;
$text = $timestamp . '+' . $tk;
/** Method 1 - unsuccessfull */
$key = PublicKeyLoader::load($publicKey);
$key = $key->withPadding(RSA::PADDING_PKCS15_COMPAT);
$encryptedString = base64_encode($key->encrypt($text));
/** Method 2 - unsuccessfull */
// $encryptedString = '';
// openssl_public_encrypt(utf8_encode($text),$encryptedString,$publicKey);
// $encryptedString = base64_encode($encryptedString);
/** Method 3 */
// $rsa = new Crypt_RSA();
// $rsa->loadKey($publicKey); // public key
// $rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1);
// $encryptedString = $rsa->encrypt($text);
$encryptedString = utf8_encode($encryptedString);
$encryptedString = urlencode($encryptedString);
echo $encryptedString;
echo '<br/>';
echo '<a href="https://adstream.daraz.lk/api/v1/marketing/download_feeds?token=' . $encryptedString . '">Click</a>';
}
}
?>
这是 daraz 给出的用于在 python 中生成令牌的代码,它有效。
import sys, time
import urllib.parse
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5 as Cipher_PKCS1_v1_5
from base64 import b64decode,b64encode
pubkey = """-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnzIrJng2dW9xPratyAE0nDm5qrnYxyw2lOVVt
BgS7C01Aufw/+RDUnneZuHvYB0rU6LExdANvMzDvqNxVQeQNwd5Frrgtx1GV5yZaKuDMqSa6TtFfW/l
oaKHiLJyIKJTiig4zqjHi0mYI2+Z2Z4wDXx1J8R+Pv+poFShK8vj7Tgx5LwgE/cK7Iq/coTXWEQJrzEbbstBJIq5o
r5oWBhK0XqB0L3THZZDp3U2b3siIWBniRTU4hquKrwu2/JTmrTYfOAFdR8FRj3oJcFVaexsbhwpiA8RFoY
043fhYKBzDz4NK8tFegYn3JIxq+7XReJJQjSKW8/LAxHAypG/aj3C8QIDAQAB
-----END PUBLIC KEY-----"""
timestamp = int(time.time()*1000);
tk = < token >;
msg = str(timestamp) + '+' + tk;
keyPub = RSA.importKey(pubkey);
cipher = Cipher_PKCS1_v1_5.new(keyPub);
cipher_text = cipher.encrypt(msg.encode());
emsg = b64encode(cipher_text);
token = str(emsg,'utf-8');
urlencoded_token = urllib.parse.quote_plus(token);
print(token);
print();
print(urlencoded_token);
我是这样用jsEncrypt Js库做的,也是成功结束
<script>
let timestamp = Date.now();
let accountToken = < token >;
let publicKey = `"""-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnzIrJng2dW9xPratyAE0nDm5qrnYxyw2lOVVt
BgS7C01Aufw/+RDUnneZuHvYB0rU6LExdANvMzDvqNxVQeQNwd5Frrgtx1GV5yZaKuDMqSa6TtFfW/l
oaKHiLJyIKJTiig4zqjHi0mYI2+Z2Z4wDXx1J8R+Pv+poFShK8vj7Tgx5LwgE/cK7Iq/coTXWEQJrzEbbstBJIq5o
r5oWBhK0XqB0L3THZZDp3U2b3siIWBniRTU4hquKrwu2/JTmrTYfOAFdR8FRj3oJcFVaexsbhwpiA8RFoY
043fhYKBzDz4NK8tFegYn3JIxq+7XReJJQjSKW8/LAxHAypG/aj3C8QIDAQAB
-----END PUBLIC KEY-----"""`;
let stringToEncrypt = timestamp + "+" + accountToken;
// let token = RSA_ENCRYPT(stringToEncrypt,
// secret);
// Encrypt with the public key...
let encrypt = new JSEncrypt();
encrypt.setPublicKey(publicKey);
let token = encrypt.encrypt(stringToEncrypt, 'RSAES-PKCS1-V1_5');
token = encodeURIComponent(token);
// console.log('https://adstream.daraz.lk/api/v1/marketing/download_feeds?token=' + token);
window.location.replace('https://adstream.daraz.lk/api/v1/marketing/download_feeds?token=' + token);
</script>
但我仍在寻找在 PHP 中完成相同任务的方法。到目前为止,我在 PHP 中尝试的所有方法都以失败告终,因为 daraz API 说加密令牌无效。有什么帮助吗?
已发布的 Python (PyCryptodome) 和 JavaScript (JSEncrypt) 参考代码执行以下操作:
- 时间戳的生成(自 1970 年 1 月 1 日 00:00:00 UTC 以来经过的毫秒数)。
- 时间戳和标记的串联,格式为
<timestamp>+<token>
。
- 使用 RSA 和 PKCS#1 v1.5 填充进行加密 (RSAES-PKCS1-v1_5)
- Base64编码及后续URL编码
发布的 PHP 代码使用不同的库进行加密:phpseclib(V3 和 V1)和 OpenSSL。与参考代码唯一的区别原来是时间戳是以秒为单位确定的(而不是毫秒),这最终被确定为问题的原因。
其余与参考代码一致,包括用RSA和PKCS#1 v1.5 padding加密,最初怀疑是bug的原因,使用有效密钥对解密即可轻松验证使用第二个独立应用程序(例如 online)使用 PHP 代码生成的密文。
请注意,phpseclib V3 在使用 RSA::ENCRYPTION_PKCS1
加密的上下文中指定 PKCS#1 v1.5 填充。
有人知道在 PHP 7 中使用 public 密钥进行 PKCS 1.5 RSA 加密的方法吗?。我尝试过的每个 PHP 库看起来都用 OAEP 填充替换了加密填充,因为 PKCS 1.5 加密不再安全。 (Phpseclib equivalent to Java RSA Encryption) 。下面给出的是我到目前为止尝试过的 PHP 代码。我在这里做错了什么? PHP有什么办法可以完成这个任务吗?。我正在使用 CodeIgniter 3 PHP 框架。
<?php
defined('BASEPATH') or exit('No direct script access allowed');
use phpseclib3\Crypt\PublicKeyLoader;
use phpseclib3\Crypt\RSA;
class Welcome extends CI_Controller
{
/**
* Index Page for this controller.
*
* Maps to the following URL
* http://example.com/index.php/welcome
* - or -
* http://example.com/index.php/welcome/index
* - or -
* Since this controller is set as the default controller in
* config/routes.php, it's displayed at http://example.com/
*
* So any other public methods not prefixed with an underscore will
* map to /index.php/welcome/<method_name>
* @see https://codeigniter.com/user_guide/general/urls.html
*/
public function index()
{
$key = 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnzIrJng2dW9xPratyAE0nDm5qrnYxyw2lOVVtBgS7C01Aufw/+RDUnneZuHvYB0rU6LExdANvMzDvqNxVQeQNwd5Frrgtx1GV5yZaKuDMqSa6TtFfW/loaKHiLJyIKJTiig4zqjHi0mYI2+Z2Z4wDXx1J8R+Pv+poFShK8vj7Tgx5LwgE/cK7Iq/coTXWEQJrzEbbstBJIq5or5oWBhK0XqB0L3THZZDp3U2b3siIWBniRTU4hquKrwu2/JTmrTYfOAFdR8FRj3oJcFVaexsbhwpiA8RFoY043fhYKBzDz4NK8tFegYn3JIxq+7XReJJQjSKW8/LAxHAypG/aj3C8QIDAQAB';
$publicKey = "-----BEGIN PUBLIC KEY-----\n" . wordwrap($key, 64, "\n", true) . "\n-----END PUBLIC KEY-----";
$timestamp = new DateTime();
$timestamp = $timestamp->getTimestamp();
$tk = <token>;
$text = $timestamp . '+' . $tk;
/** Method 1 - unsuccessfull */
$key = PublicKeyLoader::load($publicKey);
$key = $key->withPadding(RSA::PADDING_PKCS15_COMPAT);
$encryptedString = base64_encode($key->encrypt($text));
/** Method 2 - unsuccessfull */
// $encryptedString = '';
// openssl_public_encrypt(utf8_encode($text),$encryptedString,$publicKey);
// $encryptedString = base64_encode($encryptedString);
/** Method 3 */
// $rsa = new Crypt_RSA();
// $rsa->loadKey($publicKey); // public key
// $rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1);
// $encryptedString = $rsa->encrypt($text);
$encryptedString = utf8_encode($encryptedString);
$encryptedString = urlencode($encryptedString);
echo $encryptedString;
echo '<br/>';
echo '<a href="https://adstream.daraz.lk/api/v1/marketing/download_feeds?token=' . $encryptedString . '">Click</a>';
}
}
?>
这是 daraz 给出的用于在 python 中生成令牌的代码,它有效。
import sys, time
import urllib.parse
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5 as Cipher_PKCS1_v1_5
from base64 import b64decode,b64encode
pubkey = """-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnzIrJng2dW9xPratyAE0nDm5qrnYxyw2lOVVt
BgS7C01Aufw/+RDUnneZuHvYB0rU6LExdANvMzDvqNxVQeQNwd5Frrgtx1GV5yZaKuDMqSa6TtFfW/l
oaKHiLJyIKJTiig4zqjHi0mYI2+Z2Z4wDXx1J8R+Pv+poFShK8vj7Tgx5LwgE/cK7Iq/coTXWEQJrzEbbstBJIq5o
r5oWBhK0XqB0L3THZZDp3U2b3siIWBniRTU4hquKrwu2/JTmrTYfOAFdR8FRj3oJcFVaexsbhwpiA8RFoY
043fhYKBzDz4NK8tFegYn3JIxq+7XReJJQjSKW8/LAxHAypG/aj3C8QIDAQAB
-----END PUBLIC KEY-----"""
timestamp = int(time.time()*1000);
tk = < token >;
msg = str(timestamp) + '+' + tk;
keyPub = RSA.importKey(pubkey);
cipher = Cipher_PKCS1_v1_5.new(keyPub);
cipher_text = cipher.encrypt(msg.encode());
emsg = b64encode(cipher_text);
token = str(emsg,'utf-8');
urlencoded_token = urllib.parse.quote_plus(token);
print(token);
print();
print(urlencoded_token);
我是这样用jsEncrypt Js库做的,也是成功结束
<script>
let timestamp = Date.now();
let accountToken = < token >;
let publicKey = `"""-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnzIrJng2dW9xPratyAE0nDm5qrnYxyw2lOVVt
BgS7C01Aufw/+RDUnneZuHvYB0rU6LExdANvMzDvqNxVQeQNwd5Frrgtx1GV5yZaKuDMqSa6TtFfW/l
oaKHiLJyIKJTiig4zqjHi0mYI2+Z2Z4wDXx1J8R+Pv+poFShK8vj7Tgx5LwgE/cK7Iq/coTXWEQJrzEbbstBJIq5o
r5oWBhK0XqB0L3THZZDp3U2b3siIWBniRTU4hquKrwu2/JTmrTYfOAFdR8FRj3oJcFVaexsbhwpiA8RFoY
043fhYKBzDz4NK8tFegYn3JIxq+7XReJJQjSKW8/LAxHAypG/aj3C8QIDAQAB
-----END PUBLIC KEY-----"""`;
let stringToEncrypt = timestamp + "+" + accountToken;
// let token = RSA_ENCRYPT(stringToEncrypt,
// secret);
// Encrypt with the public key...
let encrypt = new JSEncrypt();
encrypt.setPublicKey(publicKey);
let token = encrypt.encrypt(stringToEncrypt, 'RSAES-PKCS1-V1_5');
token = encodeURIComponent(token);
// console.log('https://adstream.daraz.lk/api/v1/marketing/download_feeds?token=' + token);
window.location.replace('https://adstream.daraz.lk/api/v1/marketing/download_feeds?token=' + token);
</script>
但我仍在寻找在 PHP 中完成相同任务的方法。到目前为止,我在 PHP 中尝试的所有方法都以失败告终,因为 daraz API 说加密令牌无效。有什么帮助吗?
已发布的 Python (PyCryptodome) 和 JavaScript (JSEncrypt) 参考代码执行以下操作:
- 时间戳的生成(自 1970 年 1 月 1 日 00:00:00 UTC 以来经过的毫秒数)。
- 时间戳和标记的串联,格式为
<timestamp>+<token>
。 - 使用 RSA 和 PKCS#1 v1.5 填充进行加密 (RSAES-PKCS1-v1_5)
- Base64编码及后续URL编码
发布的 PHP 代码使用不同的库进行加密:phpseclib(V3 和 V1)和 OpenSSL。与参考代码唯一的区别原来是时间戳是以秒为单位确定的(而不是毫秒),这最终被确定为问题的原因。
其余与参考代码一致,包括用RSA和PKCS#1 v1.5 padding加密,最初怀疑是bug的原因,使用有效密钥对解密即可轻松验证使用第二个独立应用程序(例如 online)使用 PHP 代码生成的密文。
请注意,phpseclib V3 在使用 RSA::ENCRYPTION_PKCS1
加密的上下文中指定 PKCS#1 v1.5 填充。