php如何用RSA私钥加密数据?

How to encrypted data with RSA private key in php?

目前正在使用 php.So 开发基于财务的应用程序,我与第三方 api 集成以获取用户数据。

基于集成,他们正在使用签名和有效负载进行身份验证。

根据文件,我按照我的观点做了一切正确的事情,但我得到的回应是

SignatureDoesNotMatch The request signature we calculated does not match the signature you provided.

根据文件:

正在计算签名: 必要时,请求必须由发件人签名。请求的签名计算如下:

  1. 将负载 XML 压缩成一行,如下所示: 2.Remove XML 声明 3.Remove 所有评论 4.Remove 所有换行符 5.Normalise 个空格

6) 生成压缩负载的 SHA1 摘要。 7)Base16编码生成的SHA1摘要。 8) 使用 Perfios 提供的 RSA 私钥加密编码摘要。 9)Base16编码加密后的摘要。

这是我的脚本:

$condense_payload ='<payload><vendorId>test</vendorId><txnId>dummyApplicationId</txnId><emailId>'.$emailid.'</emailId><destination>netbankingFetch</destination><returnUrl>https://www.google.com</returnUrl></payload>';


$condense_payload_updated = trim(preg_replace('/(?<=\>)(\r?\n)|(\r?\n)(?=\<\/)/', $condense_payload));


$payload ='
<payload>
<vendorId>test</vendorId>
<txnId>dummyApplicationId</txnId>
<emailId>'.$emailid.'</emailId>
<destination>netbankingFetch</destination>
<returnUrl>https://www.google.com</returnUrl>
</payload>';

/* Convert to Sha1 */
$sha1_convert = sha1($condense_payload_updated);

/* Convert to Hex (base16) */
$first_base16_convert=bin2hex($sha1_convert);


$fp =  fopen("private_key", "r");

$private_key_string = fread($fp, 8192);

fclose($fp);

/* Convert to private key */
$private_key = openssl_get_privatekey($private_key_string);

$encrypted_private="";



/* Encrypt digest using key */

openssl_private_encrypt($first_base16_convert, $encrypted_private, $private_key, OPENSSL_PKCS1_PADDING);
/* Convert to Hex (base16) */
$signature=bin2hex($encrypted_private);

所以这里生成有效负载和签名并使用 post 方法发送 url:

<html>
    <body onload='document.autoform.submit();'>
        <form name='autoform' method='post' action='https://demo.perfios.com/KuberaVault/insights/start'>
            <input type='hidden' name='payload' value='<?php echo $payload; ?>' />
            <input type='hidden' name='signature' value='<?php echo $signature; ?>'/>
    </body>
</html>

最后我得到了:

SignatureDoesNotMatch The request signature we calculated does not match the signature you provided.

Api 支持团队提供了 java 示例代码,我遵守了 运行 java,它正在工作。

此处java代码:

   package javaapplication1;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringReader;
import java.security.Key;
import java.security.KeyPair;
import java.security.MessageDigest;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Security;

import javax.crypto.Cipher;

import org.bouncycastle.openssl.PEMReader;
import org.bouncycastle.util.encoders.Hex;

public class JavaApplication1 {
    static String email = "test@hello.com";
    static String server = "demo.test.com";
    public static String vendor = "test";
    public static String returnURL = "https://www.google.com";


