Microsoft MVP성태의 닷넷 이야기
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
 
(연관된 글이 1개 있습니다.)
(시리즈 글이 5개 있습니다.)
개발 환경 구성: 74. 인증서 관련(CER, PVK, SPC, PFX) 파일 만드는 방법
; https://www.sysnet.pe.kr/2/0/863

개발 환경 구성: 76. JKS(Java Key Store)에 저장된 인증서를 ActiveX 코드 서명에 사용하는 방법
; https://www.sysnet.pe.kr/2/0/882

개발 환경 구성: 147. .keystore 파일에 저장된 개인키 추출 방법과 인증기관으로부터 온 공개키를 합친 pfx 파일 만드는 방법
; https://www.sysnet.pe.kr/2/0/1262

개발 환경 구성: 549. ssh-keygen으로 생성한 PKCS#1 개인키/공개키 파일을 각각 PKCS8/PEM 형식으로 변환하는 방법
; https://www.sysnet.pe.kr/2/0/12560

.NET Framework: 1038. C# - 인증서 및 키 파일로부터 pfx/p12 파일을 생성하는 방법
; https://www.sysnet.pe.kr/2/0/12599




JKS(Java Key Store)에 저장된 인증서를 ActiveX 코드 서명에 사용하는 방법


이번에, DLL 파일에 대한 서명을 할 일이 있었습니다. 문제는, 이미 회사에서 인증서를 verisign으로부터 발급받았고, 애플릿 서명용으로 사용되고 있다는 것입니다.

그것이 왜 문제냐??? 라고 하시겠지만. ^^

기존에 있는 인증서 파일이 달랑 아래와 같은 PEM 형식의 텍스트 파일 뿐이라는 것입니다.

-----BEGIN CERTIFICATE-----
MIIB5jCCAU8CAQAwgaUxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJHQTELMAkGA1UE 
...[생략]...
bPZJpECkPLp4Xg==
-----END CERTIFICATE-----

위의 형식으로 된 CER 파일을 윈도우의 "인증서 관리자"에서 "가져오기" 시도를 하면 "개인키"가 없는 인증서로만 등록이 됩니다. 그렇다면, 키 파일을 찾아야 하는데... ^^; 그걸 가지고 있지 않은 것입니다. 게다가 JKS가 있는 서버는 윈도우가 아니고 리눅스 서버여서... ^^; 제가 접근할 수가 없는 상황!

암튼, 검색을 해보니 다음과 같은 글을 찾았습니다.

Convert the Java JKS key-store to Microsoft PFX format
; http://www.crionics.com/products/opensource/faq/signFree.htm

위의 글에 중간 쯤에 보면 "Convert Sun Java JKS Keystore to Microsoft PFX format"와 같은 글이 있는데 거기서 다음과 같은 명령어로 JKS로부터 PFX를 내려받는 방법을 알려주고 있습니다.

형식) JKS2PFX key-store-filename password alias java-class-path-for-ExportPrvKey.class
예제) JKS2PFX CodeSigning.jks mypassword CodeSigning C:\KeyTools

일단, 자바 담당하시는 분에게 위의 방법을 알려주고 pfx를 달라고 했는데요. ^^; 제시되었던 방법과는 달리 다음과 같은 3개의 파일이 나오더라고 합니다.

myprivate.key
privatekey.b64
privatekey.pkcs8

그중에서 privatekey.b64는 "BEGIN/END PRIVATE KEY" 내에 아무런 데이터가 없는 쓸모없는 파일이었고, myprivate.key는 "---BEGIN PRIVATE KEY---"과 "---END PRIVATE KEY---" 사이에 base64 인코딩된 PEM 형식의 개인키 저장 파일이고, privatekey.pkcs8은 동일한 개인키인데 PKCS #8 형식으로 바이너리 파일이었습니다. 참고로, myprivate.key는 다음과 같은 출력 결과였습니다.

---BEGIN PRIVATE KEY---
MIIB5jCCAU8CAQAwgaUxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJHQTELMAkGA1UE 
...[생략]...
bPZJpECkPLp4Xg==
---END PRIVATE KEY---

