서비스(서버) 인증서
서비스 인증서
NHN KCP 발급 서비스 인증서는 KCP-API 결제시 필요한 인증서 입니다.
실제 서비스 운영을 위해서는 각 상점에 맞는 서비스 인증서가 필요합니다.
NHN KCP 발급 인증서 내 데이터 값 추출,
가맹점 인증을 위해 KCP로부터 발급 받은 인증서 정보를 text 형식으로 전달해주셔야 하며,
인증서의 text 값을 데이터 직렬화하여 kcp_cert_info 의 value 값으로 전달하시기 바랍니다.
kcp_cert_info는 결제 승인 거래취소 거래등록 시에 필요합니다.
테스트 서비스 인증서는 아래 KCP 서비스 인증서 예시와 다운로드 자료실을 참고 부탁 드립니다.
추가적으로 KCP 상점 관리사이트(partner.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 는 거래취소 시에 필요합니다.
Cancel API 서명데이터(kcp_sign_data)는,
site_cd + "^" + tno + "^" + mod_type 규칙으로 생성하며
SHA256withRSA 알고리즘을 통하여 인코딩 후 요청하시기 바랍니다.
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)