    static String privateKey = "-----BEGIN RSA PRIVATE KEY-----\n" + 
            "MIIEpQIBAAKCAQEAx76oeNWYPkAbbSPyvJdfgfdgcPkQvAMvIHCPgY9yNdN/qsYMHytyit\n" + 
            "xdO0aTatgfS/ig4zmqKFVpC9o2YMyQ7E1FYNcl/ev++r4nV+qVXA1OKcsSv4Kbj/\n" + 
            fgdfg"iNwxGmnhBsRDswY/dEZZDN9RisRpo9NRSOskGRv+nLEA2dLgj0/f9SSzykz3cxAP\n" + 
            "bq6bV0unie5C8r6RALj+hTLU7B7QF88SkDsFx0/TYQe4H9QJtFMWJtOnhumY5Ku6\n" + 
            "CL4OdZrtz71y4ji8IxQxv2nyqdfgfd0JwYQ4rG84uzJQeRQf2RaJLhnSdfQnonDkP7L1z\n" + 
            "NSizzi8VgHI+GVIo9FrLj7DVo+fFzMucbsvvNQIDAQABAoIBAQCMVKOR+SYzneBm\n" + 
            "5hmUa2CxW5sVb7qHj54iiwLj4EYY2EnIaljjol+eh56Qrb2fpWiV3FZnQdspn/md\n" + 
            "i7W3JBngYABjwmN0/20UVL3cErVZN/XqgiFtKp2gfhfgI3BgPI/YYIWyVKRNJGt/z6Rf6\n" + 
            "0+zImQLMbUGNHkHlxuSjas+CL93sYrXo52TXqZgkfghgf40gEkQVLE+SLrtXTFiOOlX/s\n" + 
            "WWXyeUY14hl+oVQLmEO6UZd532bxAE0VlIV6Vr2pE3gJqEyaAoGgkT3inxvRPiek\n" + 
            "swRm9OONWZD9frKXYqabJTsd87623Czg5h2WGimsN4fZ+LfyBXul24KKVeMDELHn\n" + 
            "GvdRm95lAoGBAPMQRrb3iB8oYJc+4KwbtWR/vTQW++G69CeyIfD7WM0Ix3Gy0wod\n" + 
            "FwIeKSkYsZ/R5n+9Ucx/RVFv7X86YzYajhH3hl+8/q4c+L1yAGS5hW3m21gIViDt\n" + 
            "k1h3gKLI5o4EKGhCRX1teSoZ+n4G7KlYbJas8h5MX3u81GhKRmiVItr/AoGBANJg\n" + 
            "KoIhxKsyNRccULosYZBGc3vpkFtpHeZ5w0qxbXaGveUIKvqzUqonGy0o3yqVNRrH\n" + 
            "JJREHss+5/HqeuauawKUYLWapCqmVF6IlDc1PxTw+BLDzgzMlX2o43951iTMJXkd\n" + 
            "80MOujsnyTdZq7wAzR7KNR3U/OjDFlcORxhCGrnLAoGBAONZcgtp9NTP+6j8k0Ho\n" + 
            "mP5rzRmP9gHp0L3gjIbPUvxVHdhnn6ZyFzdP5sgd5ObMeoE5H+3bjYbi3o6Gmo3c\n" + 
            "wM5lbDbYnI9XYgIxQ9TzAq8NpFTvV0Btd8jj3lpk9+IWWYVLl5v+bbrHmdmPuIWd\n" + 
            "w9Qb6EwWu6kNss/pyXnBJV0ZAoGAPj+2VEsppn50tyHpwSzgsZAnG8NAs8umzUu6\n" + 
            "PZ/ChA/aoKqKDSSCkVaA9Bvj7PW5gPLsH/MIKZuzhiGbvCZgA6Nj+liHuxb8X/yJ\n" + 
            "3swink+vF95YWfEvSr9ukYm7k6fUbsIt+OmisV5Ua8xcxIR4LWQn02vyae1P7vKK\n" + 
            "luL4hYECgYEAmSiiHa4bSLF8MT/IbL2YIrxK4yatABvVWZLkAV7hiFJWeEhLCmCd\n" + 
            "OKcX8QSq9lT6TbS6NCEfHfCR0FFrny4nZMT3YnyDkgrYOiHhZL/YVfr3Izr62Gcy\n" + 
            "PizNJH/JWoNDonAuFi+eQjgBRNfd894pMeCT4tMu2nE1SOEafzykzPA=\n" + 
            "-----END RSA PRIVATE KEY-----";

    static final String DIGEST_ALGO = "SHA-1";
    static final String ENCRYPTION_ALGO = "RSA/ECB/PKCS1Padding";
    static String applicationId = "dummyApplicationId";
    static String perfiosTransactionId = "PLEASE UPDATE ME";
    static String format = "xml";

public static String payloadStatement = "<payload>\n"
            + "<vendorId>"
            + vendor
            + "</vendorId>\n"
            + "<txnId>"
            + applicationId
            + "</txnId>\n"
            + "<yearMonthFrom>2015-06</yearMonthFrom>\n" + 
            "<yearMonthTo>2016-02</yearMonthTo>"
            + "<emailId>#email#</emailId>\n<destination>statement</destination>\n"
            + "<returnUrl>" + returnURL + "</returnUrl>\n" + "</payload>";









