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분
선택한 인증서 파일에 암호가 있나요?
정성태

1  2  3  4  5  6  7  [8]  9  10  11  12  13  14  15  ...
NoWriterDateCnt.TitleFile(s)
13420정성태9/26/20235258스크립트: 57. 파이썬 - UnboundLocalError: cannot access local variable '...' where it is not associated with a value
13419정성태9/25/20233088스크립트: 56. 파이썬 - RuntimeError: dictionary changed size during iteration
13418정성태9/25/20233749닷넷: 2146. C# - ConcurrentDictionary 자료 구조의 동기화 방식
13417정성태9/19/20233332닷넷: 2145. C# - 제네릭의 형식 매개변수에 속한 (매개변수를 가진) 생성자를 호출하는 방법
13416정성태9/19/20233150오류 유형: 877. redis-py - MISCONF Redis is configured to save RDB snapshots, ...
13415정성태9/18/20233637닷넷: 2144. C# 12 - 컬렉션 식(Collection Expressions)
13414정성태9/16/20233387디버깅 기술: 193. Windbg - ThreadStatic 필드 값을 조사하는 방법
13413정성태9/14/20233576닷넷: 2143. C# - 시스템 Time Zone 변경 시 이벤트 알림을 받는 방법
13412정성태9/14/20236843닷넷: 2142. C# 12 - 인라인 배열(Inline Arrays) [1]
13411정성태9/12/20233356Windows: 252. 권한 상승 전/후 따로 관리되는 공유 네트워크 드라이브 정보
13410정성태9/11/20234855닷넷: 2141. C# 12 - Interceptor (컴파일 시에 메서드 호출 재작성) [1]
13409정성태9/8/20233701닷넷: 2140. C# - Win32 API를 이용한 모니터 전원 끄기
13408정성태9/5/20233711Windows: 251. 임의로 만든 EXE 파일을 포함한 ZIP 파일의 압축을 해제할 때 Windows Defender에 의해 삭제되는 경우
13407정성태9/4/20233469닷넷: 2139. C# - ParallelEnumerable을 이용한 IEnumerable에 대한 병렬 처리
13406정성태9/4/20233402VS.NET IDE: 186. Visual Studio Community 버전의 라이선스
13405정성태9/3/20233835닷넷: 2138. C# - async 메서드 호출 원칙
13404정성태8/29/20233356오류 유형: 876. Windows - 키보드의 등호(=, Equals sign) 키가 눌리지 않는 경우
13403정성태8/21/20233186오류 유형: 875. The following signatures couldn't be verified because the public key is not available: NO_PUBKEY EB3E94ADBE1229CF
13402정성태8/20/20233243닷넷: 2137. ILSpy의 nuget 라이브러리 버전 - ICSharpCode.Decompiler
13401정성태8/19/20233505닷넷: 2136. .NET 5+ 환경에서 P/Invoke의 성능을 높이기 위한 SuppressGCTransition 특성 [1]
13400정성태8/10/20233341오류 유형: 874. 파이썬 - pymssql을 윈도우 환경에서 설치 불가
13399정성태8/9/20233369닷넷: 2135. C# - 지역 변수로 이해하는 메서드 매개변수의 값/참조 전달
13398정성태8/3/20234122스크립트: 55. 파이썬 - pyodbc를 이용한 SQL Server 연결 사용법
13397정성태7/23/20233634닷넷: 2134. C# - 문자열 연결 시 string.Create를 이용한 GC 할당 최소화
13396정성태7/22/20233330스크립트: 54. 파이썬 pystack 소개 - 메모리 덤프로부터 콜 스택 열거
13395정성태7/20/20233306개발 환경 구성: 685. 로컬에서 개발 중인 ASP.NET Core/5+ 웹 사이트에 대해 localhost 이외의 호스트 이름으로 접근하는 방법
1  2  3  4  5  6  7  [8]  9  10  11  12  13  14  15  ...