흠... PFX로 바로 나오진 않았지만, 어쨌든 base64 인코딩된 CER 인증서 파일이 있고, 개인키 파일이 있으니 잘 조립해보면 개인키를 가진 인증서 파일로 변환이 가능할 것 같은데요.

여기서 다시 검색을 해보았습니다.

How to transform your certificate to a pvk + spc combination.
; http://www.globalsign.com/support/code-signing/pvk-spc.html

위의 글에 보면 아래와 같이 PEM 형식의 개인키 파일을 PVK 파일로 변환하는 것을 볼 수 있습니다.,

Download the pvk transform utility. This file can be found at 
http://www.globalsign.com/support/code-signing/PVK.zip 

pvk -in <pem-key-file> -topvk -strong -out <pvk-file>

그래서 실행해 보니 다음과 같은 결과가 나옵니다.

C:\temp>pvk -in myprivate.key -topvk -strong -out myprivate.pvk
Error reading key
6408:error:0906D06C:PEM routines:PEM_read_bio:no start line:.\crypto\pem\pem_lib
.c:632:Expecting: ANY PRIVATE KEY

헉~~~ 당황스럽습니다. ^^; 이 문제 때문에 엄청나게 고생을 했는데요. 원인은? ^^;

[기존 형식]
---BEGIN PRIVATE KEY---
MIIB5jCCAU8CAQAwgaUxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJHQTELMAkGA1UE 
...[생략]...
bPZJpECkPLp4Xg==
---END PRIVATE KEY---

==>

[변경된 형식]
-----BEGIN PRIVATE KEY-----
MIIB5jCCAU8CAQAwgaUxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJHQTELMAkGA1UE 
...[생략]...
bPZJpECkPLp4Xg==
-----END PRIVATE KEY-----

위에서 보는 것처럼, BEGIN/END 구분자의 "-" 문자가 3개였던 것을 5개로 했어야 한다는 것입니다. (실수로 찾아낸 것입니다. ^^;)

그래서 다시 실행해 보면, 다음과 같이 정상적으로 pvk 파일을 생성해 냅니다.

C:\temp>pvk -in myprivate.key -topvk -strong -out myprivate.pvk
Enter Password:
Verifying - Enter Password:

자... 일단 이렇게 해서 PVK와 CER 파일이 있으니 "인증서 관련(CER, PVK, SPC, PFX) 파일 만드는 방법"에서 설명한 대로 다음과 같이 명령어를 주면 PFX 파일이 나오게 됩니다.

cert2spc mycert.cer mycert.spc
pvkimprt -pfx mycert.spc myprivate.pvk

이 정도면 해결이 되었죠. ^^

시간을 내서 좀 더 검색을 해보니, openssl이라는 공개 도구를 찾았습니다.

Download OpenSSL for windows
; http://www.deanlee.cn/programming/openssl-for-windows/

위의 툴을 이용하면 PEM 형식이었던 myprivate.key와 CER 파일만을 가지고 곧바로 PFX 파일로 만드는 것이 가능했습니다.

C:\temp>openssl pkcs12 -export -in mycert.cer -inkey myprivate.key -out my.pfx
Loading 'screen' into random state - done
Enter Export Password:
Verifying - Enter Export Password:
unable to write 'random state'

마지막 부분에 "unable to write 'random state'"라고 안 좋은 메시지가 있긴 하지만, "인증서 관리자"로 해당 pfx 파일을 가져와서 등록하는 과정이 정상적으로 진행되었습니다.

참고로, 위에서 "---" 3개의 구분 문자만 있는 상황에서 openssl을 실행하면 다음과 같은 식으로 오류가 발생합니다.

C:\temp>openssl pkcs12 -export -in mycert.cer -inkey myprivate.key -out my.pfx
Loading 'screen' into random state - done
unable to load private key
unable to write 'random state'

끝!!!



[이 토픽에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]

[연관 글]






