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분
정성태

... 76  77  78  79  80  [81]  82  83  84  85  86  87  88  89  90  ...
NoWriterDateCnt.TitleFile(s)
11911정성태5/23/201917492VS.NET IDE: 136. Visual Studio 2019 - 리눅스 C/C++ 프로젝트에 인텔리센스가 동작하지 않는 경우
11910정성태5/23/201927123Math: 50. C# - MathNet.Numerics의 Matrix(행렬) 연산 [1]파일 다운로드1
11909정성태5/22/201921197.NET Framework: 837. C# - PLplot 사용 예제 [1]파일 다운로드1
11908정성태5/22/201919938.NET Framework: 836. C# - Python range 함수 구현파일 다운로드1
11907정성태5/22/201916672오류 유형: 541. msbuild - MSB4024 The imported project file "...targets" could not be loaded
11906정성태5/21/201916918.NET Framework: 835. .NET Core/C# - 리눅스 syslog에 로그 남기는 방법
11905정성태5/21/201917405.NET Framework: 834. C# - 폴더 경로 문자열에서 "..", "." 표기를 고려한 최종 문자열을 얻는 방법 - 두 번째 이야기
11904정성태5/21/201925821.NET Framework: 833. C# - Open Hardware Monitor를 이용한 CPU 온도 정보 [1]파일 다운로드1
11903정성태5/21/201919639오류 유형: 540. .NET Core - System.PlatformNotSupportedException: The named version of this synchronization primitive is not supported on this platform.
11902정성태5/21/201917766오류 유형: 539. mstest 실행 시 "The directory name is invalid." 오류 발생
11901정성태5/21/201919697오류 유형: 538. msbuild 오류 - Could not find a part of the path '%LOCALAPPDATA%\Temp\2\.NETFramework,Version=v4.0.AssemblyAttributes.cs'
11900정성태5/18/201918680오류 유형: 537. "sfc /scannow" 실행 중 시스템이 부팅되는 현상
11899정성태5/17/201919490Linux: 9. Linux에서 윈도우의 OutputDebugString 대신 사용할 수 있는 syslog [1]
11898정성태5/16/201921295VC++: 130. C++ string의 c_str과 data 함수의 차이점 [3]
11897정성태5/16/201928263오류 유형: 536. Visual Studio - "Developer Pack"을 설치했는데도 "대상 프레임워크" 목록에 나오지 않는 경우 [2]
11896정성태5/15/201923226개발 환경 구성: 440. C#, C++ - double의 Infinity, NaN 표현 방식파일 다운로드1
11895정성태5/12/201921043.NET Framework: 832. ML.NET Model Builder - 회귀(Regression), 다중 분류(Multi-class classification) 예제파일 다운로드1
11894정성태5/10/201922794VS.NET IDE: 135. Visual Studio - ML.NET Model Builder 소개 [5]
11893정성태5/10/201919669오류 유형: 535. C# 6.0 이상의 문법을 컴파일 시 오류가 발생한다면?
11892정성태5/10/201919540웹: 38. HTTP Cookie의 expires 시간 형식(RFC7231)
11891정성태5/9/201922634.NET Framework: 831. (번역글) .NET Internals Cookbook Part 12 - Memory structure, attributes, handles
11890정성태5/8/201917752개발 환경 구성: 439. "Visual Studio Enterprise is required to execute the test." 메시지와 관련된 코드 기록
11889정성태5/8/201918366개발 환경 구성: 438. mstest, QTAgent의 로그 파일 설정 방법
11888정성태5/8/201935749.NET Framework: 830. C# - 비동기 호출을 취소하는 CancellationToken의 간단한 예제 코드 [1]파일 다운로드1
11887정성태5/8/201921411.NET Framework: 829. C# - yield 문을 사용할 수 있는 메서드의 조건
11886정성태5/7/201919211오류 유형: 534. mstest.exe 실행 시 "Visual Studio Enterprise is required to execute the test." 오류 [2]
... 76  77  78  79  80  [81]  82  83  84  85  86  87  88  89  90  ...