System.Security.Cryptography.Xml.SignedXml 클래스

이 문서에서는 이 API에 대한 참조 설명서에 대한 추가 설명서를 제공합니다.

SignedXml 클래스는 XMLDSIG(XML 디지털 서명)라고도 하는 W3C(World Wide Web 컨소시엄) XML 서명 구문 및 처리 사양의 .NET 구현입니다. XMLDSIG는 XML 문서 또는 URI(Uniform Resource Identifier)에서 주소 지정이 가능한 다른 데이터의 전부 또는 일부를 서명하고 확인하는 표준 기반의 상호 운용 가능한 방법입니다.

사용 된 SignedXml 표준 방식으로 서명 된 애플리케이션 또는 조직 간의 XML 데이터를 공유 해야 할 경우에 클래스입니다. 이 클래스를 사용하여 서명된 모든 데이터는 XMLDSIG에 대한 W3C 사양의 모든 준수 구현을 통해 확인할 수 있습니다.

SignedXml 클래스를 사용하면 다음과 같은 세 가지 종류의 XML 디지털 서명을 만들 수 있습니다.

서명 유형 설명
봉투 서명 서명은 서명되는 XML 요소 내에 포함됩니다.
서명 둘러싸기 서명된 XML은 요소 내에 <Signature> 포함됩니다.
내부 분리된 서명 서명 및 서명된 XML은 동일한 문서에 있지만 두 요소 모두 다른 요소를 포함하지 않습니다.

데이터와 서명이 별도의 XML 문서에 있는 경우 외부 분리된 서명이라는 네 번째 종류의 서명도 있습니다. 외부 분리된 서명은 클래스에서 SignedXml 지원되지 않습니다.

XML 서명의 구조

XMLDSIG는 XML 문서의 디지털 서명 또는 URI에서 주소 지정 가능한 기타 데이터를 포함하는 요소를 만듭니다 <Signature> . <Signature> 이 요소는 필요에 따라 서명을 확인할 키와 서명에 사용된 암호화 알고리즘에 대한 정보를 포함할 수 있습니다. 기본 구조는 다음과 같습니다.

<Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
    <SignedInfo>
      <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
      <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
      <Reference URI="">
        <Transforms>
          <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
        </Transforms>
        <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
        <DigestValue>Base64EncodedValue==</DigestValue>
      </Reference>
    </SignedInfo>
    <SignatureValue>AnotherBase64EncodedValue===</SignatureValue>
</Signature>