[최초 등록일: ]
[최종 수정일: 2/23/2023]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 



2015-03-09 05시43분
정성태

[1]  2  3  4  5  6  7  8  9  10  11  12  13  14  15  ...
NoWriterDateCnt.TitleFile(s)
13981정성태8/1/2025170오류 유형: 971. CentOS 7에서 yum 사용 시 "Could not resolve host: mirrorlist.centos.org; Unknown error"
13980정성태7/31/2025244Linux: 119. eBPF - BPF_PROG_TYPE_CGROUP_SOCK 유형에서 정상 동작하지 않는 BPF_CORE_READ (2)
13979정성태7/30/2025272Linux: 118. eBPF - BPF_PROG_TYPE_CGROUP_SOCK 유형에서 정상 동작하지 않는 BPF_CORE_READ
13978정성태7/29/2025365오류 유형: 970. 파일 복사 시 "Data error (cyclic redundancy check). (0x80070017)" 에러
13977정성태7/28/2025484닷넷: 2349. C# 14 - (5) 문자열 리터럴을 utf-8 인코딩으로 저장파일 다운로드1
13976정성태7/25/2025719닷넷: 2348. C# - 카카오 카나나 모델 + Microsoft.ML.OnnxRuntimeGenAI 예제파일 다운로드1
13975정성태7/23/2025845닷넷: 2347. C# 14 - (4) 형식 인자가 없는 제네릭 타입의 nameof 지원파일 다운로드1
13974정성태7/22/20251117닷넷: 2346. C# 14 - (3) Span 타입과 배열 간의 암시적 형변환파일 다운로드1
13973정성태7/21/20251023닷넷: 2345. C# - 배열 및 Span의 공변성파일 다운로드1
13972정성태7/21/20251290닷넷: 2344. C#의 Identity conversion 의미파일 다운로드1
13971정성태7/17/20251428닷넷: 2343. C# 14 - (2) 속성 구문에서 문맥 키워드로 추가되는 field 예약어파일 다운로드1
13970정성태7/17/20251387닷넷: 2342. C# 14 - (1) (예약)
13969정성태7/17/20251434닷넷: 2341. snap으로 설치한 .NET 리눅스 실행 환경
13968정성태7/16/20251314오류 유형: 969. lddtree - TypeError: 'type' object is not subscriptable
13967정성태7/16/20251835오류 유형: 968. snap으로 설치한 "dotnet run" 실행 시 "undefined symbol: _dl_audit_symbind_alt, version GLIBC_PRIVATE" 오류
13966정성태7/15/20252380디버깅 기술: 223. WinDbg - .kframes 명령어
13965정성태7/11/20251661오류 유형: 967. 디버깅 모드로 실행 시 "Could not find file 'C:\Program Files\IIS Express\Oracle.DataAccess.Common.Configuration.Section.xsd'" 예외
13964정성태7/10/20252331닷넷: 2340. C# - Win32 Multimedia Timer 주기파일 다운로드1
13963정성태7/8/20251876VS.NET IDE: 202. Visual Studio 2022 + Copilot 기본 사용법
13962정성태7/7/20251896스크립트: 79. 파이썬 - onnxruntime_genai에서 지원하지 않는 모델 사용
13961정성태7/5/20251600디버깅 기술: 222. WinDbg 분석 사례 - IISreset 시점에 w3wp.exe의 crash 발생
13960정성태7/3/20252786개발 환경 구성: 752. ProcDump - C/C++ 예외 코드 필터를 지정한 덤프 생성 [2]
13959정성태6/25/20251813오류 유형: 966. Ubuntu - ping: connect: Network is unreachable
13958정성태6/21/20252470닷넷: 2339. C# - Phi-4-multimodal 모델의 GPU 가속 방법 (ORT 사용)파일 다운로드1
13957정성태6/20/20252915닷넷: 2338. C# / Foundry Local - Phi-4-multimodal 모델을 사용하는 방법 [1]
[1]  2  3  4  5  6  7  8  9  10  11  12  13  14  15  ...