diff --git a/README.md b/README.md index 3263f57..bcd6d19 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ JAVA 1.8버전 사용자들을 위한 세션키 발급 및 개인정보 암복 예시) ``` -0.0.12 +0.0.13 ``` pom.xml 을 사용하시면 아래와 같이 추가해주세요. diff --git a/build.gradle b/build.gradle index 3a58ad5..c710d48 100644 --- a/build.gradle +++ b/build.gradle @@ -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 @@ -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' diff --git a/src/main/java/im/toss/cert/sdk/PKCS7CertificateExtractor.java b/src/main/java/im/toss/cert/sdk/PKCS7CertificateExtractor.java new file mode 100644 index 0000000..9daddb4 --- /dev/null +++ b/src/main/java/im/toss/cert/sdk/PKCS7CertificateExtractor.java @@ -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 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; + } +} diff --git a/src/main/java/im/toss/cert/sdk/TossCertSessionGenerator.java b/src/main/java/im/toss/cert/sdk/TossCertSessionGenerator.java index e02c56b..bdfb6d3 100644 --- a/src/main/java/im/toss/cert/sdk/TossCertSessionGenerator.java +++ b/src/main/java/im/toss/cert/sdk/TossCertSessionGenerator.java @@ -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; diff --git a/src/test/java/im/toss/cert/sdk/ExampleTest.java b/src/test/java/im/toss/cert/sdk/ExampleTest.java index 265ff39..a03adb4 100644 --- a/src/test/java/im/toss/cert/sdk/ExampleTest.java +++ b/src/test/java/im/toss/cert/sdk/ExampleTest.java @@ -6,6 +6,7 @@ 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; @@ -13,13 +14,15 @@ 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 호출 전에 세션을 생성해 주세요. @@ -34,52 +37,33 @@ 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); } // 결과호출을 하기전에 토스앱에서 인증을 완료해 주세요. @@ -87,52 +71,79 @@ void request() throws Exception { @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(); } } diff --git a/src/test/java/im/toss/cert/sdk/PKCS7CertificateExtractorTest.java b/src/test/java/im/toss/cert/sdk/PKCS7CertificateExtractorTest.java new file mode 100644 index 0000000..3b4034d --- /dev/null +++ b/src/test/java/im/toss/cert/sdk/PKCS7CertificateExtractorTest.java @@ -0,0 +1,86 @@ +package im.toss.cert.sdk; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class PKCS7CertificateExtractorTest { + + @Test + void test() { + String pemCertificate = PKCS7CertificateExtractor.extractCertificate(pkcs7Data); + assertEquals(expectedPemCertificate, pemCertificate); + } + + private final String pkcs7Data = + "MIIIZAYJKoZIhvcNAQcCoIIIVTCCCFECAQExDzANBglghkgBZQMEAgEFADAeBgkqhkiG9w0BBwGg" + + "EQQPZG9jdW1lbnQgc2FtcGxloIIGJjCCBiIwggQKoAMCAQICBAFAvqIwDQYJKoZIhvcNAQELBQAw" + + "UTELMAkGA1UEBgwCS1IxGzAZBgNVBAoMElZpdmEgUmVwdWJsaWNhIEluYzESMBAGA1UECwwJVG9z" + + "cyBDZXJ0MREwDwYDVQQDDAhUb3NzIENBMTAeFw0yNDAyMTUwNTIzNDdaFw0yNzAyMTQxNDU5NTla" + + "MHwxCzAJBgNVBAYTAktSMRswGQYDVQQKDBJWaXZhIFJlcHVibGljYSBJbmMxEjAQBgNVBAsMCVRv" + + "c3MgQ2VydDEoMCYGCgmSJomT8ixkAQEMGDcwMDI3MjEyMDIxMTExODgwMjAwMDAwMTESMBAGA1UE" + + "AwwJ7KCV7J246raMMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkx0j1LpuVyn0G8RH" + + "oXleMrB27nf4uH57lr1Bchgkp5CysakjIQ/Q06Gosr4JmlrfPYiAlPHYcqTwKvU/uxUK7GoH9Ymx" + + "K8Z4xFJuHAQdMzMS63QVq5LH5VFjujutpR0vY5rQOSaQZUTSuybSlI9GxCUJwh0bSZhPUmHrpURl" + + "Qj//fGk8+LpBDsXUECypGq7UlM5M4z1bOOYA1I3SyCmvnqIiMd4xNx+Vy1bRvB3U6fE/vsplYFvz" + + "Efrcc2xVfnPGypskQZ0iv0ydw6TegAMkOGUttZQik7wMyZ7in4lbpidpTdyzGpoQtbUm3A56tbWG" + + "N4y9ru0RvtbvJVsTftULVQIDAQABo4IB1TCCAdEwfgYDVR0jBHcwdYAUIOEEYoA6EFhC3FSBskx+" + + "jPX3qh+hWqRYMFYxCzAJBgNVBAYMAktSMRswGQYDVQQKDBJWaXZhIFJlcHVibGljYSBJbmMxEjAQ" + + "BgNVBAsMCVRvc3MgQ2VydDEWMBQGA1UEAwwNVG9zcyBSb290IENBMYIBAjAdBgNVHQ4EFgQUGGl2" + + "Nn0TMLprdD5gjlLyzrJPOgUwDgYDVR0PAQH/BAQDAgbAMIGLBgNVHSABAf8EgYAwfjB8BgsqgxqM" + + "myIFAQEBAzBtMCsGCCsGAQUFBwIBFh9odHRwOi8vY2EuY2VydC50b3NzLmltL2Nwcy5odG1sMD4G" + + "CCsGAQUFBwICMDIeMABUAGgAaQBzACAAaQBzACAAVABvAHMAcwAgAGMAZQByAHQAaQBmAGkAYwBh" + + "AHQAZTBbBgNVHR8EVDBSMFCgTqBMhkpodHRwOi8vY2EuY2VydC50b3NzLmltL2NybC90b3NzX2Ny" + + "bF9kcDJwNzAwNy5jcmw/Y2VydGlmaWNhdGVSZXZvY2F0aW9uTGlzdDA1BggrBgEFBQcBAQQpMCcw" + + "JQYIKwYBBQUHMAGGGWh0dHA6Ly9vY3NwLmNlcnQudG9zcy5pbS8wDQYJKoZIhvcNAQELBQADggIB" + + "AC2CSrLGoNRT9KtjA5iGGSD8oOuc7gKcxn19B9gE2fcfe8tl3CiUYCBs6GTO8U29q0CeDVadmN0m" + + "dOE1V7qMDCdjEQLf4cskMKn0LNj406b+LhsYJPks+9Ra4RAl+P5QMrkVnfKS9HmM+k1snvMJXMV+" + + "zHwapai0C2cK1dKAttL+WZH5VhP2P48yDCRmoaB8ZzQ1YhS+PVyqtvGqSJBYbJusBXulMULcxbFq" + + "d/bSbIuyKEvUsd+6NbhT5jKs8EFbZ/fUPRMZusJj/VepIhwyb4hK3QiTgAq88Z8Tcofzq/1oV4Mm" + + "dRcj7IGdcSd2k6JgP+R6UObNaSTjjDLC9JfiOtXbnz9Lh55fG48r11qP2oZukyJGFdjI6HSiYScA" + + "cloc2INMFzifWioY3rG/bucLBqJGs5CU3ZYNaTKsGMnU7GPGCm3Rvh14QYB3I918VT8nrlcdiWZl" + + "MiPj6QUNSdTDuTgUDr/ud50VaD0ZhRNWouZ9w7V+Be+gGpv08HR6Ebdy+MuecxjjpIwPsbeBwjfg" + + "KPB+aEMdgYfVb8t/TQimbH8vxEUlct8+NRVawLe5F4ZXRMtr8WfbhTPU3aJiraemy7OGXxDkdRkO" + + "DHhG82Gjl8AQ4Rs5wveJvnT3a0/UUwBb3XTvYylGCHbw8i+ShbZ0ZU9E6anycByWlBZ16Agq4seR" + + "MYIB7zCCAesCAQEwWTBRMQswCQYDVQQGDAJLUjEbMBkGA1UECgwSVml2YSBSZXB1YmxpY2EgSW5j" + + "MRIwEAYDVQQLDAlUb3NzIENlcnQxETAPBgNVBAMMCFRvc3MgQ0ExAgQBQL6iMA0GCWCGSAFlAwQC" + + "AQUAoGkwGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcNMjQwMjI2MTIy" + + "MTQzWjAvBgkqhkiG9w0BCQQxIgQgtFv6KxZyYKTYL0BTDjk64Y7QBNMHVQwwXxAOO9HsDV4wDQYJ" + + "KoZIhvcNAQEBBQAEggEAhnqCF4z8tKfszHoBL57oiN4+Odn1rN8ZOUdVnrlFbKG9NbQgysAx9otF" + + "tF5PGtICTOaRZmPe6VQjxE7QbJv2GGuQX3ezVolM0I3RsCrDkIVycgopCvjZlITq36gnZSCiyAsz" + + "lVET5mLOQQpsvUWCPaTUjeYghRqE8ItwNtuQoKwy78RLLdQQvF7Q+mJf3H9GSKPzOGl51Hrnc5jx" + + "ZVJ+1fNGqjOdgggyHiUvFtap8Jja6tEQtt6LGkPdCnNprJjTHOWu7yzn5jmACWUvyY+BgbCF0vJL" + + "jiJTlKe5W1NK8G3jBJe9pLDQlyFbsScBYr1AqQx+ChusfcQ+c9COGGFbKg=="; + + private final String expectedPemCertificate = + "-----BEGIN CERTIFICATE-----\n" + + "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" + + "\n-----END CERTIFICATE-----"; +}