    public static void main(String[] args) throws Exception {
        Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
        if (args.length > 1 && args[0] != null) {
            if ("encrypt".equals(args[0])) {
                if (args[1] != null) {
                    String encrypt = encrypt(args[1], ENCRYPTION_ALGO,
                            buildPublicKey(privateKey));
                    System.out.print(encrypt);
                } else {
                    throw new Exception("Wrong number of arguments provided.");
                }
            } else if ("signature".equals(args[0])) {
                if (args[1] != null) {
                    String signature = getSignature(ENCRYPTION_ALGO,
                            DIGEST_ALGO, buildPrivateKey(privateKey), args[1]);
                    System.out.print(signature);
                } else {
                    throw new Exception("Wrong number of arguments provided.");
                }
            }
        } else {
            String argPerfiosTxnId = System.getProperty("perfiosTransactionId");
            if (argPerfiosTxnId != null)
                perfiosTransactionId = argPerfiosTxnId;

            String argTxnId = System.getProperty("applicationId");
            if (argTxnId != null)
                applicationId = argTxnId;

            System.out
                    .println("This program helps you try out Perfios APIs to initiate and track Perfios online transactions. "
                            + "\nIt generates HTML files that can be opened in a browser to initiate or track the transaction.");

            /** Create a folder for customer */
            File folder = new File(vendor);
            String message = "\n\nnetbanking and statement APIs are the APIs to start the transaction. \n"
                    + "Only integration supported to start the transaction is through autopost form as in the netbanking and statement htmls.\n"
                    + "All other APIs are xml over HTTP and do not need browser to be present.\n"
                    + "You can directly invoke those APIs using other mechanisms.\n\n"
                    + "Trying this program:\n"
                    + "\t(1)First run the program and it will generate the netbanking and statement upload files.\n"
                    + "\t(2)Depending upon whether you have requested these features to be available, you should be able to start the transactions.\n"
                    + "\t(3)netbanking and statment HTML start the perfios transaction using browser to browser integration.\n"
                    + "\t\t(3.1)To start netbanking transaction, open netbanking_* file in your browser..\n"
                    + "\t\t(3.2)To start statement upload transaction, open statement_* file in your browser..\n"
                    + "\t(4)You can then check the status of all transactions using txnstatus API.\n"
                    + "\t\t(4.1)To check the status of transaction, open txnstatus_* file in your browser. \n"
                    + "\t\t\tThis API could also be accessed without a browser. Without autoform load request\n"
                    + "\t(5)To retrieve a report, you will need to re-run the program. Change the value of perfiosTransactionId variable in your program.\n"
                    + "\t\t Compile and run the java program. open retrieve_* file in your browser. This API could also be accessed without a browser.\n"
                    + "\t\t Without autoform load request\n"
                    + "\t(5)To delete the transaction related artifacts, you will need to re-run the program. \n"
                    + "\t\tChange the value of perfiosTransactionId variable in your program. Compile and run the java program. open delete_* \n"
                    + "\t\tfile in your browser. This API could also be accessed without a browser. Without autoform load request\n"
                    + "You can pass applicationId and perfiosTransactionId through command line by providing system properties too. "
                    + "For e.g. java -DperfiosTransactionId=HDJDJ com.perfios.sample.OnlineSampleCapitalInfusionIndia\n"
                    + "\t(6)For more details please refer the API guide.\n";

            System.out.println(message);

            if (!folder.exists())
                folder.mkdir();

            System.out
                    .println("Your files will be created in the following location: "
                            + folder.getAbsolutePath());

            /** Create files for the customer */
            String  myHTML = genericCreateHTML(JavaApplication1.payloadStatement);
            createFile("statement", myHTML);








        }
    }

    private static void createFile(String classification, String myHTML) {
        String filename = vendor + "/" + classification + "_" + server
                + ".html";

        try {
            PrintWriter out = new PrintWriter(filename);
            out.print(myHTML);
            out.close();
            System.out.println("Successfully created file " + filename);
        } catch (Exception e) {
            System.out.println("Error while creating file " + filename);
            e.printStackTrace();
        }
    }

    private static String genericCreateHTML(String payload) {
        return genericCreateHTML(payload, null);
    }

    private static String genericCreateHTML(String payload, String operation) {

        String emailEncrypted = encrypt(email, ENCRYPTION_ALGO,
                buildPublicKey(privateKey));
        payload = payload.replaceAll("\n", "");
        payload = payload.replaceAll("#email#", emailEncrypted);

        String signature = getSignature(ENCRYPTION_ALGO, DIGEST_ALGO,
                buildPrivateKey(privateKey), payload);
        if (operation == null)
            operation = "start";
        String myHTML = "<html>\n"
                + " <body onload='document.autoform.submit();'>\n"
                + "     <form name='autoform' method='post' action='https://"
                + server + "/KuberaVault/insights/" + operation + "'>\n"
                + "         <input type='hidden' name='payload' value='" + payload
                + "'>\n" + "            <input type='hidden' name='signature' value='"
                + signature + "'>\n" + "        </form>\n" + "  </body>\n"
                + "</html>\n";
        return myHTML;
    }

