Skip to content

Commit

Permalink
RELEASE
Browse files Browse the repository at this point in the history
  • Loading branch information
kaifer authored and root committed Feb 28, 2024
1 parent 9fd67fa commit 368a0af
Show file tree
Hide file tree
Showing 6 changed files with 208 additions and 72 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ JAVA 1.8버전 사용자들을 위한 세션키 발급 및 개인정보 암복

예시)
```
<version>0.0.12</version>
<version>0.0.13</version>
```

pom.xml 을 사용하시면 아래와 같이 추가해주세요.
Expand Down
3 changes: 2 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ plugins {
}

group 'com.github.toss'
version '0.0.12'
version '0.0.13'

sourceCompatibility = JavaVersion.VERSION_1_6
targetCompatibility = JavaVersion.VERSION_1_6
Expand All @@ -25,6 +25,7 @@ repositories {

dependencies {
implementation 'commons-codec:commons-codec:1.15'
implementation 'org.bouncycastle:bcpkix-jdk18on:1.77'
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.9.0'
testImplementation 'javax.json:javax.json-api:1.1.4'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.9.0'
Expand Down
38 changes: 38 additions & 0 deletions src/main/java/im/toss/cert/sdk/PKCS7CertificateExtractor.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package im.toss.cert.sdk;

import org.bouncycastle.cert.jcajce.JcaCertStoreBuilder;
import org.bouncycastle.cms.CMSException;
import org.bouncycastle.cms.CMSSignedData;

import java.security.GeneralSecurityException;
import java.security.cert.CertStore;
import java.security.cert.CertStoreException;
import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
import java.util.Collection;

public class PKCS7CertificateExtractor {
public static String extractCertificate(String pkcs7Data) {
try {
CMSSignedData signedData = new CMSSignedData(Base64Utils.decode(pkcs7Data));
CertStore certStore = new JcaCertStoreBuilder().addCertificates(signedData.getCertificates()).build();
Collection<? extends Certificate> certificates = certStore.getCertificates(null);
return convertToPem(certificates.iterator().next());
} catch (CMSException e) {
throw new RuntimeException(e.getCause());
} catch (CertificateEncodingException e) {
throw new RuntimeException(e.getCause());
} catch (CertStoreException e) {
throw new RuntimeException(e.getCause());
} catch (GeneralSecurityException e) {
throw new RuntimeException(e.getCause());
}
}

private static String convertToPem(Certificate certificate) throws CertificateEncodingException {
String pemCertPre = "-----BEGIN CERTIFICATE-----\n";
String pemCertPost = "\n-----END CERTIFICATE-----";
String pemCert = Base64Utils.encodeToString(certificate.getEncoded());
return pemCertPre + pemCert + pemCertPost;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import java.util.UUID;

public class TossCertSessionGenerator {
private final static String version = "v1_0.0.12";
private final static String version = "v1_0.0.13";
private final static String publicKey = "MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAoVdxG0Qi9pip46Jw9ImSlPVD8+L2mM47ey6EZna7D7utgNdh8Tzkjrm1Yl4h6kPJrhdWvMIJGS51+6dh041IXcJEoUquNblUEqAUXBYwQM8PdfnS12SjlvZrP4q6whBE7IV1SEIBJP0gSK5/8Iu+uld2ctJiU4p8uswL2bCPGWdvVPltxAg6hfAG/ImRUKPRewQsFhkFvqIDCpO6aeaR10q6wwENZltlJeeRnl02VWSneRmPqqypqCxz0Y+yWCYtsA+ngfZmwRMaFkXcWjaWnvSqqV33OAsrQkvuBHWoEEkvQ0P08+h9Fy2+FhY9TeuukQ2CVFz5YyOhp25QtWyQI+IaDKk+hLxJ1APR0c3tmV0ANEIjO6HhJIdu2KQKtgFppvqSrZp2OKtI8EZgVbWuho50xvlaPGzWoMi9HSCb+8ARamlOpesxHH3O0cTRUnft2Zk1FHQb2Pidb2z5onMEnzP2xpTqAIVQyb6nMac9tof5NFxwR/c4pmci+1n8GFJIFN18j2XGad1mNyio/R8LabqnzNwJC6VPnZJz5/pDUIk9yKNOY0KJe64SRiL0a4SNMohtyj6QlA/3SGxaEXb8UHpophv4G9wN1CgfyUamsRqp8zo5qDxBvlaIlfkqJvYPkltj7/23FHDjPi8q8UkSiAeu7IV5FTfB5KsiN8+sGSMCAwEAAQ==";

private final RSACipher rsaCipher;
Expand Down
149 changes: 80 additions & 69 deletions src/test/java/im/toss/cert/sdk/ExampleTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,23 @@
import javax.json.Json;
import javax.json.JsonObject;
import javax.json.JsonReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.StringReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Scanner;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

@Disabled // 실행전에 해당라인을 삭제해주세요.
class ExampleTest {
// 0. 세션 생성기를 사전에 1회만 생성해 주세요.
TossCertSessionGenerator tossCertSessionGenerator = new TossCertSessionGenerator();

final String accessToken = "eyJraWQiOiJjZXJ0IiwiYWxnIjoiUlMyNTYifQ.eyJzdWIiOiJ0ZXN0X2E4ZTIzMzM2ZDY3M2NhNzA5MjJiNDg1ZmU4MDZlYjJkIiwiYXVkIjoidGVzdF9hOGUyMzMzNmQ2NzNjYTcwOTIyYjQ4NWZlODA2ZWIyZCIsIm5iZiI6MTcwOTAyMDA5OSwic2NvcGUiOlsiY2EiXSwiaXNzIjoiaHR0cHM6Ly9jZXJ0LnRvc3MuaW0iLCJleHAiOjE3NDA1NTYwOTksImlhdCI6MTcwOTAyMDA5OSwianRpIjoiZDc3NmUxZmEtZmNkMy00MDE4LTg2MGMtZDA0NTY0YmUxY2U5In0.hQDc7eeY6-a-0tLfcsAO_Tejbmu_Sd7f80P90NtTy6T4HjEUQNji13sMdkhPeibnonE0E8d4fdsyFy2J2KQFLIqFNjV-jPypjm9XcF2yUBwBfG7Jq7k1BBuigPXTN1NistNpnE24F0nNlMzsGZi72YePIFEayFi_SQN5GUwZ9MZbQenGA9sKct0heqKxQj7wuyELgvT7dCFtZ5EU_C_DDhvgtyauGvD4ubtxj2_-SskAnr54LZhW-cDF-rdsAD9knbhcnscpZKXnGVNlXbQzgrVfWNEYlJeZ9bwagdgYh67VrC8SNBoGPuXsKU4eUV17lh_TwB9M2lPkBJLwgaJVgA";

@Test
void request() throws Exception {
// 1. 개인정보가 포함되어 있는 인증요청 API 호출 전에 세션을 생성해 주세요.
Expand All @@ -34,105 +37,113 @@ void request() throws Exception {
String encryptedUserBirthday = tossCertSession.encrypt(userBirthday);

// 3. 인증요청 API 를 호출해주세요.
URL url = new URL("https://cert.toss.im/api/v2/sign/user/auth/request");
HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
httpConn.setRequestMethod("POST");

httpConn.setRequestProperty("Authorization", "Bearer eyJraWQiOiJjZXJ0IiwiYWxnIjoiUlMyNTYifQ.eyJzdWIiOiJ0ZXN0X2E4ZTIzMzM2ZDY3M2NhNzA5MjJiNDg1ZmU4MDZlYjJkIiwiYXVkIjoidGVzdF9hOGUyMzMzNmQ2NzNjYTcwOTIyYjQ4NWZlODA2ZWIyZCIsIm5iZiI6MTY0OTIyMjk3OCwic2NvcGUiOlsiY2EiXSwiaXNzIjoiaHR0cHM6XC9cL2NlcnQudG9zcy5pbSIsImV4cCI6MTY4MDc1ODk3OCwiaWF0IjoxNjQ5MjIyOTc4LCJqdGkiOiI4MDNjNDBjOC1iMzUxLTRmOGItYTIxNC1iNjc5MmNjMzBhYTcifQ.cjDZ0lAXbuf-KAgi3FlG1YGxvgvT3xrOYKDTstfbUz6CoNQgvd9TqI6RmsGZuona9jIP6H12Z1Xb07RIfAVoTK-J9iC5_Yp8ZDdcalsMNj51pPP8wso86rn-mKsrx1J5Rdi3GU58iKt0zGr4KzqSxUJkul9G4rY03KInwvl692HU19kYA9y8uTI4bBX--UPfQ02G0QH9HGTPHs7lZsISDtyD8sB2ikz5p7roua7U467xWy4BnRleCEWO2uUaNNGnwd7SvbjhmsRZqohs9KzDUsFjVhSiRNdHL53XJQ5zFHwDF92inRZFLu6Dw8xttPtNHwAD1kT84uXJcVMfEHtwkQ");
httpConn.setRequestProperty("Content-Type", "application/json");
httpConn.setDoOutput(true);
OutputStreamWriter writer = new OutputStreamWriter(httpConn.getOutputStream());
/* json
{
"requestType": "USER_PERSONAL",
"triggerType": "PUSH",
"sessionKey": tossCertSession.getSessionKey(),
"userName": encryptedUserName,
"userPhone": encryptedUserPhone,
"userBirthday": encryptedUserBirthday
}
*/
/* json
{
"requestType": "USER_PERSONAL",
"triggerType": "PUSH",
"sessionKey": tossCertSession.getSessionKey(),
"userName": encryptedUserName,
"userPhone": encryptedUserPhone,
"userBirthday": encryptedUserBirthday
}
*/
String requestBody = Json.createObjectBuilder()
.add("requestType", "USER_PERSONAL")
.add("triggerType", "PUSH")
// 3.1 세션키를 넣어주세요.
.add("sessionKey", tossCertSession.getSessionKey())
// 3.2 tossCertSession 로 암호화된 개인정보를 넣어주세요.
.add("userName", encryptedUserName)
.add("userPhone", encryptedUserPhone)
.add("userBirthday", encryptedUserBirthday)
.build()
.toString();
writer.write(requestBody);
writer.flush();
writer.close();

httpConn.getOutputStream().close();
InputStream responseStream = httpConn.getResponseCode() == 200
? httpConn.getInputStream()
: httpConn.getErrorStream();
Scanner s = new Scanner(responseStream).useDelimiter("\\A");
String response = s.hasNext() ? s.next() : "";
.add("requestType", "USER_PERSONAL")
.add("triggerType", "PUSH")
// 3.1 세션키를 넣어주세요.
.add("sessionKey", tossCertSession.getSessionKey())
// 3.2 tossCertSession 로 암호화된 개인정보를 넣어주세요.
.add("userName", encryptedUserName)
.add("userPhone", encryptedUserPhone)
.add("userBirthday", encryptedUserBirthday)
.build()
.toString();

JsonObject responseObject = postUrl("https://cert.toss.im/api/v2/sign/user/auth/request", requestBody);

JsonReader responseReader = Json.createReader(new StringReader(response));
JsonObject responseObject = responseReader.readObject();
System.out.println("\n--------------------------- 인증 요청 결과 -------------------------------------");
System.out.println("인증 txId: " + responseObject.getJsonObject("success").getString("txId"));
System.out.println("----------------------------------------------------------------------------\n");
assertEquals(1, 1);
}

// 결과호출을 하기전에 토스앱에서 인증을 완료해 주세요.

@Test
void result() throws Exception {
// 0. 인증 요청 결과에서 응답받은 인증 txId 로 변경한 후 테스트 해주세요.
String txId = "2122cb6d-46f9-4e72-86eb-3f71c3c97507";
String txId = "인증 txId";

// 1. 인증 결과 조회 API 호출 전에 세션을 생성해 주세요.
TossCertSession tossCertSession = tossCertSessionGenerator.generate();

// 2. 인증요청 API 를 호출해주세요.
URL url = new URL("https://cert.toss.im/api/v2/sign/user/auth/result");
/* json
{
"sessionKey": tossCertSession.getSessionKey(),
"txId": txId
}
*/
String requestBody = Json.createObjectBuilder()
// 2.1 세션키를 넣어주세요.
.add("sessionKey", tossCertSession.getSessionKey())
// 2.2 인증 요청 결과의 txId 를 넣어주세요.
.add("txId", txId)
.build()
.toString();

JsonObject responseObject = postUrl("https://cert.toss.im/api/v2/sign/user/auth/result", requestBody);

// 3. 결과를 복호화 합니다.
String encryptedCi = responseObject.getJsonObject("success").getJsonObject("personalData").getString("ci");
String ci = tossCertSession.decrypt(encryptedCi);
System.out.println("\n--------------------------- 인증 결과 조회 CI ----------------------------------");
System.out.println("복호화 된 CI: " + ci);
System.out.println("----------------------------------------------------------------------------\n");

// 4. 인증서 유효성을 검사합니다.
String signature = responseObject.getJsonObject("success").getString("signature");
String pemCertificate = PKCS7CertificateExtractor.extractCertificate(signature);

/* json
{
"certificate": pemCertificate
}
*/
requestBody = Json.createObjectBuilder()
// 2.1 세션키를 넣어주세요.
.add("certificate", pemCertificate)
// 2.2 인증 요청 결과의 txId 를 넣어주세요.
.build()
.toString();

responseObject = postUrl("https://cert.toss.im/api/v1/certificate/validate", requestBody);

assertTrue(responseObject.getJsonObject("success").getBoolean("valid"));
assertTrue(responseObject.getJsonObject("success").getBoolean("enabled"));
}

private JsonObject postUrl(String urlString, String requestBody) throws IOException {
URL url = new URL(urlString);
HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
httpConn.setRequestMethod("POST");

httpConn.setRequestProperty("Authorization", "Bearer eyJraWQiOiJjZXJ0IiwiYWxnIjoiUlMyNTYifQ.eyJzdWIiOiJ0ZXN0X2E4ZTIzMzM2ZDY3M2NhNzA5MjJiNDg1ZmU4MDZlYjJkIiwiYXVkIjoidGVzdF9hOGUyMzMzNmQ2NzNjYTcwOTIyYjQ4NWZlODA2ZWIyZCIsIm5iZiI6MTY0OTIyMjk3OCwic2NvcGUiOlsiY2EiXSwiaXNzIjoiaHR0cHM6XC9cL2NlcnQudG9zcy5pbSIsImV4cCI6MTY4MDc1ODk3OCwiaWF0IjoxNjQ5MjIyOTc4LCJqdGkiOiI4MDNjNDBjOC1iMzUxLTRmOGItYTIxNC1iNjc5MmNjMzBhYTcifQ.cjDZ0lAXbuf-KAgi3FlG1YGxvgvT3xrOYKDTstfbUz6CoNQgvd9TqI6RmsGZuona9jIP6H12Z1Xb07RIfAVoTK-J9iC5_Yp8ZDdcalsMNj51pPP8wso86rn-mKsrx1J5Rdi3GU58iKt0zGr4KzqSxUJkul9G4rY03KInwvl692HU19kYA9y8uTI4bBX--UPfQ02G0QH9HGTPHs7lZsISDtyD8sB2ikz5p7roua7U467xWy4BnRleCEWO2uUaNNGnwd7SvbjhmsRZqohs9KzDUsFjVhSiRNdHL53XJQ5zFHwDF92inRZFLu6Dw8xttPtNHwAD1kT84uXJcVMfEHtwkQ");
httpConn.setRequestProperty("Authorization", "Bearer " + accessToken);
httpConn.setRequestProperty("Content-Type", "application/json");
httpConn.setDoOutput(true);
OutputStreamWriter writer = new OutputStreamWriter(httpConn.getOutputStream());
/* json
{
"sessionKey": tossCertSession.getSessionKey(),
"txId": txId
}
*/
String requestBody = Json.createObjectBuilder()
// 2.1 세션키를 넣어주세요.
.add("sessionKey", tossCertSession.getSessionKey())
// 2.2 인증 요청 결과의 txId 를 넣어주세요.
.add("txId", txId)
.build()
.toString();

writer.write(requestBody);
writer.flush();
writer.close();

httpConn.getOutputStream().close();
InputStream responseStream = httpConn.getResponseCode() == 200
? httpConn.getInputStream()
: httpConn.getErrorStream();
? httpConn.getInputStream()
: httpConn.getErrorStream();
Scanner s = new Scanner(responseStream).useDelimiter("\\A");
String response = s.hasNext() ? s.next() : "";
JsonReader responseReader = Json.createReader(new StringReader(response));
JsonObject responseObject = responseReader.readObject();

// 3. 결과를 복호화 합니다.
String encryptedCi = responseObject.getJsonObject("success").getJsonObject("personalData").getString("ci");
String ci = tossCertSession.decrypt(encryptedCi);
System.out.println("\n--------------------------- 인증 결과 조회 CI ----------------------------------");
System.out.println("복호화 된 CI: " + ci);
System.out.println("----------------------------------------------------------------------------\n");
assertEquals(1, 1);
JsonReader responseReader = Json.createReader(new StringReader(response));
return responseReader.readObject();
}
}
Loading

0 comments on commit 368a0af

Please sign in to comment.