2009-12-01 2 views
4

OpenSSL에 의해 생성 된 RSA 개인 키를 사용하여 C# .NET 3.5에서 XML 파일에 서명하려고합니다. 내가 진행 방법은 다음과.NET에서 RSA 키로 XML 파일에 서명하는 방법은 무엇입니까?

입니다 : 내 XML 키를 사용하여 chilkat 프레임 워크 (www.example-code.com/csharp/cert_usePrivateKeyFromPEM.asp)

를 사용하여 XML 형식으로 PEM 형식에서 RSA 키를 변환, 나는 내가 선호하는 네이티브 .NET 함수를 사용할 수있게되었습니다. 그래서 나는 MSDN에 설명 된 방법을 사용했습니다.

그래서, 결국, 내 소스 코드는 다음과 같습니다 :이 기능은 OK 외모가처럼 내가 얻는 서명 XML, 나는, 파일의 끝에서 XML 요소가

RSACryptoServiceProvider rsaProvider = new RSACryptoServiceProvider(); 

//Load the private key from xml file 
XmlDocument xmlPrivateKey = new XmlDocument(); 
xmlPrivateKey.Load("PrivateKey.xml"); 
rsaProvider.FromXmlString(xmlPrivateKey.InnerXml); 

// Create a SignedXml object. 
SignedXml signedXml = new SignedXml(Doc); 

// Add the key to the SignedXml document. 
signedXml.SigningKey = Key; 

// Create a reference to be signed. 
Reference reference = new Reference(); 
reference.Uri = ""; 

// Add an enveloped transformation to the reference. 
XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform(); 
reference.AddTransform(env); 

// Add the reference to the SignedXml object. 
signedXml.AddReference(reference); 

// Compute the signature. 
signedXml.ComputeSignature(); 

// Get the XML representation of the signature and save 
// it to an XmlElement object. 
XmlElement xmlDigitalSignature = signedXml.GetXml(); 

// Append the element to the XML document. 
Doc.DocumentElement.AppendChild(Doc.ImportNode(xmlDigitalSignature, true)); 

있어야 :

<Signature xmlns="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>qoGPSbe4oR9e2XKN6MzP+7XlXYI=</DigestValue> 
    </Reference> 
</SignedInfo> 
<SignatureValue>iPQ6IET400CXfchWJcP22p2gK6RpEc9mkSgfoA94fL5UM6+AB5+IO6BbjsNt31q6MB8hR6lAIcnjzHzc5SeXvFP8Py2bqHTYJvcSA6KcKCQl1LiDNt12UwWiKpSkus2p0LdAeeZJNy9aDxjC/blUaZEr4uPFt0kGCD7h1NQM2SY=</SignatureValue> 

문제는 그 나는이 URL에 xmlsec 사용하여 서명을 확인하려고하면 http://www.aleksey.com/xmlsec/xmldsig-verifier.html합니다. 서명이 유효하지 않다는 메시지가 나타납니다.

나는 내 코드에서 몇 일 동안 오류를 찾고 있었고 찾을 수 없습니다. PEM에서 XML 파일로의 변환이 문제 일 수 있다고 생각하기 시작했으나이를 테스트하는 방법을 모르겠습니다. 게다가, 나는 키로 변환하거나 .NET에서 PEM 파일을 직접 사용하는 다른 방법을 찾지 못했습니다.

누구든지 .NET에서 유효한 서명을 얻을 수 있습니까?

답변

2

예, 저는 그렇게 할 수있었습니다. 문제는 귀하의 참조와 함께 생각합니다. URI는 서명이있는 요소의 ID를 가리켜 야합니다. 어쨌든 아래 코드를 확인하여 올바른 방향으로 당신을 가리 키길 바랍니다.

/클라우스

/// <summary> 
    /// Signs an XmlDocument with an xml signature using the signing certificate given as argument to the method. 
    /// </summary> 
    /// <param name="doc">The XmlDocument to be signed</param> 
    /// <param name="id">The is of the topmost element in the xmldocument</param> 
    /// <param name="cert">The certificate used to sign the document</param> 
    public static void SignDocument(XmlDocument doc, string id, X509Certificate2 cert) 
    { 
     SignedXml signedXml = new SignedXml(doc); 
     signedXml.SignedInfo.CanonicalizationMethod = SignedXml.XmlDsigExcC14NTransformUrl; 
     signedXml.SigningKey = cert.PrivateKey; 

     // Retrieve the value of the "ID" attribute on the root assertion element. 
     Reference reference = new Reference("#" + id); 

     reference.AddTransform(new XmlDsigEnvelopedSignatureTransform()); 
     reference.AddTransform(new XmlDsigExcC14NTransform()); 

     signedXml.AddReference(reference); 

     // Include the public key of the certificate in the assertion. 
     signedXml.KeyInfo = new KeyInfo(); 
     signedXml.KeyInfo.AddClause(new KeyInfoX509Data(cert, X509IncludeOption.WholeChain)); 

     signedXml.ComputeSignature(); 
     // Append the computed signature. The signature must be placed as the sibling of the Issuer element. 
     XmlNodeList nodes = doc.DocumentElement.GetElementsByTagName("Issuer", Saml20Constants.ASSERTION); 
     // doc.DocumentElement.InsertAfter(doc.ImportNode(signedXml.GetXml(), true), nodes[0]);    
     nodes[0].ParentNode.InsertAfter(doc.ImportNode(signedXml.GetXml(), true), nodes[0]); 
    } 
+1

: PreserveWhitespace은 좋은 예는 여기에서 찾을 수 있습니다

서명 할 XML 문서를로드하기 전에 거짓 을 = 그것. –

+0

내가해야하는 서명은 "보이는 것만 서명해야합니다"규칙을 따라야합니다. 나는 전체 문서에 서명해야만한다고 생각했지만, 틀렸을 수도 있습니다 ... 나는 참고 문헌의 URI를 그렇게 바꾸려고 노력할 것입니다. 희망이 완전히 트릭을 할 것입니다. –

+0

맨 위 요소의 ID를 어떻게 설정합니까? 나는 이것을 시도했다 : // 서명 할 데이터를 저장할 데이터 객체를 만든다. DataObject dataObject = new DataObject(); dataObject.Data = Doc.ChildNodes; dataObject.Id = "MyObjectId"; // 데이터 객체를 서명에 추가합니다. signedXml.AddObject (dataObject); //하면 SignedXml 문서에 키를 추가합니다. signedXml.SigningKey = Key; // 서명 할 참조를 만듭니다. 참조 참조 = 새 참조 ("# MyObjectId"); 하지만 난 예외를 얻고있다 ... –

1

당신이 XML에서 everrything에 서명, 나에게 보인다 문서에 삽입하거나 잘못된에 삽입 할 때 서명을 깰

Purhaps reference.Uri = ""; 방법.

또한 네임 스페이스와 공백을 인식해야하며 서명 된 문서에서 작업 할 때 나중에 문제가 발생할 수있는 일부도 서명됩니다. 보십시오이와

dataObject.Data = Doc.ChildNodes; 

을 대체 할

1

:

오늘 같은 문제가 있습니다
dataObject.Data = Doc.GetElementsByTagName("YourRootNodeNameHere"); 
1

내 한 동료는 .NET XML C14은 아무튼 변환 있기 때문에 '어쩌면 있다고 의심 xmlsec에서 구현되는 XML 표준을 따르십시오. 나는 독자적으로 변신을 시도 할 것이고 그것이 정말로 문제인지를 알려줄 것이다.

+0

음, 같은 문제입니까? 이 경우 답변을 확장하십시오. –

관련 문제