문제

서명 된 XML 문서 (.NET의 SignEdXml 클래스)의 서명에 접두사를 설정하는 방법이 있습니까?

그래서 대신 :

<Signature xmlns="http://www.w3.org/2000/09/xmldsig#>
...
</Signature>

다음을 가질 수 있습니다.

<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#>
...
</ds:Signature>
도움이 되었습니까?

해결책

우선,이 작업을 수행할만한 충분한 이유는 없습니다. 두 형태는 기능적으로 동일합니다. 잘 행동하는 XML 프로세서는 절대적으로 동일하게 처리합니다. 따라서 XML 네임 스페이스를 올바르게 구현하지 않는 응용 프로그램과 대화하려고하지 않는 한 기본 양식을 단독으로 남겨 두는 것이 더 좋습니다 (IMO). (이 경우에도 가능하다면 결함이있는 응용 프로그램을 대신 고정하는 것이 더 나을 것입니다.)

즉, signedxml.getxml ()에 의해 반환되는 xmlelement에서 접두사를 수동으로 설정할 수 있으며 다음과 같은 xpath를 사용하여 하위 요소를 설정할 수 있습니다.

XmlElement signature = signedXml.GetXml();
foreach (XmlNode node in signature.SelectNodes(
    "descendant-or-self::*[namespace-uri()='http://www.w3.org/2000/09/xmldsig#']"))
{
    node.Prefix = "ds";
}

다른 팁

할 수 없습니다. XML을 수정 한 경우 서명 된 후 위의 예제에서 확인할 수 없을 수도 있습니다. IMO 이것은 당신이 함께 살아야 할 MSFT의 디지털 서명 구현의 결함입니다.

많은 사람들 이이 일을 할 이유가 없으며 기술적으로 정확하다고 말할 것입니다. 그러나 거대한 공급 업체 (예 : 주 정부 또는 은행)를 다룰 때 행운을 빕니다. 대부분의 참조 구현에는 포함됩니다.

업데이트 : 서명 징후 모든 것 SignedInfo 요소에서 사실 이후 해당 요소를 업데이트하면 서명이 더 이상 유효하지 않습니다. 당신은 메시지를 "변조"했습니다.

이를 수행 할 수 있지만 SignedInfo 노드의 다이제스트 값을 얻기 전에 접두사를 추가하려면 SignEdXml 클래스를 수정해야합니다.

ComputeSignature 메소드는 접두사 매개 변수를 추가하도록 수정됩니다.

public void ComputeSignature(string prefix){...}

이 메소드가 불리는 경우 SignedInfo 노드의 값을 소화하여 서명 값을 계산합니다. "DS"접두사가없는이 값을 얻은 다음 접두사를 추가하면 유효하지 않은 서명이 발생하므로 접두사를 추가해야합니다. SignedInfo 노드의 다이제스트 값을 얻기 전에.

이 다이제스트 값은 GetC14nDigest 메소드에서 생성 되므로이 방법은 접두사 매개 변수를 추가하고 Digest 값을 얻기 전에 접두사를 추가하도록 수정됩니다.

private byte[] GetC14NDigest(HashAlgorithm hash, string prefix)
{
    XmlDocument document = new XmlDocument();
    document.PreserveWhitespace = false;
    XmlElement e = this.SignedInfo.GetXml(); //get the signedinfo nodes
    document.AppendChild(document.ImportNode(e, true));        
    Transform canonicalizationMethodObject = this.SignedInfo.CanonicalizationMethodObject;       
    SetPrefix(prefix, document.DocumentElement); /*Set the prefix before getting the HASH*/
    canonicalizationMethodObject.LoadInput(document);
    return canonicalizationMethodObject.GetDigestedOutput(hash);
}