이 구조체의 기본 부분은 다음과 같습니다.

  • <CanonicalizationMethod> 요소

    서명 유효성 검사를 위해 XML/텍스트에서 바이트로 요소를 다시 쓰는 Signature 규칙을 지정합니다. .NET의 기본값은 http://www.w3.org/TR/2001/REC-xml-c14n-20010315신뢰할 수 있는 알고리즘을 식별하는 것입니다. 이 요소는 속성으로 SignedInfo.CanonicalizationMethod 표시됩니다.

  • <SignatureMethod> 요소

    에서 값을 <SignatureValue>생성하기 <Signature> 위해 요소에 적용된 서명 생성 및 유효성 검사에 사용되는 알고리즘을 지정합니다. 이전 예제에서 값 http://www.w3.org/2000/09/xmldsig#rsa-sha1 은 RSA PKCS1 SHA-1 서명을 식별합니다. SHA-1의 충돌 문제로 인해 Microsoft는 SHA-256 이상에 기반한 보안 모델을 권장합니다. 이 요소는 속성으로 SignatureMethod 표시됩니다.

  • <SignatureValue> 요소

    요소에 대한 암호화 서명을 지정합니다 <Signature> . 이 서명이 확인되지 않으면 블록의 <Signature> 일부가 변조되었으며 문서가 잘못된 것으로 간주됩니다. 값이 <CanonicalizationMethod> 신뢰할 수 있는 한 이 값은 변조에 대한 강한 저항력이 있습니다. 이 요소는 속성으로 SignatureValue 표시됩니다.

  • URI 요소의 특성입니다<Reference>.

    URI 참조를 사용하여 데이터 개체를 지정합니다. 이 특성은 속성으로 Reference.Uri 표시됩니다.

    • 특성을 지정 URI 하지 않습니다. 즉, 속성을 nullReference.Uri로 설정하면 수신 애플리케이션이 개체의 ID를 알아야 합니다. 대부분의 경우 URI는 null 예외가 throw됩니다. 사용 하지 마십시오는 null URI, 애플리케이션에 필요한 프로토콜을 사용 하 여 상호 운용 하지 않는 한 합니다.

    • URI 특성을 빈 문자열로 설정하면 문서의 루트 요소가 봉투 서명 형식으로 서명되고 있음을 나타냅니다.

    • 특성 값 URI 이 #으로 시작하는 경우 이 값은 현재 문서의 요소로 확인되어야 합니다. 이 양식은 지원되는 서명 형식(봉투형 서명, 둘러싸는 서명 또는 내부 분리된 서명)과 함께 사용할 수 있습니다.

    • 다른 항목은 외부 리소스 분리 서명으로 간주되며 클래스에서 SignedXml 지원되지 않습니다.

  • <Transforms> 요소

    서명자가 다이제스트된 데이터 개체를 가져온 방법을 설명하는 정렬된 요소 목록을 <Transform> 포함합니다. 변환 알고리즘은 정식화 메서드와 비슷하지만 요소를 다시 작성하는 <Signature> 대신 요소의 <Reference> 특성으로 URI 식별된 콘텐츠를 다시 작성합니다. 요소는 <Transforms> 클래스로 TransformChain 표시됩니다.

    • 각 변환 알고리즘은 XML(XPath 노드 집합) 또는 바이트를 입력으로 사용하는 것으로 정의됩니다. 현재 데이터의 형식이 변환 입력 요구 사항과 다른 경우 변환 규칙이 적용됩니다.

    • 각 변환 알고리즘은 XML 또는 바이트를 출력으로 생성하는 것으로 정의됩니다.

    • 마지막 변환 알고리즘의 출력이 바이트로 정의되지 않았거나 변환이 지정되지 않은 경우 정식화 메서드 는 암시적 변환으로 사용됩니다(요소에 <CanonicalizationMethod> 다른 알고리즘이 지정된 경우에도).

    • 변환 알고리즘의 http://www.w3.org/2000/09/xmldsig#enveloped-signature 값은 문서에서 요소를 제거하는 <Signature> 것으로 해석되는 규칙을 인코딩합니다. 그렇지 않으면 봉투형 서명의 검증 도구는 서명을 포함하여 문서를 소화하지만 서명자는 서명이 적용되기 전에 문서를 다이제스트하여 다른 답변으로 이어집니다.

  • <DigestMethod> 요소

    요소의 특성으로 식별되는 변환된 콘텐츠에 적용할 다이제스트(암호화 해시) 메서드를 URI 식별합니다 <Reference> . 속성으로 Reference.DigestMethod 표시됩니다.

정식화 방법 선택

다른 값을 사용해야 하는 사양과 상호 운용하지 않는 한 값이 있는 XML-C14N 1.0 알고리즘 http://www.w3.org/TR/2001/REC-xml-c14n-20010315인 기본 .NET 정식화 메서드를 사용하는 것이 좋습니다. XML-C14N 1.0 알고리즘은 특히 적용할 암시적 최종 변환이므로 XMLDSIG의 모든 구현에서 지원되어야 합니다.

주석 보존을 지원하는 정식화 알고리즘 버전이 있습니다. 주석 보존 정식화 메서드는 "표시되는 기호" 원칙을 위반하므로 권장되지 않습니다. 즉, 요소의 주석 <Signature> 은 서명이 수행되는 방식에 대한 처리 논리를 변경하지 않고 서명 값만 변경합니다. 약한 서명 알고리즘과 결합하면 주석을 포함할 수 있도록 하면 공격자가 해시 충돌을 강제로 적용할 수 있는 자유가 없어 변조된 문서가 합법적인 것처럼 보입니다. .NET Framework에서는 기본적으로 기본 제공 정식 변환기만 지원됩니다. 추가 또는 사용자 지정 정식 변환기를 지원하려면 속성을 참조 SafeCanonicalizationMethods 하세요. 문서에서 속성이 나타내는 컬렉션에 없는 정식화 메서드를 SafeCanonicalizationMethods 사용하는 경우 메서드가 CheckSignature 반환 false됩니다.

