2009-04-28 11 views
5

sn.exe 유틸리티 및 this question의 설명에서 강력한 이름으로 서명 된 모든 어셈블리에 공개 키 복사본이 추가 된 것을 볼 수 있습니다. 어셈블리 바이너리가 변경되지 않았 음을 확인하기에 충분합니다..snk 파일에서 공개 키를 게시해야합니까?

그러나 주어진 어셈블리가 실제로 주어진 키 쌍으로 서명되었고 주어진 회사에서 컴파일되었는지 어떻게 확인합니까? 누구나 자신의 키 쌍을 만들고, 일부 어셈블리를 만들고, 키 쌍으로 서명 할 수 있습니다. 어셈블리 출처를 확인하려는 사람들이 공개 키를 비교할 수 있도록 공용 키를 게시해야합니까? 그렇다면 가장 좋은 방법은 무엇입니까?

답변

5

는 해시 및 클라이언트의 응용 프로그램 내부의 참조와 함께 토큰으로 저장되기 때문에 아니, 당신은 어셈블리의 외부에 공개 키를 게시 할 필요가 없습니다 :이 보장하는 방법을 제공

AssemblyName, Version=1.0.0.0, Culture=neutral, PublicKeyToken=bcd6707151635d07" 

이후의 모든 버전의 어셈블리는 동일한 키 쌍에 대해 컴파일되므로 동일한 게시자에서 컴파일됩니다.

자세한 내용 이 정보를 가지고있는은 다른 소스가 다른 질문에서 멈추는 것을 막아 내 다른 답변에서 찾을 수 있습니다.

3

저는 항상 코드에 대한 업그레이드가 신뢰할 수있는 소스에서 제공되는지 확인하기 위해 런타임에 어셈블리를 서명하는 목적을 이해했습니다. 효과적으로 그들은 이런 종류의 시나리오를 피하려고합니다 :

나는 회사 A에서 암호화 라이브러리를 구입하고, 곧이어 회사 B는 이메일 세부 사항을 얻고 나에게 주요 보안 버그 인 척하는 어셈블리로 무료 업그레이드를 보냅니다 회사 B의 서버에 암호화하려는 모든 데이터를 보내는 숨겨진 방법을 코드에 실제로 삽입 할 때 회사 A에서 수정하십시오. 내가 멍청하다고 가정하고 맹목적으로이 새로운 dll을 내 응용 프로그램의 bin 디렉토리에 추가합니다. 이전 버전과 동일한 개인 키로 서명되지 않았다는 사실은 런타임에 예외가 발생하여 데이터가 보호됩니다.

공개 키가 특정 공급 업체에서 제공된다는 보장이 없으므로 어셈블리 외부에서 공개 키를 게시 할 필요는 없습니다. 모든 후속 버전은 다음 위치에서 가져온 것입니다. 첫번째.

Wikipedia은 많이 똑같은 말을합니다 (단어 수가 현저히 적음).


편집

내가 먼저 명확히해야 할 것은 공개 키와 개인 키의 쌍 고유한지 생각 ...이 명확하게하기위한 시도에서 자세한 정보를 추가 할 수 있습니다. 즉, 공개 키를 알고 있으면 동일한 해시 검사를 통과하는 방식으로 어셈블리를 다시 작성하는 데 필요한 정보가 충분하지 않다는 것을 의미합니다.

그래서 사용자 A는 자신의 응용 프로그램 bin 폴더에있는 A의 암호화 라이브러리를 사용하고 있습니다. 그는 다음과 같이 DLL을 참조하는이 작업을 수행하려면 :

Encryption, Version=1.0.0.0, Culture=neutral, PublicKeyToken=bcd6707151635d07" 

공개 키의 목적은 내가 한 번에 하나씩 처리 할 수 ​​있습니다하는 three benefits을 우리에게 제공하는 것입니다.

첫째, 어셈블리에 대한 고유 한 이름을 제공합니다. 이렇게하면 별도의 보안을 제공하지 않지만 두 가지 회사가 Encyption 버전 1.0.0.0이라는 두 가지 라이브러리를 릴리스 할 수있는 C 스타일 dll Hell을 중단하고 차별화 할 방법이 없기 때문에 동일한 디렉토리에 저장하십시오.

둘째, 원래 게시글에서 설명한 시나리오를 방지합니다. 회사 B가 버전 1.0.0.0이고 동일한 공개 키를 가진 다른 버전의 암호화 라이브러리를 만들 수 없습니다 (따라서 전체 이름이 일치하고 A 사 대신 코드를 호출 할 수 있음). 공개 키가 일치하면 개인 키가 일치해야하기 때문에 (각 이 고유하기 때문에)이 작업을 수행 할 수 없습니다. 개인 키를 얻을 수있는 유일한 방법은 회사 A의 보안을 손상시키는 것입니다.

