現在、phpを使用して金融ベースのアプリケーションで作業しています。ユーザーデータを取得するためにサードパーティのAPIと統合されています。PHPでRSA秘密鍵でデータを暗号化するには?
インテグレーションに基づいて、署名とペイロードで認証しています。文書を1として
、私は右の私の視点のためにすべてをした、しかし、私は、我々が算出した要求の署名が指定した署名と一致しません
SignatureDoesNotMatch
のような応答を得ました。文書1として
:
署名を計算する:、送信者によって署名されなければならない必要 要求を。次のように要求の署名が計算される。
- 次のように単一のラインにペイロードXMLを凝縮: 2.Remove XML宣言 3.Removeをすべてのコメント 4.Removeすべてのラインが 5を破ります。正規化スペース
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
要求 私たちが計算した署名は、あなたが提供した署名と一致しません。
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 = "[email protected]";
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誰と間違っている知りませんか?
'sha1'の戻り値はすでに16進数(base16)でエンコードされていると思います。 – DanielO
だから、私は、ペイロードのsha1変換の後に、base_16をエンコードする必要はなく、rsa秘密鍵で直接暗号化した後に何をする必要がありますか? @DanielO。 –