다음으로 쿠키 세팅과 파라미터 세팅을 해야함
1. 인증서 로그인에 필요한 쿠키를 세팅
헤더 | 세팅 값 |
Content-Type | application/x-www-form-urlencoded; charset=UTF-8 |
Cookie | WMONID, TXPPsessionID |
https://www.hometax.go.kr/wqAction.do?actionId=ATXPPZXA001R01&screenId=UTXPPABA01
위의 API GET 요청을 통해 쿠키 정보를 가져와 WMONID, TXPPsessionID 정보를 세팅하고, 파마미터 세팅에 중요한 값인 Response에서 pkcEncSsn에 담긴 값을 가져옴
아래와 같이 Header 세팅을 해줌
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
headers.set(HttpHeaders.COOKIE, cookies);
2. 파라미터 세팅
파라미터 명 | 세팅 값 |
logSgnt | pkcEncSsn $ 공개키 인증서 일련번호 $ yyyyMMddHHmmss $ 전자 서명 값 |
cert | 공개키 PEM 값 |
randomEnc | 개인키에서 찾은 randomNum 값 |
pkcLoginYnImpv | Y (하드 코딩) |
pkcLgnClCd | 04 (하드코딩) |
위의 파라미터에서 설명이 필요한 부분은 logSgnt와 randomEnc 임
logSgnt 세팅에 필요한 값은 총 4개인데, 그 4개의 값을 $로 합치고 Base64로 인코딩 한 후 logSgnt로 담아 보냄
(1) pkcEncSsn은 1번의 요청의 Response pkcEncSsn의 값
(2) 공개키 인증서 일련번호 공개키의 SerialNumber 값
(3) yyyyMMddHHmmss 값
String currentDate = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
(4) pkcEncSsn으로 전자 서명한 값
알고리즘 SHA256withRSA 방식으로 개인키를 전자 서명한 값이 필요함
randomEnc는 개인키에서 randomNum을 찾아 세팅해 줘야 함
이를 위해선 개인키의 포맷을 확인하고 (한국 전자 인증의 경우 pkcs5PBES2) 그에 맞는 복호화를 통해서 randomNum 값을 찾음
// 복호화
public String decryptKey(String password) {
try {
byte[] decryptedKey = null;
byte[] encodedKey = FileUtils.readBinary(filePath);
EncryptedPrivateKeyInfo encryptedPrivateKeyInfo = null;
try (ByteArrayInputStream bIn = new ByteArrayInputStream(encodedKey);
ASN1InputStream aIn = new ASN1InputStream(bIn);) {
ASN1Sequence asn1Sequence = (ASN1Sequence) aIn.readObject();
AlgorithmIdentifier algId = AlgorithmIdentifier.getInstance(asn1Sequence.getObjectAt(0));
ASN1OctetString data = ASN1OctetString.getInstance(asn1Sequence.getObjectAt(1));
encryptedPrivateKeyInfo = new EncryptedPrivateKeyInfo(algId, data.getEncoded());
String privateKeyAlgName = encryptedPrivateKeyInfo.getEncryptionAlgorithm().getAlgorithm().getId();
if ("1.2.840.113549.1.5.13".equals(privateKeyAlgName)) { // pkcs5PBES2
// 개인키 암호화 정보에서 Salt, Iteration Count(IC), Initial Vector(IV)를 가져오는 로직
ASN1Sequence asn1Sequence2 = (ASN1Sequence) algId.getParameters();
ASN1Sequence asn1Sequence3 = (ASN1Sequence) asn1Sequence2.getObjectAt(0);
// PBKDF2 Key derivation algorithm
ASN1Sequence asn1Sequence33 = (ASN1Sequence) asn1Sequence3.getObjectAt(1);
// Salt 값
DEROctetString derOctetStringSalt = (DEROctetString) asn1Sequence33.getObjectAt(0);
// Iteration Count(IC)
ASN1Integer asn1IntegerIC = (ASN1Integer) asn1Sequence33.getObjectAt(1);
ASN1Sequence asn1Sequence4 = (ASN1Sequence) asn1Sequence2.getObjectAt(1);
// Initial Vector(IV)
DEROctetString derOctetStringIV = (DEROctetString) asn1Sequence4.getObjectAt(1);
// 복호화 키 생성
int keySize = 256;
PBEParametersGenerator generator = new PKCS5S2ParametersGenerator();
generator.init(
PBEParametersGenerator.PKCS5PasswordToBytes(password.toCharArray()),
derOctetStringSalt.getOctets(),
asn1IntegerIC.getValue().intValue());
byte[] iv = derOctetStringIV.getOctets();
KeyParameter key = (KeyParameter) generator.generateDerivedParameters(keySize);
// 복호화 수행
IvParameterSpec ivSpec = new IvParameterSpec(iv);
SecretKeySpec secKey = new SecretKeySpec(key.getKey(), "SEED");
Cipher cipher = Cipher.getInstance("SEED/CBC/PKCS5Padding", "BC");
cipher.init(Cipher.DECRYPT_MODE, secKey, ivSpec);
decryptedKey = cipher.doFinal(data.getOctets());
}
} catch (Exception e) {
...
}
...
}
복호화 후 id-randomNum를 찾기
아래 사이트에서 확인해보면 OID(오브젝트 고유 번호)
http://www.oid-info.com/cgi-bin/display?oid=1.2.410.200004.10.1.1.3&submit=Display&action=display
randomNum의 OID가 1.2.410.200004.10.1.1.3 인 걸 확인할 수 있음
이 값을 찾아서 세팅해주기
'프로그래밍 > JAVA' 카테고리의 다른 글
[JAVA] 홈택스 인증서 로그인 다시 구현(업데이트 된 부분 반영) (0) | 2024.11.27 |
---|---|
[Java] 홈택스 공동 인증서 로그인_3 (1) | 2024.09.24 |
[Java] 홈택스 공동 인증서 로그인_1 (0) | 2024.09.09 |
[Java Error] java.security.NoSuchProviderException: No such provider: BC (0) | 2024.09.05 |
[Spring Error] java.lang.IllegalArgumentException: Invalid character found in the request target... 에러 해결 방법 (0) | 2023.12.01 |