Библиотека для шифрования PKCS 1.5 RSA в PHP 7 [закрыто]

Кто-нибудь знает библиотеку PHP для шифрования PKCS 1.5 RSA с использованием открытого ключа в PHP 7 ?. Каждая библиотека PHP, которую я пытался использовать, похоже, заменила это заполнение для шифрования заполнением OAEP, потому что шифрование PKCS 1.5 больше не является безопасным. (Phpseclib эквивалентно шифрованию Java RSA ). Ниже приведен код PHP, который я пробовал до сих пор. Что я здесь делаю не так? Есть ли способ выполнить эту задачу в PHP? Я использую PHP-фреймворк CodeIgniter 3.

      <?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 до сих пор, закончились неудачей, потому что API daraz говорит, что зашифрованный токен недействителен. Любая помощь, пожалуйста?

1 ответ

Опубликованные справочные коды Python (PyCryptodome) и JavaScript (JSEncrypt) делают следующее:

  • Генерация метки времени (количество миллисекунд, прошедших с 1 января 1970 г., 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, первоначально предполагавшееся причиной ошибки, что можно легко проверить, используя действительную пару ключей и расшифровав зашифрованный текст, сгенерированный с помощью PHP. код со вторым независимым приложением (например, онлайн).

Обратите внимание, что phpseclib V3 определяет заполнение PKCS#1 v1.5 в контексте шифрования с помощью RSA::ENCRYPTION_PKCS1.

Другие вопросы по тегам