简体   繁体   English

PHP 等同于 Java RSA 解密是什么?

[英]What's the PHP equivalent of Java RSA Decryption?

What I'm trying to do here is implement Samsung Pay on PHP but so far I haven't been able to get the decryption process correctly.我在这里要做的是在 PHP 上实现 Samsung Pay,但到目前为止我还没有能够正确地获得解密过程。

Below is the Java code sample that I'm trying to port in PHP:下面是我试图移植到 PHP 的 Java 代码示例:


import java.io.*;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;
import javax.crypto.*;

public static void main(String[] args) {
    String encPayload = {{encryptedPayload}};
    String privateKeyFilePath = "./rsapriv.pem";
    getDecryptedData(encPayload, privateKeyFilePath);
}

public static String getDecryptedData(String encPayload, String privateKeyFilePath) {
    String delims = "[.]";
    String[] tokens = encPayload.split(delims);
    Decoder urlDecoder = Base64.getUrlDecoder();
    byte[] encKey = urlDecoder.decode(tokens[1]);
    byte[] iv = urlDecoder.decode(tokens[2]);
    byte[] cipherText = urlDecoder.decode(tokens[3]);
    byte[] tag = urlDecoder.decode(tokens[4]);
    byte[] plainText = new byte[cipherText.length];
    try {
// Read private key file
        File privateKeyFile = new File(privateKeyFilePath);
        DataInputStream dis = new DataInputStream(new FileInputStream(privateKeyFile));
        byte[] privKeyBytes = new byte[(int) privateKeyFile.length()];
        dis.read(privKeyBytes);
        dis.close();
// Set private key spec
        PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(privKeyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PrivateKey privKey = keyFactory.generatePrivate(spec);
        Cipher decryptCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        decryptCipher.init(Cipher.DECRYPT_MODE, privKey);
        byte[] plainEncKey = decryptCipher.doFinal(encKey);
        final Cipher aes128Cipher = Cipher.getInstance("AES/GCM/NoPadding");
        final GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(16 * Byte.SIZE, iv);
        final SecretKeySpec keySpec = new SecretKeySpec(plainEncKey, "AES");
        aes128Cipher.init(Cipher.DECRYPT_MODE, keySpec, gcmParameterSpec);
        int offset = aes128Cipher.update(cipherText, 0, cipherText.length, plainText, 0);
        aes128Cipher.update(tag, 0, tag.length, plainText, offset);
        aes128Cipher.doFinal(plainText, offset);
    } catch (Exception e) {
    }
    return new String(plainText);
}

And here's what I have tried so far in PHP:这是我到目前为止在 PHP 中尝试过的内容:

    private function getDecryptedData($encPayload, $privateKeyFilePath) {
        // Split the base64 encoded url
        $tokens = explode('.', $encPayload);

        // Convert to bytes
        $header = base64_decode($tokens[0]);
        $encKey = base64_decode($tokens[1]);
        $iv = base64_decode($tokens[2]);
        $cipherText = base64_decode($tokens[3]);
        $tag = base64_decode($tokens[4]);
        $plainText = "";

        try {
            $private = RSA::loadPrivateKeyFormat('PKCS8', $privateKeyFilePath)->withPadding(RSA::ENCRYPTION_PKCS1);
            dd($private->decrypt($encKey));

           // then some AES-128 GCM Stuff.

        } catch (\Exception $ex) {
            dd($ex->getMessage());
        }
    }

I'm supposed to get a plaintext but instead I'm getting a Decryption error message, which is making me think if whether I'm doing it the right way or not.我应该得到一个明文,但我却收到一条Decryption error消息,这让我思考我是否以正确的方式进行操作。

UPDATE: The previous syntax used was phpseclib v2.0 but now I've changed the syntax to phpseclib v3.0更新:以前使用的语法是 phpseclib v2.0 但现在我已经将语法更改为 phpseclib v3.0

From your PHP code:来自您的 PHP 代码:

$private = RSA::loadPrivateKeyFormat('PKCS8', $privateKeyFilePath)
    ->withPadding(RSA::ENCRYPTION_PKCS1);

It doesn't read the key from the filesystem - it reads the key as a string.它不从文件系统中读取密钥——它将密钥作为字符串读取。 So you prob need to do this:所以你可能需要这样做:

$private = RSA::loadPrivateKeyFormat('PKCS8', file_get_contents($privateKeyFilePath))
    ->withPadding(RSA::ENCRYPTION_PKCS1);

Also, for good measure, I'd just do this, instead:另外,为了更好的衡量,我只是这样做,而不是:

$private = PublicKeyLoader::load(file_get_contents($privateKeyFilePath))
    ->withPadding(RSA::ENCRYPTION_PKCS1);

phpseclib will auto detect the key format so might as well take advantage of that. phpseclib 将自动检测密钥格式,所以不妨利用它。

For more info see https://phpseclib.com/docs/java有关详细信息,请参阅https://phpseclib.com/docs/java

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM