Microsoft MVP성태의 닷넷 이야기
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
 
(연관된 글이 2개 있습니다.)

Visual Studio에서 pfx 파일로 서명한 경우, 암호는 어디에 저장될까?

다음과 같은 질문이 있는데요.

소스세이프 사용시 pfx 파일 빌드 실패
; https://www.sysnet.pe.kr/3/0/1067

재현을 하자면, 아래와 같이 프로젝트에 대해 서명할 때 사용하는 pfx 파일의 비밀번호를 설정하는 경우,

pfx_co_op_1.png

위의 프로젝트를 소스 제어(소스 세이프나 TFS 소스 컨트롤)에 포함시키고 다른 개발자가 다운로드 받아서 빌드하게 되면 pfx 때문에 아래와 같은 빌드 오류가 발생합니다.

pfx_co_op_2.png

Cannot import the following key file: test.pfx. The key file may be password protected. To correct this, try to import the certificate again or manually install the certificate to the Strong Name CSP with the following key container name: VS_KEY_5BA0AFAB813A51FF

Importing key file "test.pfx" was canceled.





질문의 답변에 제가 명시한 것처럼, 이런 경우 정말로 "암호가 있는 pfx" 파일로 서명해야 하는지를 스스로 질문을 던져야 합니다. 사실, 여기서 대부분의 개발자가 단순 snk 파일로 서명을 하는 것으로 방향을 바꾸어 문제를 해결할 수 있습니다.

하지만, 절대로 pfx를 이용하여 서명을 해야 한다고 하면 이제 좀 ^^ 괴로워집니다.

우선, pfx는 암호를 가지기 때문에 모든 개발자에게 암호를 알려주고 스스로 입력하라고 할 수 있습니다. 사실 이럴 거면 pfx를 사용한 의미가 많이 퇴색하지요. 따라서, 일반적으로는 관리자 한 명이 개발자들 PC에 일일이 돌아다니면서 pfx 암호를 직접 입력해 주어야 합니다.

암호 입력 방법은 어렵지 않습니다. "Cannot import the following key file" 빌드 오류가 발생하는 개발자 PC에 가서, 프로젝트 속성창을 띄운 다음 아래와 같이 pfx 파일을 다시 한번 '의도적으로' 선택해 주면,

pfx_co_op_3.png

이렇게 비밀번호를 묻는 창이 뜹니다.

pfx_co_op_4.png

한번 입력해 두면, 두번 다시 묻지 않기 때문에 개발자들은 이후 별다른 수고로움없이 빌드를 할 수 있습니다.

하지만, 마이크로소프트는 실제 서명에 사용되는 "인증 파일"을 여러 곳에 배포하는 것은 위험하다고 판단해서 별도로 "delay sign" 옵션을 두었습니다. 이에 대해서는 다음의 글을 참고하시기 바랍니다.

When to Delay Sign Assemblies
; https://www.c-sharpcorner.com/article/when-to-delay-sign-assemblies/

어쨌든, 2가지 방법 모두 관리적인 요소가 들어가므로 수고로움은 각오를 해야 합니다.




그런데, 문득... 개인적으로 궁금한 점이 생겼습니다. Visual Studio에서 pfx에 대해 암호를 한번 설정해 주면 이후로는 다시 묻지 않고 해당 pfx 파일로 빌드를 할 수 있게 해주는데... 그렇다면 그 정보가 어딘가 저장된다는 의미인데... 도대체 어디일까요? ^^

이에 대한 답은... ^^ 혹시 기억하실지 모르겠지만 예전에 이미 한번 언급한 적이 있었습니다.

인증서의 개인키를 담은 물리 파일 위치 알아내는 방법
; https://www.sysnet.pe.kr/2/0/865

pfx에 대해 설치를 한 것은 아니므로 '인증서 관리자'에는 나오지 않지만, Visual Studio는 pfx의 암호를 알아낸 뒤 개인키를 추출해서 별도의 폴더에 보관해 놓는데, 그것이 인증서의 개인키 파일 위치와 동일합니다.

실제로, Visual Studio에서 pfx의 암호를 입력하면 다음과 같은 2군데의 폴더에 새로운 파일이 생성됩니다.

C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys

%USERPROFILE%\AppData\Roaming\Microsoft\Crypto\RSA\AppData\Roaming\Microsoft\Crypto\RSA\[로그인 사용자 SID]
또는
%USERPROFILE%\AppData\Roaming\Microsoft\Crypto\RSA\[로그인 사용자 SID]

* "로그인 사용자 SID"는 "wmic useraccount where name='%USERNAME%' get sid" 명령어로 알아낼 수 있습니다.

아래에 보시면, 오늘 테스트한 날짜로 파일이 하나 생성된 것이 확인됩니다.

pfx_co_op_5.png

테스트를 해보니, "로그인 사용자 ID" 경로의 파일의 유무는 Visual Studio 빌드에 아무런 영향을 주지 않았지만, "C:\ProgramData" 하위 경로의 파일을 삭제한 경우에는 다시 빌드 오류가 발생하였습니다.




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

[연관 글]






[최초 등록일: ]
[최종 수정일: 6/20/2023]

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

비밀번호

댓글 작성자
 



2019-10-28 01시14분
[초보자] 서명에서 파일을 선택하면 암호입력하는 창이 나와야하는데 입력창이 나오지 않는 경우는 어떻게 해야할까요 ??
참고로 관리자권한실행하였습니다.
[guest]
2019-10-28 03시52분
선택한 인증서 파일에 암호가 있나요?
정성태

... 16  17  18  19  20  21  22  23  24  25  26  27  28  29  [30]  ...
NoWriterDateCnt.TitleFile(s)
12895정성태12/31/20219569.NET Framework: 1126. C# - snagit처럼 화면 캡처를 연속으로 수행해 동영상 제작 [1]파일 다운로드1
12894정성태12/30/20217533.NET Framework: 1125. C# - DefaultObjectPool<T>의 IDisposable 개체에 대한 풀링 문제 [3]파일 다운로드1
12893정성태12/27/20219160.NET Framework: 1124. C# - .NET Platform Extension의 ObjectPool<T> 사용법 소개파일 다운로드1
12892정성태12/26/20217130기타: 83. unsigned 형의 이전 값이 최댓값을 넘어 0을 지난 경우, 값의 차이를 계산하는 방법
12891정성태12/23/20217036스크립트: 38. 파이썬 - uwsgi의 --master 옵션
12890정성태12/23/20217174VC++: 152. Golang - (문자가 아닌) 바이트 위치를 반환하는 strings.IndexRune 함수
12889정성태12/22/20219629.NET Framework: 1123. C# - (SharpDX + DXGI) 화면 캡처한 이미지를 빠르게 JPG로 변환하는 방법파일 다운로드1
12888정성태12/21/20217701.NET Framework: 1122. C# - ImageCodecInfo 사용 시 System.Drawing.Image와 System.Drawing.Bitmap에 따른 Save 성능 차이파일 다운로드1
12887정성태12/21/20219848오류 유형: 777. OpenCVSharp4를 사용한 프로그램 실행 시 "The type initializer for 'OpenCvSharp.Internal.NativeMethods' threw an exception." 예외 발생
12886정성태12/20/20217652스크립트: 37. 파이썬 - uwsgi의 --enable-threads 옵션 [2]
12885정성태12/20/20217908오류 유형: 776. uwsgi-plugin-python3 환경에서 MySQLdb 사용 환경
12884정성태12/20/20216941개발 환경 구성: 620. Windows 10+에서 WMI root/Microsoft/Windows/WindowsUpdate 네임스페이스 제거
12883정성태12/19/20217864오류 유형: 775. uwsgi-plugin-python3 환경에서 "ModuleNotFoundError: No module named 'django'" 오류 발생
12882정성태12/18/20216962개발 환경 구성: 619. Windows Server에서 WSL을 위한 리눅스 배포본을 설치하는 방법
12881정성태12/17/20217419개발 환경 구성: 618. WSL Ubuntu 20.04에서 파이썬을 위한 uwsgi 설치 방법 (2)
12880정성태12/16/20217290VS.NET IDE: 170. Visual Studio에서 .NET Core/5+ 역어셈블 소스코드 확인하는 방법
12879정성태12/16/202113564오류 유형: 774. Windows Server 2022 + docker desktop 설치 시 WSL 2로 선택한 경우 "Failed to deploy distro docker-desktop to ..." 오류 발생
12878정성태12/15/20218583개발 환경 구성: 617. 윈도우 WSL 환경에서 같은 종류의 리눅스를 다중으로 설치하는 방법
12877정성태12/15/20217251스크립트: 36. 파이썬 - pymysql 기본 예제 코드
12876정성태12/14/20217101개발 환경 구성: 616. Custom Sources를 이용한 Azure Monitor Metric 만들기
12875정성태12/13/20216742스크립트: 35. python - time.sleep(...) 호출 시 hang이 걸리는 듯한 문제
12874정성태12/13/20216752오류 유형: 773. shell script 실행 시 "$'\r': command not found" 오류
12873정성태12/12/20217897오류 유형: 772. 리눅스 - PATH에 등록했는데도 "command not found"가 나온다면?
12872정성태12/12/20217733개발 환경 구성: 615. GoLang과 Python 빌드가 모두 가능한 docker 이미지 만들기
12871정성태12/12/20217774오류 유형: 771. docker: Error response from daemon: OCI runtime create failed
12870정성태12/9/20216341개발 환경 구성: 614. 파이썬 - PyPI 패키지 만들기 (4) package_data 옵션
... 16  17  18  19  20  21  22  23  24  25  26  27  28  29  [30]  ...