2014-01-08 7 views
1

몇 가지 비슷한 질문을했지만 필자가 정확히 말한 것은 없습니다.SignedXml.CheckSignature는 개인 키로 확인하는 경우에만 true를 반환합니다.

XML에 서명을 시도하고 C#을 사용하여 공개 키로 확인하려고합니다.

키를 사용하여 XML에 서명 한 다음 키를 XML로 내 보냅니다. 그런 다음 키와 서명 된 XML을 다른 컴퓨터로 가져오고 rsa.FromXmlString(doc.InnerXml)을 사용하여 키를 가져온 다음 XML 서명을 확인하십시오.

rsa.ToXmlString(True)을 사용하여 공개 키와 개인 키를 모두 XML로 내보낼 때 작동합니다. 그러나 rsa.ToXmlString(False)을 사용하여 공개 키만 내보내려고합니다. 공개 키만 내보내고 두 번째 컴퓨터로 가져 와서 XML 서명의 유효성을 검사하려고하면 서명이 유효하지 않다는 메시지가 나타납니다.

먼저 공개 키로 서명 된 XML을 확인할 수 있습니까?

둘째, 이것이 사실이라면 내 XML 검증 기능이 공용 키가 아닌 pub/priv 키 쌍에서만 작동하는 이유는 무엇입니까?

이 문제를 디버깅하는 방법에 대한 지혜가 있습니까? signedXml.CheckSignature(Key);은 실패한 이유에 대한 정보를 제공하지 않기 때문에 그 밖의 작업을 수행 할 것인지 잘 모릅니다.

내 가져 오기 키, 내보내기 키, XML 서명 및 XML 함수 확인이 아래에 나와 있습니다. 더 많은 정보가 필요하면 알려주세요.

public static void ImportKeyFromFile(string ContainerName, string inputFile) 
    { 
     try 
     { 
      // Create new XmlDocument. 
      XmlDocument doc = new XmlDocument(); 

      // Load XML Document. 
      doc.Load(inputFile); 

      // Create the CspParameters object and set the key container 
      // name used to store the RSA key pair. 
      CspParameters cp = new CspParameters(); 
      cp.KeyContainerName = ContainerName; 

      // Create a new instance of RSACryptoServiceProvider that accesses 
      // the key container MyKeyContainerName. 
      RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(cp); 

      // Get RSA Parameters from xml document. 
      rsa.FromXmlString(doc.InnerXml); 
     } 
     catch (Exception ex) 
     { 
      MessageBox.Show(ex.Message); 
     } 
    } 
    public static void ExportKeyToFile(string ContainerName, string outputPath, bool private_key) 
    { 
     try 
     { 
      // Create the CspParameters object and set the key container 
      // name used to store the RSA key pair. 
      CspParameters cp = new CspParameters(); 
      cp.KeyContainerName = ContainerName; 

      // Create a new instance of RSACryptoServiceProvider that accesses 
      // the key container MyKeyContainerName. 
      RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(cp); 

      // Create new XmlDocument. 
      XmlDocument doc = new XmlDocument(); 

      // Store rsa key. 
      doc.InnerXml = rsa.ToXmlString(private_key); 

      // Save Document. 
      doc.Save(outputPath); 
     } 
     catch (Exception ex) 
     { 
      MessageBox.Show(ex.Message); 
     } 
    } 
    public static Boolean VerifyXml(XmlDocument Doc, RSA Key) 
    { 
     // Check arguments. 
     if (Doc == null) 
      throw new ArgumentException("Doc"); 
     if (Key == null) 
      throw new ArgumentException("Key"); 

     // Create a new SignedXml object and pass it 
     // the XML document class. 
     SignedXml signedXml = new SignedXml(Doc); 

     // Find the "Signature" node and create a new 
     // XmlNodeList object. 
     XmlNodeList nodeList = Doc.GetElementsByTagName("Signature"); 

     // Throw an exception if no signature was found. 
     if (nodeList.Count <= 0) 
     { 
      throw new CryptographicException("Verification failed: No Signature was found in the document."); 
     } 

     // Load the first <signature> node. 
     signedXml.LoadXml((XmlElement)nodeList[0]); 

     // Check the signature and return the result. 
     return signedXml.CheckSignature(Key); 
    } 
    public static void SignXml(XmlDocument xmlDoc, RSA Key) 
    { 
     // Check arguments. 
     if (xmlDoc == null) 
      throw new ArgumentException("xmlDoc"); 
     if (Key == null) 
      throw new ArgumentException("Key"); 

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

     // 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. 
     xmlDoc.DocumentElement.AppendChild(xmlDoc.ImportNode(xmlDigitalSignature, true)); 
    } 

답변

1

키 컨테이너에 공개 키를 저장할 수 없기 때문에 문제가 발생합니다. 공개 키로 서명을 확인하려면 rsa.FromXmlString을 사용하여 XML에서 키를 가져온 다음 rsa를 직접 서명 확인 함수로 전달해야합니다. 키 컨테이너에 공개 키를 저장하고 나중에 검색하려고하면 결국 새 키가 생성됩니다. How to store a public key in a machine-level RSA key container

+0

다른 옵션은 서명 된 문서에 키 (또는 인증서)를 포함시키는 것입니다. 이것은 많은 공간을 차지하지 않지만 소비자가 별도의 채널에서 키를 얻지 못하도록합니다. –

+0

소비자는 여전히 공개 키가 자신이 생각하는 사람이 누구인지를 확인하는 방법이 필요합니다. 필자의 경우, xml을받을 때 소비자는 이미 공개 키를 가지고있다. – user985637

+0

참이지만 수신 된 것과 비교하려면 키 엄지 손가락 (키 해시) 만 필요합니다. –