마지막으로 파일의 무결성을 보장합니다 (손상 또는 악의적 인 코드 삽입을 통해 변경됨). dll은 런타임시 (개인용이고 응용 프로그램의 bin 폴더에있을 때) 해시되거나 공개 키를 사용하여 설치 시간 (GAC에 넣을 때)을 해시하고 해당 해시를 비공개 사용자가 해킹 한 해시와 비교합니다 키를 누르고 어셈블리에 저장하십시오. This page에는 몇 가지 다이어그램과 자세한 내용이 있습니다. 이 해시를 가짜로 만드는 유일한 방법은 개인 키를 아는 것입니다.

위에서 설명한 특정 시나리오를 다루기 위해 나는 사용자 B에게 암호화 dll의 악성 버전을 제공하려고 시도하고 있습니다. 내 첫 번째 시도는 단순히 암호화 및 버전 1.0.0.0 이름 가진 내 자신의 DLL을 만들고 내 자신의 키 쌍으로 서명 할 수 있습니다. 불행히도 사용자 Z의 응용 프로그램에서 참조 코드를 변경할 수 없으므로 성명 확인에 실패하고로드되지 않습니다. "좋아,"나는 내 콧수염을 돌면서 "나는 회사의 A와 일치하도록 의회의 공개 키를 간단히 바꿀 것"이라고 말한다. 이 작업을 완료하면 이름 확인이 통과되지만 사용자 Z의 앱이 공개 키 (회사)의 (회사 B의 개인 키로 암호화 된) 어셈블리에 저장된 해시를 해독 할 수 없으므로 해시 검사가 실패합니다. A 's)가 제공되었습니다. 따라서 회사 B가 회사 A가 가장하는 라이브러리를 만드는 유일한 방법은 회사 A의 개인 키를 아는 것입니다. 이러한 보안 검사는 회사 A가 공개 키를 다른 곳에서는 게시하지 않았지만 원래 릴리스에서 공개하는 것에 의존합니다.

원래의 어셈블리가 A 회사의 것이고 Verisign 또는 Microsoft의 Authenticode 서비스와 같은 다른 시스템에서 처리된다는 것을 보장하지는 않습니다 (보장하지도 않음). 어셈블리를 참조한 후에는 A 회사 만 해당 코드를 변경할 수 있습니다.

+0

완전히 명확하지 않아 링크 된 기사에서 명시 적으로 언급하지 않았습니다.이 모든 작업을 수행하려면 런타임에서 각 어셈블리의 해시를 캐시하고 어셈블리를로드 할 때이를 확인해야합니다. 정말 그럴까요? – sharptooth

+1

Jeffery Richter의 "CLR via C#"에 따르면 어셈블리가 GAC에 없을 때 수행됩니다. "강력한 이름의 어셈블리를 GAC 이외의 위치에서로드하면 CLR은 어셈블리를로드 할 때 해시 값을 비교합니다. 즉, 응용 프로그램을 실행하고 어셈블리를로드 할 때마다 파일의 해시가 수행됩니다 이 성능 저하는 어셈블리 파일의 내용이 변경되지 않았다는 점에서 절충점입니다. " –

+0

또한 "C# via CLR"(이 책에서 추천하는 책)의 인용문을 추가 할 것입니다. "중요 :이 메커니즘은 파일의 내용이 변경되지 않았 음을 보장합니다. 게시자가 공개 키를 생산하고 게시자의 개인 키가 절대로 손상되지 않았 음이 확실하다는 점을 절대적으로 긍정적으로 밝히지 않는 한 게시자를 밝히십시오. " 따라서 공개 키를 어셈블리와 별도로 게시하더라도 여전히 게시자를 확인할 수있는 것은 아닙니다. –

2
  1. 일부 타사 인증서 제공 업체 (예 : VeriSign)에서 인증서를 구입할 수 있습니다 (Code Signing At Verisign).
  2. 코드에 서명하기 위해 회사 이름, URL 등이있는 지정된 인증서를 사용합니다.
  3. 앱을 다운로드하고 앱이 서명 한 인증서 목록을 확인합니다.
  4. 귀하의 인증서를 사용하여 VeriSign으로 돌아가서 인증서가 실제로 MyCompany, LLC에게 발행되었는지 확인하십시오.
  5. 인증서를 발급하는 데 사용 된 인증서를 확인하고 VeriSign이 그 중 하나임을 확인합니다 (Windows에는 신뢰할 수있는 인증서가 거의 설치되지 않았습니다).

요약 :
에만 해당 코드를 확인하지가 함께 만지작 거렸다되지 않았지만, 또한 당신이 신뢰하는 자에 의해 발급 된 인증서로 서명했다.

+1

나는이 모든 것을 알고 있으며 이것은 우리가 실제로하는 것입니다. 하지만 이것은 강력한 이름과 .snk 파일과는 아무 상관이 없습니다. – sharptooth

+0

그 일을한지 얼마되지 않았습니다. 그러나 IIRK는 인증서의 공개 키를 사용하여 코드에 서명합니다. 나는. .snk는 makecert.exe를 사용하여 VeriSign에서 가져온 .cer 파일에서 생성/내보내기됩니다. 서명 코드는 실제로 1) 코드가 훼손되지 않도록 (보호) 2) 게시자를 인증합니다. –

관련 문제