    public static String getSignature(String encryptAlgo, String digestAlgo,
            Key k, String xml) {
        String dig = makeDigest(xml, digestAlgo);
        return encrypt(dig, encryptAlgo, k);
    }

    private static PrivateKey buildPrivateKey(String privateKeySerialized) {
        StringReader reader = new StringReader(privateKeySerialized);
        PrivateKey pKey = null;
        try {
            PEMReader pemReader = new PEMReader(reader);
            KeyPair keyPair = (KeyPair) pemReader.readObject();
            pKey = keyPair.getPrivate();
            pemReader.close();
        } catch (IOException i) {
            i.printStackTrace();
        }
        return pKey;
    }

    private static PublicKey buildPublicKey(String privateKeySerialized) {
        StringReader reader = new StringReader(privateKeySerialized);
        PublicKey pKey = null;
        try {
            PEMReader pemReader = new PEMReader(reader);
            KeyPair keyPair = (KeyPair) pemReader.readObject();
            pKey = keyPair.getPublic();
            pemReader.close();
        } catch (IOException i) {
            i.printStackTrace();
        }
        return pKey;
    }

    public static String makeDigest(String payload, String digestAlgo) {
        String strDigest = "";
        try {
            MessageDigest md = MessageDigest.getInstance(digestAlgo);
            md.update(payload.getBytes("UTF-8"));
            byte[] digest = md.digest();
            byte[] encoded = Hex.encode(digest);
            strDigest = new String(encoded);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return strDigest;
    }

    public static String encrypt(String raw, String encryptAlgo, Key k) {



        String strEncrypted = "";
        try {
            Cipher cipher = Cipher.getInstance(encryptAlgo);
            cipher.init(Cipher.ENCRYPT_MODE, k);
            byte[] encrypted = cipher.doFinal(raw.getBytes("UTF-8"));
            byte[] encoded = Hex.encode(encrypted);
            strEncrypted = new String(encoded);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return strEncrypted;
    }

}

我的观点是,我生成了签名和有效负载,但我不知道我的 script.Can 哪里有问题,有人指导我吗?

它试图修复您的代码中的一些可能问题。也许尝试像这样的东西作为基础。

<?php

$email = "FinmomentaSample@perfios.com";
$server = "demo.perfios.com";
$vendor = "finmomenta";
$returnURL = "https://www.google.com";
$applicationId = "dummyApplicationId";
$perfiosTransactionId = "PLEASE UPDATE ME";
$format = "xml";

$privateKey = "-----BEGIN RSA PRIVATE KEY-----\n" .
    "MIIEpQIBAAKCAQEAx76oeNWYPkAbbSPyvJcPkQvAMvIHCPgY9yNdN/qsYMHytyit\n" .
    "xdO0aTatgfS/ig4zmqKFVpC9o2YMyQ7E1FYNcl/ev++r4nV+qVXA1OKcsSv4Kbj/\n" .
    "iNwxGmnhBsRDswY/dEZZDN9RisRpo9NRSOskGRv+nLEA2dLgj0/f9SSzykz3cxAP\n" .
    "bq6bV0unie5C8r6RALj+hTLU7B7QF88SkDsFx0/TYQe4H9QJtFMWJtOnhumY5Ku6\n" .
    "CL4OdZrtz71y4ji8IxQxv2nyq0JwYQ4rG84uzJQeRQf2RaJLhnSdfQnonDkP7L1z\n" .
    "NSizzi8VgHI+GVIo9FrLj7DVo+fFzMucbsvvNQIDAQABAoIBAQCMVKOR+SYzneBm\n" .
    "5hmUa2CxW5sVb7qHj54iiwLj4EYY2EnIaljjol+eh56Qrb2fpWiV3FZnQdspn/md\n" .
    "i7W3JBngYABjwmN0/20UVL3cErVZN/XqgiFtKp2I3BgPI/YYIWyVKRNJGt/z6Rf6\n" .
    "0+zImQLMbUGNHkHlxuSjas+CL93sYrXo52TXqZgk40gEkQVLE+SLrtXTFiOOlX/s\n" .
    "WWXyeUY14hl+oVQLmEO6UZd532bxAE0VlIV6Vr2pE3gJqEyaAoGgkT3inxvRPiek\n" .
    "swRm9OONWZD9frKXYqabJTsd87623Czg5h2WGimsN4fZ+LfyBXul24KKVeMDELHn\n" .
    "GvdRm95lAoGBAPMQRrb3iB8oYJc+4KwbtWR/vTQW++G69CeyIfD7WM0Ix3Gy0wod\n" .
    "FwIeKSkYsZ/R5n+9Ucx/RVFv7X86YzYajhH3hl+8/q4c+L1yAGS5hW3m21gIViDt\n" .
    "k1h3gKLI5o4EKGhCRX1teSoZ+n4G7KlYbJas8h5MX3u81GhKRmiVItr/AoGBANJg\n" .
    "KoIhxKsyNRccULosYZBGc3vpkFtpHeZ5w0qxbXaGveUIKvqzUqonGy0o3yqVNRrH\n" .
    "JJREHss+5/HqeuauawKUYLWapCqmVF6IlDc1PxTw+BLDzgzMlX2o43951iTMJXkd\n" .
    "80MOujsnyTdZq7wAzR7KNR3U/OjDFlcORxhCGrnLAoGBAONZcgtp9NTP+6j8k0Ho\n" .
    "mP5rzRmP9gHp0L3gjIbPUvxVHdhnn6ZyFzdP5sgd5ObMeoE5H+3bjYbi3o6Gmo3c\n" .
    "wM5lbDbYnI9XYgIxQ9TzAq8NpFTvV0Btd8jj3lpk9+IWWYVLl5v+bbrHmdmPuIWd\n" .
    "w9Qb6EwWu6kNss/pyXnBJV0ZAoGAPj+2VEsppn50tyHpwSzgsZAnG8NAs8umzUu6\n" .
    "PZ/ChA/aoKqKDSSCkVaA9Bvj7PW5gPLsH/MIKZuzhiGbvCZgA6Nj+liHuxb8X/yJ\n" .
    "3swink+vF95YWfEvSr9ukYm7k6fUbsIt+OmisV5Ua8xcxIR4LWQn02vyae1P7vKK\n" .
    "luL4hYECgYEAmSiiHa4bSLF8MT/IbL2YIrxK4yatABvVWZLkAV7hiFJWeEhLCmCd\n" .
    "OKcX8QSq9lT6TbS6NCEfHfCR0FFrny4nZMT3YnyDkgrYOiHhZL/YVfr3Izr62Gcy\n" .
    "PizNJH/JWoNDonAuFi+eQjgBRNfd894pMeCT4tMu2nE1SOEafzykzPA=\n" .
    "-----END RSA PRIVATE KEY-----";


$payloadStatement = "<payload>\n" .
    "<vendorId>" . $vendor . "</vendorId>\n" .
    "<txnId>" . $applicationId . "</txnId>\n" .
    "<yearMonthFrom>2017-06</yearMonthFrom>\n" .
    "<yearMonthTo>2017-12</yearMonthTo>" .
    "<emailId>#email#</emailId>\n<destination>statement</destination>\n" .
    "<returnUrl>" . $returnURL . "</returnUrl>\n" .
    "</payload>";


echo genericCreateHTML($payloadStatement, 'start', $email, $server, $privateKey);

function genericCreateHTML($payload, $operation, $email, $server, $privateKey)
{
    $email = encryptData($email, $privateKey);
    $payload = str_replace("#email#", $email, $payload);

    // Remove all line breaks
    $payload = str_replace("\n", "", $payload);

    $signature = getSignature($payload, $privateKey);

    $html = "<html>\n" . " <body onload='document.autoform.submit();'>\n" .
        "     <form name='autoform' method='post' action='https://" . $server . "/KuberaVault/insights/" . $operation . "'>\n" .
        "         <input type='hidden' name='payload' value='" . $payload . "'>\n" .
        "            <input type='hidden' name='signature' value='" . $signature . "'>\n" .
        "        </form>\n" . "  </body>\n" .
        "</html>\n";

    return $html;
}

function getSignature($data, $privateKey)
{
    // Make digest
    $digest = sha1($data);

    // Encrypt
    return encryptData($digest, $privateKey);
}

function encryptData($raw, $privateKey)
{
    $privateKey = openssl_pkey_get_private($privateKey);

    if (!$privateKey) {
        throw new RuntimeException('Invalid private key or passphrase');
    }

    // Encrypt digest using the key
    $encrypted = "";
    openssl_private_encrypt($raw, $encrypted, $privateKey, OPENSSL_PKCS1_PADDING);

    // Convert to Hex (base16)
    $result = bin2hex($encrypted);

    return $result;
}

如果有人想在go lang中等同于openssl_pkey_get_private,可以参考https://github.com/hixichen/golang_openssl_private_encrypt_rsa/blob/master/openssl_private_encrypt.go