서비스(서버) 인증서


서비스 인증서

NHN KCP 발급 서비스 인증서는 KCP-API 결제시 필요한 인증서 입니다.
실제 서비스 운영을 위해서는 각 상점에 맞는 서비스 인증서가 필요합니다.

NHN KCP 발급 인증서 내 데이터 값 추출,
가맹점 인증을 위해 KCP로부터 발급 받은 인증서 정보를 text 형식으로 전달해주셔야 하며,
인증서의 text 값을 데이터 직렬화하여 kcp_cert_info 의 value 값으로 전달하시기 바랍니다.

kcp_cert_info는 결제 승인 거래취소 거래등록 조회 시에 필요합니다.

NHN KCP 서비스 인증서 발급이 필요하시거나 관련된 문의사항은
문의하기등을 통한 별도 문의 접수를 부탁 드립니다.

테스트 서비스 인증서 값은 아래 KCP 서비스 인증서 예시와 다운로드 자료실을 참고 부탁 드립니다.

추가적으로 KCP 상점 관리사이트(admin8.kcp.co.kr) 로그인 > 고객센터 > 인증센터 > KCP PG-API > 발급하기 경로에서 개인키 + 인증서 발급이 가능합니다.

kcp_cert_info

<!-- kcp_cert_info 요청 예시 -->

1"kcp_cert_info":"-----BEGIN CERTIFICATE-----MIID3DCCAsSgAwIBAgIJAMzLXkRXpY3KMA0GCSqGSIb3DQEBCwU...bpE1aPTjDDQsuUduNaCu1jYuBALO+LelrFA...VNeequGLUZSx1il+tJU=-----END CERTIFICATE-----"

암호화 데이터 전송

서명데이터(kcp_sign_data)는, 가맹점 부인방지와 요청 데이터의 무결성 검증을 위한 데이터이며,
KCP로부터 발급받은 개인키(PRIVATE KEY)로 SHA256withRSA 알고리즘을 사용하여
문자열을 인코딩하는 방식으로 이루어집니다.

kcp_sign_data 는거래조회 거래취소 시에 필요합니다.

Inquery API 서명데이터(kcp_sign_data)는,
site_cd + "^" + tno + "^" + pay_type 규칙으로 생성하며 SHA256withRSA 알고리즘을 통하여 인코딩 후 요청하시기 바랍니다.

Cancel API 서명데이터(kcp_sign_data)는,
site_cd + "^" + tno + "^" + mod_type 규칙으로 생성하며 SHA256withRSA 알고리즘을 통하여 인코딩 후 요청하시기 바랍니다.

NHN KCP 개인키 발급이 필요하시거나 관련된 문의사항은 문의하기등을 통한 별도 문의 접수를 부탁 드립니다.

테스트 개인키는 다운로드 자료실을 확인해주세요.

추가적으로 KCP 상점 관리사이트(admin8.kcp.co.kr) 로그인 > 고객센터 > 인증센터 > KCP PG-API > 발급하기 경로에서 개인키 + 인증서 발급이 가능합니다.

kcp_sign_data

<!-- kcp_sign_data 요청 예시 -->

1  "kcp_sign_data":"QdwMF6y3GU1JTVkSv7Yn20CCCTeFrKkjvrdZOjShiFibFo...cA0nyX+4HEUZ4Fy3U+htmkZqAfJljeujC1KAL5Flnzqbp5Tst5p5SvZ...0qH7NSq0c6BpedDZb04w=="

KCP 서비스 인증서

kcp_sign_data 생성예시

public class MakeSplParam
  {
    static{ Security.addProvider( new BouncyCastleProvider() ); }

      public static void main(String[] args)
      {
          PrivateKey priKey       = loadSplMctPrivateKeyPKCS8( "../splPrikeyPKCS8.pem", "changeit" ); // (개인키 경로, 개인키 비밀번호)
          String signData   = makeSignatureData( priKey, "T0000^20210719000000^PACA" );	// 서명데이터 생성
          System.out.println( "\n[서명데이터(kcp_sign_data)] : " + signData );
      }
      public static PrivateKey loadSplMctPrivateKeyPKCS8( String filePath, String privateKeyPassword )
      {
          PrivateKey priKey = null;
      Path path = Paths.get( filePath );
      String strPriKeyData = Files.readAllLines( path )
          .stream()
          .filter( line -> !line.startsWith( "-----BEGIN" ) && !line.startsWith( "-----END" ) )
          .collect( Collectors.joining() );

      byte[] btArrPriKey   = Base64.getDecoder().decode( strPriKeyData );

      ASN1Sequence derSeq = ASN1Sequence.getInstance( btArrPriKey );
      PKCS8EncryptedPrivateKeyInfo encPkcs8PriKeyInfo = new PKCS8EncryptedPrivateKeyInfo( org.bouncycastle.asn1.pkcs.EncryptedPrivateKeyInfo.getInstance( derSeq ) );
      JcaPEMKeyConverter pemKeyConverter = new JcaPEMKeyConverter();
      InputDecryptorProvider decProvider = new JceOpenSSLPKCS8DecryptorProviderBuilder().build( privateKeyPassword.toCharArray() );
      PrivateKeyInfo priKeyInfo          = encPkcs8PriKeyInfo.decryptPrivateKeyInfo( decProvider );
      priKey                             = pemKeyConverter.getPrivateKey( priKeyInfo );

          return priKey;
      }
      public static String makeSignatureData(PrivateKey priKey, String targetData)
      {
          String signData = null;
          byte[] btArrTargetData = targetData.getBytes( StandardCharsets.UTF_8 );

      Signature sign = Signature.getInstance( "SHA256WithRSA" );
      sign.initSign( priKey );
      sign.update( btArrTargetData );

      byte[] btArrSignData = sign.sign();
      signData = Base64.getEncoder().encodeToString( btArrSignData );

      return signData;
      }
  }
