2017-12-16 38 views
0

현재 PHP를 사용하는 금융 기반 응용 프로그램에서 일하고 있습니다. 사용자 데이터를 가져 오기 위해 제 3 자 API와 통합되었습니다.PHP에서 RSA 비공개 키로 데이터를 암호화하는 방법은 무엇입니까?

통합을 기반으로 서명과 페이로드로 인증됩니다. 문서 당으로

, 내가 바로 견해에 대한 모든 것을했다,하지만 난

SignatureDoesNotMatch 우리는 당신이 제공하는 서명과 일치하지 않습니다 계산 요청 서명과 같은 응답을 얻었다. 문서 당으로

:

서명을 계산 : 보낸 사람의 서명이 있어야합니다 필요 요청. 다음과 같이

  1. 은 하나의 라인으로 페이로드 XML을 응축 : 다음과 같이 요청의 서명이 계산됩니다 XML 선언 2.Remove 3.Remove 모든 코멘트 4.Remove 모든 라인은 5 나누기. 정규화 공백

6) 응축 된 페이로드의 SHA1 다이제스트를 생성합니다. 7) Base16은 생성 된 SHA1 다이제스트를 인코딩합니다. 8) Perfios 제공 RSA 개인 키를 사용하여 인코딩 된 다이제스트를 암호화합니다. 9) Base16은 암호화 된 다이제스트를 인코딩합니다. 여기

내 스크립트를

<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 요청

$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); 

그래서 여기에 페이로드 및 서명 및 게시 방법과 URL을 보낼 생성 계산 한 서명과 사용자가 제공 한 서명이 일치하지 않습니다.

API 지원 팀이 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 사람 잘못입니다 몰라요?

+1

'sha1'의 반환 값은 이미 16 진수 (base16)로 인코딩되어 있다고 생각합니다. – DanielO

+0

좋아요, 페이로드의 sha1 변환 후, 내가해야 할 일은, 직접 rsa 개인 키로 암호화 된 base_16을 인코딩 할 필요가 없습니까? @ 다니엘. –

답변

1

코드에서 가능한 문제를 수정하려고 시도했습니다. 어쩌면 이것을 기초로 시도해보십시오.

<?php 

$email = "[email protected]"; 
$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; 
} 
+0

안녕하세요, response.I 주셔서 감사 스크립트를 수정했지만 여전히 동일한 오류가 발생했습니다. ** SignatureDoesNotMatch 계산 된 요청 서명이 귀하가 제공 한 서명과 일치하지 않습니다. ** –

+1

16 진수 문자열은 대문자 '$ signature = strtoupper ($ signature)'로 작성되어야합니다. 불행히도 추가 컨텍스트 정보 없이는 도움이되지 않습니다. API 제공 업체에 문의하십시오. – DanielO

+0

안녕하세요, API 서비스 공급자는 자바에서 API를 실행하는 예제 스크립트를 제공하고, 내가 실행하고 자바를 실행, 우리의 응용 프로그램에서 잘 작동하지만, PHP의 종속성은 –