참고 항목

매우 안전한 애플리케이션에서 사용 하는 서명자를 예상 하지 않습니다 모든 값을 제거할 수는 SafeCanonicalizationMethods 컬렉션입니다.

참조 값은 변조로부터 안전합니까?

예, 값은 <Reference> 변조로부터 안전합니다. .NET은 <SignatureValue> 값 및 관련 변환을 <Reference> 처리하기 전에 계산을 확인하고 잠재적으로 악의적인 처리 지침을 방지하기 위해 일찍 중단됩니다.

서명할 요소 선택

가능한 경우 특성에 "" URI 값을 사용하거나 속성을 빈 문자열로 설정하는 Uri 것이 좋습니다. 즉, 전체 문서가 다이제스트 계산에 고려됩니다. 즉, 전체 문서가 변조로부터 보호됩니다.

ID 특성이 "foo"인 요소를 참조하는 #foo 같은 앵커 형식의 값을 보는 URI 것은 매우 일반적입니다. 아쉽게도 컨텍스트가 아닌 대상 요소의 콘텐츠만 포함하므로 쉽게 변조할 수 있습니다. 이러한 구분을 악용하는 것을 XSW(XML 서명 래핑)라고 합니다.

애플리케이션에서 (있는 경우에 일반적인 다루는 XML) 주석 수 의미 체계를 사용 해야 합니다 "#xpointer(/)" 대신 "", "#foo" 대신 "#xpointer(id('foo'))" 하 고 있습니다. #xpointer 버전은 주석을 포함하는 것으로 해석되지만 짧은 이름 형식은 주석을 제외합니다.

부분적으로만 보호되는 문서를 수락해야 하며 서명이 보호한 것과 동일한 콘텐츠를 읽고 있는지 확인하려면 이 메서드를 GetIdElement 사용합니다.

KeyInfo 요소에 대한 보안 고려 사항

서명의 유효성을 검사하는 키가 포함된 선택적 <KeyInfo> 요소(즉, KeyInfo 속성)의 데이터는 신뢰할 수 없습니다.

특히 값이 KeyInfo 맨손 RSA, DSA 또는 ECDSA 공개 키를 나타내는 경우 서명이 유효하다고 보고하는 메서드에도 불구하고 CheckSignature 문서가 변조되었을 수 있습니다. 이는 변조를 수행하는 엔터티가 새 키를 생성하고 변조된 문서에 해당 새 키로 다시 서명해야 하기 때문에 발생할 수 있습니다. 따라서 공개 키가 예상 값을 확인 하는 애플리케이션, 하지 않는 한 변조 된 것 처럼 문서 처리 합니다. 이렇게 하려면 애플리케이션이 문서 내에 포함 된 공개 키를 검사 하 고 문서 컨텍스트에 대 한 알려진된 값의 목록을 확인 합니다. 예를 들어 문서를 알려진 사용자가 발급한 것으로 인식할 수 있는 경우 해당 사용자가 사용하는 알려진 키 목록에 대해 키를 검사.

메서드를 사용하는 CheckSignature 대신 메서드를 사용하여 문서를 처리한 CheckSignatureReturningKey 후 키를 확인할 수도 있습니다. 그러나 최적의 보안을 위해 키를 미리 확인해야 합니다.

또는 요소에 있는 내용을 읽는 대신 사용자의 등록된 공개 키를 시도하는 것이 <KeyInfo> 좋습니다.

X509Data 요소에 대한 보안 고려 사항

선택적 <X509Data> 요소는 요소의 <KeyInfo> 자식이며 X509 인증서에 대한 하나 이상의 X509 인증서 또는 식별자를 포함합니다. 요소의 <X509Data> 데이터도 본질적으로 신뢰할 수 없어야 합니다.