자, 이제 "ds"접두사가있는 SignedInfo 노드의 서명 값을 가지고 있습니다. 아직 접두사가있는 XML이 아직 없으므로 getXML 메소드를 호출하면 XML을 얻지 못하면 XML을 얻게됩니다. 접두사와 물론 서명 값이 DS 접두사를 고려하여 계산 되었기 때문에 잘못된 서명이 있습니다. 이를 피하고 접두사를 사용하여 XML 구조를 가져 오려면 getXml 메소드를 수정하고 접두사 매개 변수를 추가하고 SetPrefix 메소드를 호출하여 서명 XML의 모든 노드에 "ds"접두사를 추가합니다.

public XmlElement GetXml(string prefix)
{
    XmlElement e = this.GetXml();
    SetPrefix(prefix, e); //return the xml structure with the prefix
    return e;
}

나는 그 수정으로 여기에 수업을 떠날 것이다

맞춤형 클래스

internal sealed class CustomSignedXml : SignedXml
{
    XmlElement obj = null;
    public CustomSignedXml (XmlDocument xml)
        : base(xml)
    {
    }

    public CustomSignedXml (XmlElement xmlElement)
        : base(xmlElement)
    {

    }

    public XmlElement GetXml(string prefix)
    {
        XmlElement e = this.GetXml();
        SetPrefix(prefix, e);
        return e;
    }

    public void ComputeSignature(string prefix)
    {
        this.BuildDigestedReferences();
        AsymmetricAlgorithm signingKey = this.SigningKey;
        if (signingKey == null)
        {
            throw new CryptographicException("Cryptography_Xml_LoadKeyFailed");
        }
        if (this.SignedInfo.SignatureMethod == null)
        {
            if (!(signingKey is DSA))
            {
                if (!(signingKey is RSA))
                {
                    throw new CryptographicException("Cryptography_Xml_CreatedKeyFailed");
                }
                if (this.SignedInfo.SignatureMethod == null)
                {
                    this.SignedInfo.SignatureMethod = "http://www.w3.org/2000/09/xmldsig#rsa-sha1";
                }
            }
            else
            {
                this.SignedInfo.SignatureMethod = "http://www.w3.org/2000/09/xmldsig#dsa-sha1";
            }
        }
        SignatureDescription description = CryptoConfig.CreateFromName(this.SignedInfo.SignatureMethod) as SignatureDescription;
        if (description == null)
        {
            throw new CryptographicException("Cryptography_Xml_SignatureDescriptionNotCreated");
        }
        HashAlgorithm hash = description.CreateDigest();
        if (hash == null)
        {
            throw new CryptographicException("Cryptography_Xml_CreateHashAlgorithmFailed");
        }
        this.GetC14NDigest(hash, prefix);
        this.m_signature.SignatureValue = description.CreateFormatter(signingKey).CreateSignature(hash);
    }         

    private byte[] GetC14NDigest(HashAlgorithm hash, string prefix)
    {

        XmlDocument document = new XmlDocument();
        document.PreserveWhitespace = false;
        XmlElement e = this.SignedInfo.GetXml();
        document.AppendChild(document.ImportNode(e, true));               

        Transform canonicalizationMethodObject = this.SignedInfo.CanonicalizationMethodObject;            
        SetPrefix(prefix, document.DocumentElement); //Set the prefix before getting the HASH
        canonicalizationMethodObject.LoadInput(document);
        return canonicalizationMethodObject.GetDigestedOutput(hash);
    }

    private void BuildDigestedReferences()
    {
        Type t = typeof(SignedXml);
        MethodInfo m = t.GetMethod("BuildDigestedReferences", BindingFlags.NonPublic | BindingFlags.Instance);
        m.Invoke(this, new object[] { });
    }

    private void SetPrefix(string prefix, XmlNode node)
    {
       foreach (XmlNode n in node.ChildNodes)
          SetPrefix(prefix, n);
       node.Prefix = prefix;
    }
}

그리고 그것을 사용하는 방법

CustomSignedXml signedXml = new CustomSignedXml();
.
.//your code
. 

//compute the signature with the "ds" prefix

signedXml.ComputeSignature("ds");

//get the xml of the signature with the "ds" prefix

XmlElement xmlDigitalSignature = signedXml.GetXml("ds");
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top