Signing XML Documents With RSA Keys

// December 6th, 2009 // Useful Code

This is a very useful tool when attempting to create a simple licensing protocol. You can distribute a plain text XML document which has been signed using a private key and validate it remotely using the public key. Just make sure to not store the public key in plain text otherwise a smart user can simply replace your public key and regenerate their own license file.

        /// <summary>
        /// SIGN AN XML DOCUMENT USING THE PRIVATE KEY
        /// </summary>
        /// <param name="Doc">XML DOCUMENT TO BE SHOULD SIGNED</param>
        /// <param name="PrivateKey">PRIVATE RSA KEY USED TO SIGN XML</param>
        public static void SignXml(XmlDocument Doc, string PrivateKey)
        {
            RSACryptoServiceProvider tmpRsa = new RSACryptoServiceProvider();

            //VERIFY ALL ARGUMENTS HAVE BEEN PASSED IN
            if (Doc == null)
                throw new ArgumentException("Doc");
            if (PrivateKey == null)
                throw new ArgumentException("Key");

            //IMPORT THE PRIVATE KEY INTO AN RSA PROVIDER
            tmpRsa.ImportCspBlob(Convert.FromBase64String(PrivateKey));

            //CREATE A SIGNED XML DOCUMENT
            SignedXml signedXml = new SignedXml(Doc);

            //ADD THE RSA KEY TO THE SIGNED DOCUMENT
            signedXml.SigningKey = tmpRsa;

            //CREATE A REFERENCE TO BE SIGNED
            Reference reference = new Reference();
            reference.Uri = "";

            //CREATE AN ENVELOPED SIGNATURE WHICH
            XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform(true);
            reference.AddTransform(env);

            //ADD THE REFERENCE TO THE SIGNED DOCUMENT
            signedXml.AddReference(reference);

            //COMPUTE THE DOCUMENTS SIGNATURE
            signedXml.ComputeSignature();

            //RETRIEVE THE XML SIGNATURE FROM THE DOCUMENT
            XmlElement xmlDigitalSignature = signedXml.GetXml();

            //APPEND THE SIGNATURE TO THE END OF THE DOCUMENT
            //Doc.DocumentElement.AppendChild(Doc.ImportNode(xmlDigitalSignature, true));
            Doc.DocumentElement.AppendChild(xmlDigitalSignature);
        }

        /// <summary>
        /// VERIFY A SIGNED XML DOCUMENT
        /// </summary>
        /// <param name="Doc">SIGNED XML DOCUMENT</param>
        /// <param name="PublicKey">PUBLIC KEY TO VERIFY SIGNATURE AGAINST</param>
        /// <returns></returns>
        public static bool VerifyXml(XmlDocument Doc, string PublicKey)
        {
            RSACryptoServiceProvider tmpRsa = new RSACryptoServiceProvider();

            //VERIFY ALL ARGUMENTS HAVE BEEN PASSED IN
            if (Doc == null)
                throw new ArgumentException("Doc");
            if (PublicKey == null)
                throw new ArgumentException("Key");

            //IMPORT THE PUBLIC KEY INTO AN RSA PROVIDER
            tmpRsa.ImportCspBlob(Convert.FromBase64String(PublicKey));

            //HOLD THE SIGNED DOCUMENT
            SignedXml signedXml = new SignedXml(Doc);

            //LOCATE THE SIGNATURE NODE IN THE DOCUMENT
            XmlNodeList nodeList = Doc.GetElementsByTagName("Signature");

            //IF WE CANT FIND THE NODE THEN THIS DOCUMENT IS NOT SIGNED
            if (nodeList.Count <= 0)
            {
                throw new CryptographicException("Verification failed: No Signature was found in the document.");
            }

            //IF THERE ARE MORE THEN ONE SIGNATURES THEN FAIL
            if (nodeList.Count >= 2)
            {
                throw new CryptographicException("Verification failed: More that one signature was found for the document.");
            }

            //LOAD THE SIGNATURE NODE INTO THE SIGNEDXML DOCUMENT
            signedXml.LoadXml((XmlElement)nodeList[0]);

            //CHECK THE SIGNATURE AND SEND THE RESULT
            return signedXml.CheckSignature(tmpRsa);
        }
Be Sociable, Share!
  • RSS
  • Twitter
  • Facebook
  • LinkedIn
  • DeviantArt