<?php
  $cancel_target_data = "T0000^22284971100001^STSC";
  // 결제 취소 (cancel) = site_cd^KCP거래번호^취소유형

  $key_data = file_get_contents('../splPrikeyPKCS8.pem');
  // 개인키 경로 ("splPrikeyPKCS8.pem" 은 테스트용 개인키)
  $pri_key = openssl_pkey_get_private($key_data,'changeit');
  // 개인키 비밀번호

  openssl_sign($cancel_target_data, $signature, $pri_key, 'sha256WithRSAEncryption');
  // 결제 취소 signature 생성
  echo "cancel_signature :".base64_encode($signature)."<br><br>";
?>
namespace kcp_sign_data_sample
{
    class Program
    {
        static void Main(string[] args)
        {
            // PKCS#8 PEM READ
            StreamReader sr = new StreamReader("../splPrikeyPKCS8.pem"); // 개인키 경로 ("splPrikeyPKCS8.pem" 은 테스트용 개인키)
            String privateKeyText = sr.ReadToEnd();
            // 개인키 비밀번호
            string privateKeyPass = "changeit"; // 개인키 비밀번호 ("changeit" 은 테스트용 개인키 비밀번호)
            // 개인키정보 READ
            StringReader stringReader = new StringReader(privateKeyText);
            PemReader pemReader = new PemReader(stringReader, new PasswordFinder(privateKeyPass));
            RsaPrivateCrtKeyParameters keyParams = (RsaPrivateCrtKeyParameters)pemReader.ReadObject();

            byte[] tmpSource = Encoding.ASCII.GetBytes("T0000^22671971380028^PACA");

            ISigner sign = SignerUtilities.GetSigner(PkcsObjectIdentifiers.Sha256WithRsaEncryption.Id);
            sign.Init(true, keyParams);
            sign.BlockUpdate(tmpSource, 0, tmpSource.Length);

            var kcp_sign_data = sign.GenerateSignature();
            // Console 출력
            Console.WriteLine("kcp_sign_data:" + Convert.ToBase64String(kcp_sign_data));
            Console.ReadKey();
        }

        private class PasswordFinder : IPasswordFinder
        {
            private string password;
            public PasswordFinder(string pwd)
            {
              password = pwd;
            }
            public char[] GetPassword()
            {
              return password.ToCharArray();
            }
        }
    }
}
<%
    textToSign = "T0000^22671971380028^PACA" '서명대상데이터(site_cd^tno^mod_type)
    set kcpSign = server.createobject("kcp_sign_data_lib.GenSign") '서명데이터생성 예제 lib
    kcp_sign_data = kcpSign.Sign("../splPrikeyPKCS8.pem", "changeit", textToSign) '(테스트용 개인키,테스트용 개인키 비밀번호)

    response.write "kcp_sign_data : " + kcp_sign_data + "<br/>"
%>

  const data = "T0000^22296971511092^PACA";
  const crypto = require('crypto');
  const fs = require('fs');
  // 서명데이터 생성 함수 호출
  const signature = getSignatureToVerify(data);
  // 서명데이터 생성을 위한 개인키 READ
  function getPrivateKeySomehow()
  {
      const pKey = fs.readFileSync('../splPrikeyPKCS8.pem', 'utf8' ); // "splPrikeyPKCS8.pem" 은 테스트용 개인키
      const pKeyObj = crypto.createPrivateKey({
          key : pKey,
          passphrase : "changeit", // "changeit" 은 테스트용 개인키 비밀번호
          format : "pem",
          type : "pkcs8"
          })
      const pKeyStr = pKeyObj.export({
           format: 'pem',
            type: 'pkcs8'
          }).toString();
      return pKeyStr;
  }

  // 서명데이터 생성 함수
  function getSignatureToVerify(data)
  {
      const privateKey = getPrivateKeySomehow();
      const sign = crypto.createSign("SHA256");
      sign.update(data);
      const signature = sign.sign(privateKey, "base64");
      console.log(">>> Signature:\n\n" + signature);
      return signature;
  }

  import OpenSSL
  from OpenSSL import crypto
  import base64

  data = 'T0000^22671971380028^PACA'
  # "splPrikeyPKCS8.pem" 은 테스트용 개인키
  key_file = open('../splPrikeyPKCS8.pem', 'r')
  key = key_file.read()
  key_file.close()
  # "changeit" 은 테스트용 개인키비밀번호
  password = 'changeit'.encode('utf-8')
  pkey = crypto.load_privatekey(crypto.FILETYPE_PEM, key, password)
  # 서명데이터생성
  sign = OpenSSL.crypto.sign(pkey, data, 'sha256')
  kcp_sign_data = base64.b64encode(sign)
  print("kcp_sign_data : ", kcp_sign_data)