포함된 <X509Data> 요소를 사용하여 문서를 확인할 때 .NET은 공개 키를 사용하여 문서 서명의 유효성을 검사할 수 있는 X509 인증서로만 데이터가 확인되는지 확인합니다. 매개 변수가 CheckSignature 설정된 메서드 verifySignatureOnly 를 호출하는 false것과 달리 해지 검사 수행되지 않고 체인 트러스트가 검사 않으며 만료가 확인되지 않습니다. 애플리케이션 자체 인증서를 추출 하 고 전달 하는 경우에는 CheckSignature 메서드를 verifySignatureOnly 매개 변수 설정 false, 즉 문서 변조를 방지 하기 위해 부족 합니다. 유효성 검사를 계속 합니다. 인증서는 서명 중인 문서에 적합한 것으로 확인되어야 합니다.

포함된 서명 인증서를 사용하면 섹션 또는 문서 콘텐츠에 <X509Data> 관계없이 유용한 키 회전 전략을 제공할 수 있습니다. 이 방법을 사용 하면 애플리케이션 인증서를 수동으로 추출 해야 및 유사한 유효성 검사를 수행:

  • 인증서가 발급 체인을 통해 직접 또는 여는 인증 기관 (CA) 해당 공용 인증서는 애플리케이션에 포함 됩니다.

    알려진 주체 이름과 같은 추가 검사 없이 OS에서 제공하는 신뢰 목록을 사용하면 변조를 방지하기에 SignedXml충분하지 않습니다.

  • 인증서는 문서 서명 시 만료되지 않은 것으로 확인됩니다(또는 거의 실시간 문서 처리를 위해 "지금").

  • 해지를 지원하는 CA에서 발급한 수명이 긴 인증서의 경우 인증서가 해지되지 않은지 확인합니다.

  • 인증서 주체가 현재 문서에 적합한 것으로 확인되었습니다.

변환 알고리즘 선택

특정 값(예: XrML)을 지정한 사양과 상호 운용하는 경우 사양을 따라야 합니다. 전체 문서에 서명할 때와 같이 봉투 서명이 있는 경우 클래스로 표현되는 XmlDsigEnvelopedSignatureTransform 서명을 사용해야 http://www.w3.org/2000/09/xmldsig#enveloped-signature 합니다. 암시적 XML-C14N 변환도 지정할 수 있지만 필요하지는 않습니다. 인벨로핑 또는 분리된 서명의 경우 변환이 필요하지 않습니다. 암시적 XML-C14N 변환은 모든 것을 처리합니다.

Microsoft 보안 게시판 MS16-035에서 도입된 보안 업데이트로 .NET은 기본적으로 문서 확인에 사용할 수 있는 변환을 제한했으며 신뢰할 수 없는 변환으로 인해 CheckSignature 항상 반환false됩니다. 특히 추가 입력이 필요한 변환(XML에서 자식 요소로 지정됨)은 악의적인 사용자에 의한 남용의 감수성으로 인해 더 이상 허용되지 않습니다. W3C는 이러한 제한 사항의 영향을 받는 두 기본 변환인 XPath 및 XSLT 변환을 방지하는 것이 좋습니다.

외부 참조 문제

애플리케이션은 외부 참조는 현재 컨텍스트에 대 한 적절 한 것 처럼 보일 하는 것을 확인 하지 않으며, 경우 이러한 악용 될 수 있습니다 (서비스 거부, 분산 리플렉션 서비스 거부, 정보를 포함 하는 많은 보안 취약점을 제공 하는 방식 공개 서명 바이패스 하며 원격 코드 실행) 합니다. 애플리케이션 유효성을 검사할 외부 참조 URI 인 경우에 두 번 로드 되는 리소스의 문제가 남아는:와 애플리케이션을 읽을 때 한 번씩 때 SignedXml 읽고 있습니다. 애플리케이션 읽기 및 문서 확인 동일한 콘텐츠를 포함 하는 단계는 보장 되지 않습니다 이므로 서명을 신뢰성을 제공 하지 않습니다.

외부 참조의 위험이 있는 경우 외부 참조 SignedXml 가 발견되면 예외가 throw됩니다. 이 문제에 대한 자세한 내용은 KB 문서 3148821 참조하세요.