Exemple #1
0
        public static void VerifySig(XmlDocument sigDoc)
        {
            try
            {
                XmlElement envelope = sigDoc.DocumentElement;

                XmlElement securityElem = LameXpath.SelectSingleNode(sigDoc, Elem.Security);
                if (securityElem != null)
                {
                    XmlAttribute mustUndAtt = securityElem.Attributes[Attrib.mustUnderstand, Ns.soap];
                    if (mustUndAtt != null)
                    {
                        mustUndAtt.Value = "0";
                    }
                }

                XmlElement sigElem = LameXpath.SelectSingleNode(sigDoc, Elem.Signature);
                if (sigElem == null)
                {
                    return;
                }

                XmlElement sigValElem = LameXpath.SelectSingleNode(sigElem, Elem.SignatureValue);
                byte []    baSigVal   = OpenNETCF.Security.Cryptography.NativeMethods.Format.GetB64(sigValElem.InnerText);

                bool comments  = false;
                bool exclusive = true;
                SHA1CryptoServiceProvider shaCsp = new SHA1CryptoServiceProvider();

                XmlElement sigMethElem = LameXpath.SelectSingleNode(sigElem, Elem.SignatureMethod);
                string     segMeth     = sigMethElem.Attributes["Algorithm"].Value;

                XmlElement  signedInfoElem = LameXpath.SelectSingleNode(sigElem, Elem.SignedInfo);
                XmlDocument xdSignedInfo   = new XmlDocument();
                xdSignedInfo.LoadXml(signedInfoElem.OuterXml);
                XmlCanonicalizer xc   = new XmlCanonicalizer(comments, exclusive);
                MemoryStream     ms   = (MemoryStream)xc.Canonicalize(xdSignedInfo);
                byte []          baMs = new byte[ms.Length];
                ms.Read(baMs, 0, baMs.Length);

                ArrayList  keyInfoRefElem = LameXpath.SelectChildNodes(sigElem, Elem.SecurityTokenReference, Elem.Reference);
                XmlElement keyInfoRef     = (XmlElement)keyInfoRefElem[0];
                string     secTokUri      = keyInfoRef.Attributes["URI"].Value;
                secTokUri = secTokUri.TrimStart(new char[] { '#' });
                XmlElement secTokElem = LameXpath.SelectSingleNode(secTokUri, sigDoc);

                if (secTokElem.LocalName == Elem.UsernameToken)
                {
                    XmlElement nonce   = LameXpath.SelectSingleNode(secTokElem, Elem.Nonce);
                    XmlElement created = LameXpath.SelectSingleNode(secTokElem, Elem.Created);
                    //DerivedKeyGenerator seems to be off by 1?
                    //byte [] baKey = P_SHA1.DeriveKey(ClearPassword, StrKeyLabel, nonce.InnerText, created.InnerText, NumKeyBytes);
                    byte []  baKey   = P_SHA1.DeriveKey(SigObj.ClearPassword, StrKeyLabel, nonce.InnerText, created.InnerText, NumKeyBytes);
                    HMACSHA1 hmacSha = new HMACSHA1(baKey);
                    byte []  baSig   = hmacSha.ComputeHash(baMs);
                    OpenNETCF.Security.Cryptography.NativeMethods.Format.SameBytes(baSigVal, baSig);
                }
                else if (secTokElem.LocalName == Elem.BinarySecurityToken)
                {
                    byte []         baCert = OpenNETCF.Security.Cryptography.NativeMethods.Format.GetB64(secTokElem.InnerText);
                    X509Certificate cert   = new X509Certificate(baCert);                   //pub key to verify sig.
                    byte []         exponent;
                    byte []         modulus;
                    DecodeCertKey.GetPublicRsaParams(cert, out exponent, out modulus);
                    RSAParameters rsaParam = new RSAParameters();
                    rsaParam.Exponent = exponent;
                    rsaParam.Modulus  = modulus;
                    RSACryptoServiceProvider rsaCsp = new RSACryptoServiceProvider();
                    rsaCsp.ImportParameters(rsaParam);

                    byte [] baUnsigHash = shaCsp.ComputeHash(baMs);
                    bool    valid       = rsaCsp.VerifyHash(baUnsigHash, "SHA", baSigVal);
                    if (valid == false)
                    {
                        throw new Exception("signature is not valid");
                    }
                }
                else if (secTokElem.LocalName == Elem.SecurityContextToken)
                {
                    //TODO how to validate signature?
                }
                else
                {
                    throw new Exception("only support Username, BinarySecurity, and SecurityContext Token signature");
                }

                //verify reference hashes
                string    refdName = String.Empty;
                ArrayList refNodes = LameXpath.SelectChildNodes(sigDoc, Elem.SignedInfo, Elem.Reference);
                foreach (object oXn in refNodes)
                {
                    XmlNode xn    = (XmlNode)oXn;
                    string  uriId = xn.Attributes[Attrib.URI].Value;
                    uriId = uriId.TrimStart(new char[] { '#' });
                    XmlElement digValElem = LameXpath.SelectSingleNode(xn, Elem.DigestValue);
                    byte []    baDigest   = OpenNETCF.Security.Cryptography.NativeMethods.Format.GetB64(digValElem.InnerText);

                    XmlElement  refdElem   = LameXpath.SelectSingleNode(uriId, sigDoc);
                    XmlDocument xdRefdElem = new XmlDocument();
                    refdName = refdElem.LocalName;                     //for debug visibility
                    xdRefdElem.LoadXml(refdElem.OuterXml);
                    //not reusable
                    xc = new XmlCanonicalizer(comments, exclusive);
                    //MemoryStream ms = (MemoryStream) xc.Canonicalize(refdElem);
                    ms   = (MemoryStream)xc.Canonicalize(xdRefdElem);
                    baMs = new byte[ms.Length];
                    ms.Read(baMs, 0, baMs.Length);
                    byte [] baHash = shaCsp.ComputeHash(baMs);
                    try
                    {
                        OpenNETCF.Security.Cryptography.NativeMethods.Format.SameBytes(baDigest, baHash);
                    }
                    catch (Exception ex)
                    {
                        throw new Exception(refdName + ":" + ex.Message, ex);
                    }
                }
            }
            finally
            {
                //ClearPassword = null;
                SigObj = null;
            }
        }
		public static void VerifySig(XmlDocument sigDoc)
		{
			try
			{
				XmlElement envelope = sigDoc.DocumentElement;

				XmlElement securityElem = LameXpath.SelectSingleNode(sigDoc, Elem.Security);
				if(securityElem != null)
				{
					XmlAttribute mustUndAtt = securityElem.Attributes[Attrib.mustUnderstand,Ns.soap];
					if(mustUndAtt != null)
						mustUndAtt.Value = "0";
				}

				XmlElement sigElem = LameXpath.SelectSingleNode(sigDoc, Elem.Signature);
				if(sigElem == null)
					return;

				XmlElement sigValElem = LameXpath.SelectSingleNode(sigElem, Elem.SignatureValue);
				byte [] baSigVal = OpenNETCF.Security.Cryptography.NativeMethods.Format.GetB64(sigValElem.InnerText);

				bool comments = false;
				bool exclusive = true;
				SHA1CryptoServiceProvider shaCsp = new SHA1CryptoServiceProvider();

				XmlElement sigMethElem = LameXpath.SelectSingleNode(sigElem, Elem.SignatureMethod);
				string segMeth = sigMethElem.Attributes["Algorithm"].Value;

				XmlElement signedInfoElem = LameXpath.SelectSingleNode(sigElem, Elem.SignedInfo);
				XmlDocument xdSignedInfo = new XmlDocument();
				xdSignedInfo.LoadXml(signedInfoElem.OuterXml);
				XmlCanonicalizer xc = new XmlCanonicalizer(comments, exclusive);
				MemoryStream ms = (MemoryStream) xc.Canonicalize(xdSignedInfo);
				byte [] baMs = new byte[ms.Length];
				ms.Read(baMs, 0, baMs.Length);

				ArrayList keyInfoRefElem = LameXpath.SelectChildNodes(sigElem, Elem.SecurityTokenReference, Elem.Reference);
				XmlElement keyInfoRef = (XmlElement) keyInfoRefElem[0];
				string secTokUri = keyInfoRef.Attributes["URI"].Value;
				secTokUri = secTokUri.TrimStart(new char[]{'#'});
				XmlElement secTokElem = LameXpath.SelectSingleNode(secTokUri, sigDoc);
			
				if(secTokElem.LocalName == Elem.UsernameToken)
				{
					XmlElement nonce = LameXpath.SelectSingleNode(secTokElem, Elem.Nonce);
					XmlElement created = LameXpath.SelectSingleNode(secTokElem, Elem.Created);
					//DerivedKeyGenerator seems to be off by 1?
					//byte [] baKey = P_SHA1.DeriveKey(ClearPassword, StrKeyLabel, nonce.InnerText, created.InnerText, NumKeyBytes);
					byte [] baKey = P_SHA1.DeriveKey(SigObj.ClearPassword, StrKeyLabel, nonce.InnerText, created.InnerText, NumKeyBytes);
					HMACSHA1 hmacSha = new HMACSHA1(baKey);
					byte [] baSig = hmacSha.ComputeHash(baMs);
					OpenNETCF.Security.Cryptography.NativeMethods.Format.SameBytes(baSigVal, baSig);
				}
				else if(secTokElem.LocalName == Elem.BinarySecurityToken)
				{
					byte [] baCert = OpenNETCF.Security.Cryptography.NativeMethods.Format.GetB64(secTokElem.InnerText);
					X509Certificate cert = new X509Certificate(baCert); //pub key to verify sig.
					byte [] exponent;
					byte [] modulus;
					DecodeCertKey.GetPublicRsaParams(cert, out exponent, out modulus);
					RSAParameters rsaParam = new RSAParameters();
					rsaParam.Exponent = exponent;
					rsaParam.Modulus = modulus;
					RSACryptoServiceProvider rsaCsp = new RSACryptoServiceProvider();
					rsaCsp.ImportParameters(rsaParam);
               
					byte [] baUnsigHash = shaCsp.ComputeHash(baMs);
					bool valid = rsaCsp.VerifyHash(baUnsigHash, "SHA", baSigVal);
					if(valid == false)
						throw new Exception("signature is not valid");
				}
				else if(secTokElem.LocalName == Elem.SecurityContextToken)
				{
					//TODO how to validate signature?
				}
				else
				{
					throw new Exception("only support Username, BinarySecurity, and SecurityContext Token signature");
				}

				//verify reference hashes
				string refdName = String.Empty;
				ArrayList refNodes = LameXpath.SelectChildNodes(sigDoc, Elem.SignedInfo, Elem.Reference);
				foreach(object oXn in refNodes)
				{
					XmlNode xn = (XmlNode) oXn;
					string uriId = xn.Attributes[Attrib.URI].Value;
					uriId = uriId.TrimStart(new char[]{'#'});
					XmlElement digValElem = LameXpath.SelectSingleNode(xn, Elem.DigestValue);
					byte [] baDigest = OpenNETCF.Security.Cryptography.NativeMethods.Format.GetB64(digValElem.InnerText);

					XmlElement refdElem = LameXpath.SelectSingleNode(uriId, sigDoc);
					XmlDocument xdRefdElem = new XmlDocument();
					refdName = refdElem.LocalName; //for debug visibility
					xdRefdElem.LoadXml(refdElem.OuterXml);
					//not reusable
					xc = new XmlCanonicalizer(comments, exclusive);
					//MemoryStream ms = (MemoryStream) xc.Canonicalize(refdElem);
					ms = (MemoryStream) xc.Canonicalize(xdRefdElem);
					baMs = new byte[ms.Length];
					ms.Read(baMs, 0, baMs.Length);
					byte [] baHash = shaCsp.ComputeHash(baMs);
					try
					{
						OpenNETCF.Security.Cryptography.NativeMethods.Format.SameBytes(baDigest, baHash);
					}
					catch(Exception ex)
					{
						throw new Exception(refdName + ":" + ex.Message, ex);
					}
				}
			}
			finally
			{
				//ClearPassword = null;
				SigObj = null;
			}
		}