예제 #1
0
        public static XmlDocument CheckHeaders(XmlDocument xmlDoc)
        {
            XmlElement envelope     = xmlDoc.DocumentElement;
            XmlElement headerOrBody = (XmlElement)envelope.ChildNodes[0];
            XmlElement header       = null;
            XmlElement body         = null;

            if (headerOrBody.LocalName == Elem.Header)
            {
                header = (XmlElement)envelope.ChildNodes[0];
                body   = (XmlElement)envelope.ChildNodes[1];
            }
            else             //no header
            {
                body = (XmlElement)envelope.ChildNodes[0];
            }

            if (header != null)
            {
                XmlElement tsElem = LameXpath.SelectSingleNode(header, Elem.Timestamp);
                if (tsElem != null)
                {
                    XmlElement creElem = LameXpath.SelectSingleNode(tsElem, Elem.Created);
                    XmlElement expElem = LameXpath.SelectSingleNode(tsElem, Elem.Expires);
                    string     cre     = creElem.InnerText;
                    string     exp     = expElem.InnerText;

                    if (exp.CompareTo(cre) == -1)                    //less than
                    {
                        throw new Exception("Timestamp expired before creation");
                    }
                    bool retVal = TimestampHeader.IsExpired(exp);
                    if (retVal == true)
                    {
                        throw new Exception("response TimeStamp is expired");
                    }
                }
            }

            return(xmlDoc);
        }
예제 #2
0
        //public static string ClearPassword;

        /*
         * -generate (in order)
         * 1) gen refs in SignedInfo
         * 2) construct SignedInfo and create sig element
         * 1) obtain raw data
         * add wsu:Id to everything
         * apply transforms / canonical
         * calculate digest
         * create ref elem
         * 2) create signed info
         * apply canonical
         * create actual signature value
         * sig element
         * w/SignedInfo, SigVlaue, KeyInfo, ...
         */
        public static XmlDocument SignXml(XmlDocument plainDoc)
        {
            if (SigObj == null)
            {
                return(plainDoc);                //nothing to sign
            }
            XmlElement envelope = plainDoc.DocumentElement;

            XmlElement headerOrBody = (XmlElement)envelope.ChildNodes[0];
            XmlElement header;
            XmlElement body;

            if (headerOrBody.LocalName == Elem.Body)
            {
                header = plainDoc.CreateElement(headerOrBody.Prefix, Elem.Header, headerOrBody.NamespaceURI);
                envelope.InsertBefore(header, headerOrBody);
            }
            header = (XmlElement)envelope.ChildNodes[0];
            body   = (XmlElement)envelope.ChildNodes[1];
            XmlNodeList headers  = header.ChildNodes;
            XmlElement  security = null;

            foreach (XmlNode xn in headers)
            {
                if (xn.LocalName == Elem.Security)
                {
                    security = (XmlElement)xn;
                }
            }
            if (security == null)
            {
                security = plainDoc.CreateElement(Pre.wsse, Elem.Security, Ns.wsseLatest);
                XmlAttribute mustUnderstand = plainDoc.CreateAttribute(Pre.soap, Attrib.mustUnderstand, Ns.soap);
                mustUnderstand.Value = "1";
                security.Attributes.Append(mustUnderstand);
                header.AppendChild(security);
            }

            XmlElement tokenElem = null;
            string     secTokId  = null;
            string     sigAlgVal = null;

            //add BinarySecurityToken or UsernameToken under Security
            if (SigObj.BinSecTok != null)
            {
                XmlElement binSecTok = SigObj.BinSecTok.WriteXml(plainDoc, security);

                secTokId  = SigObj.BinSecTok.Id;
                sigAlgVal = Alg.rsaSha1;
                if (SigObj.AsymmAlg is DSACryptoServiceProvider)
                {
                    sigAlgVal = Alg.dsaSha1;
                }
                tokenElem = binSecTok;
            }

            /*
             * <wsse:UsernameToken xmlns:wsu="http://schemas.xmlsoap.org/ws/2002/07/utility" wsu:Id="SecurityToken-344570f1-e3b7-42fc-9b78-f0dcd1f90bd8">
             *      <wsse:Username>Admin</wsse:Username>
             *      <wsse:Password Type="wsse:PasswordDigest">W5xVfXpb+NoV9KaPIQXUIslGGak=</wsse:Password>
             *      <wsse:Nonce>+7L+k37JW8qQCK1SPopXeQ==</wsse:Nonce>
             *      <wsu:Created>2003-10-23T04:40:04Z</wsu:Created>
             * </wsse:UsernameToken>
             */
            if (SigObj.UserTok != null)
            {
                XmlElement userTokElem = SigObj.UserTok.WriteXml(plainDoc, security);
                tokenElem = userTokElem;

                /*
                 * //xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
                 * XmlElement userTokElem = plainDoc.CreateElement(Pre.wsse, Elem.UsernameToken, Ns.wsseLatest);
                 * security.AppendChild(userTokElem);
                 * XmlAttribute uid = plainDoc.CreateAttribute(Pre.wsu, Attrib.Id, Ns.wsuLatest);
                 * uid.Value = SigObj.UserTok.Id;
                 * userTokElem.Attributes.Append(uid);
                 * XmlElement userElem = plainDoc.CreateElement(Pre.wsse, Elem.Username, Ns.wsseLatest);
                 * userElem.InnerText = SigObj.UserTok.Username.Text;
                 * userTokElem.AppendChild(userElem);
                 * if(SigObj.UserTok.Password != null)
                 * {
                 *      XmlElement passElem = plainDoc.CreateElement(Pre.wsse, Elem.Password, Ns.wsseLatest);
                 *      XmlAttribute type = plainDoc.CreateAttribute(Attrib.Type);
                 *      type.Value = SigObj.UserTok.Password.Type;
                 *      passElem.Attributes.Append(type);
                 *      passElem.InnerText = SigObj.UserTok.Password.Text;
                 *      userTokElem.AppendChild(passElem);
                 * }
                 * XmlElement nonceElem = plainDoc.CreateElement(Pre.wsse, Elem.Nonce, Ns.wsseLatest);
                 * nonceElem.InnerText = SigObj.UserTok.Nonce.Text;
                 * userTokElem.AppendChild(nonceElem);
                 * XmlElement creElem = plainDoc.CreateElement(Pre.wsu, Elem.Created, Ns.wsuLatest);
                 * creElem.InnerText = SigObj.UserTok.Created;
                 * userTokElem.AppendChild(creElem);
                 * userTokElem.Attributes.Append(uid);
                 */
                secTokId  = SigObj.UserTok.Id;
                sigAlgVal = Alg.hmacSha1;
            }
            if (SigObj.securityContextToken != null)
            {
                XmlNode sctNode = LameXpath.SelectSingleNode(header, Elem.SecurityContextToken);
                if (sctNode == null)
                {
                    //i need to import this node 1st
                    sctNode = plainDoc.ImportNode(SigObj.securityContextToken, true);
                    string     dupeId   = sctNode.Attributes[Attrib.Id, Ns.wsuLatest].Value;
                    XmlElement dupeElem = LameXpath.SelectSingleNode(dupeId, security);
                    if (dupeElem == null)
                    {
                        security.AppendChild(sctNode);
                    }
                    else
                    {
                        sctNode = LameXpath.SelectSingleNode(dupeId, security);
                    }
                }
                //<wsse:SecurityContextToken wsu:Id=\"SecurityToken-feb27552-6eb5-4a27-a831-e1bdfca326e2\">
                secTokId  = sctNode.Attributes[Attrib.Id, Ns.wsuLatest].Value;
                sigAlgVal = Alg.hmacSha1;
                tokenElem = (XmlElement)sctNode;

                if (SigObj.derKeyTok != null)
                {
                    XmlNode idElem = LameXpath.SelectSingleNode(sctNode, Elem.Identifier);
                    if (idElem != null)
                    {
                        SigObj.derKeyTok.secTokRef.Reference.URI = idElem.InnerText;
                    }

                    XmlElement derKeyTokElem = SigObj.derKeyTok.WriteXml(plainDoc, security, (XmlElement)sctNode);
                    secTokId = SigObj.derKeyTok.id;
                }
            }


            //add Signature element, SignedInfo, CanonicalizationMethod and SignatureMethod
            XmlElement sigElem = plainDoc.CreateElement(Pre.ds, Elem.Signature, Ns.ds);

            security.AppendChild(sigElem);             //just append
            //add SignedInfo
            XmlElement sigInfoElem = plainDoc.CreateElement(Pre.ds, Elem.SignedInfo, Ns.ds);

            sigElem.AppendChild(sigInfoElem);
            XmlElement   canMethElem = plainDoc.CreateElement(Pre.ds, Elem.CanonicalizationMethod, Ns.ds);
            XmlAttribute canAlg      = plainDoc.CreateAttribute(Attrib.Algorithm);

            canAlg.Value = Alg.xmlExcC14n;
            canMethElem.Attributes.Append(canAlg);
            sigInfoElem.AppendChild(canMethElem);
            XmlElement   sigMethElem = plainDoc.CreateElement(Pre.ds, Elem.SignatureMethod, Ns.ds);
            XmlAttribute sigAlg      = plainDoc.CreateAttribute(Attrib.Algorithm);

            sigAlg.Value = sigAlgVal;
            sigMethElem.Attributes.Append(sigAlg);
            sigInfoElem.AppendChild(sigMethElem);

            //get each Refs element, add Id if missing
            //canonical, Digest, add ReferenceElement
            bool comments  = false;
            bool exclusive = true;
            SHA1CryptoServiceProvider shaCsp = new SHA1CryptoServiceProvider();

            foreach (object oRef in SigObj.Refs)
            {
                XmlElement refdElem = LameXpath.SelectSingleNode(plainDoc, oRef.ToString());
                if (refdElem == null)
                {
                    continue;                     //cant sign it because it doesnt exist
                }
                //get or add Id
                XmlAttribute xaId = null;
                foreach (XmlAttribute xa in refdElem.Attributes)
                {
                    if (xa.LocalName == Attrib.Id)
                    {
                        xaId = xa;
                        break;
                    }
                }
                if (xaId == null)
                {
                    xaId = plainDoc.CreateAttribute(Pre.wsu, Attrib.Id, Ns.wsuLatest);
                    string preId = "Id-";
                    if (oRef.ToString() == Elem.Timestamp)
                    {
                        preId = "Timestamp-";
                    }
                    xaId.Value = preId + GuidEx.NewGuid().ToString("D");
                    refdElem.Attributes.Append(xaId);
                }
                XmlDocument xdRefd = new XmlDocument();
                xdRefd.LoadXml(refdElem.OuterXml);
                XmlCanonicalizer xc     = new XmlCanonicalizer(comments, exclusive);
                MemoryStream     msRefd = (MemoryStream)xc.Canonicalize(xdRefd);
                byte []          baRefd = new byte[msRefd.Length];
                msRefd.Read(baRefd, 0, baRefd.Length);
                string       debugName = oRef.ToString();
                byte []      baDigest  = shaCsp.ComputeHash(baRefd);
                XmlElement   refElem   = plainDoc.CreateElement(Pre.ds, Elem.Reference, Ns.ds);
                XmlAttribute refUri    = plainDoc.CreateAttribute(Attrib.URI);
                refUri.Value = "#" + xaId.Value;
                refElem.Attributes.Append(refUri);
                sigInfoElem.AppendChild(refElem);
                XmlElement transsElem = plainDoc.CreateElement(Pre.ds, Elem.Transforms, Ns.ds);
                refElem.AppendChild(transsElem);
                XmlElement   transElem = plainDoc.CreateElement(Pre.ds, Elem.Transform, Ns.ds);
                XmlAttribute transAlg  = plainDoc.CreateAttribute(Attrib.Algorithm);
                transAlg.Value = Alg.xmlExcC14n;
                transElem.Attributes.Append(transAlg);
                transsElem.AppendChild(transElem);
                XmlElement   digMethElem = plainDoc.CreateElement(Pre.ds, Elem.DigestMethod, Ns.ds);
                XmlAttribute digMethAlg  = plainDoc.CreateAttribute("Algorithm");
                digMethAlg.Value = Alg.sha1;
                digMethElem.Attributes.Append(digMethAlg);
                refElem.AppendChild(digMethElem);
                XmlElement digValElem = plainDoc.CreateElement(Pre.ds, Elem.DigestValue, Ns.ds);
                digValElem.InnerText = OpenNETCF.Security.Cryptography.NativeMethods.Format.GetB64(baDigest);
                refElem.AppendChild(digValElem);
            }

            //canonical SignedInfo, get key, get signature
            XmlDocument xdSigInfo = new XmlDocument();

            xdSigInfo.LoadXml(sigInfoElem.OuterXml);
            XmlCanonicalizer xcSi      = new XmlCanonicalizer(comments, exclusive);
            MemoryStream     msSigInfo = (MemoryStream)xcSi.Canonicalize(xdSigInfo);

            byte [] baSigInfo = new byte[msSigInfo.Length];
            msSigInfo.Read(baSigInfo, 0, baSigInfo.Length);
            byte [] baSig = null;
            if (SigObj.BinSecTok != null)
            {
                byte [] baUnsigHash = shaCsp.ComputeHash(baSigInfo);
                baSig = SigObj.AsymmAlg.SignHash(baUnsigHash, "SHA");
            }
            if (SigObj.UserTok != null)
            {
                byte []  derKey = P_SHA1.DeriveKey(SigObj.ClearPassword, StrKeyLabel, SigObj.UserTok.Nonce.Text, SigObj.UserTok.Created, NumKeyBytes);
                HMACSHA1 hs     = new HMACSHA1(derKey);
                baSig = hs.ComputeHash(baSigInfo);
            }
            if (SigObj.securityContextToken != null)
            {
                //XmlElement createdElem = LameXpath.SelectSingleNode(SigObj.securityContextToken, "Created");
                //string strCreated = createdElem.InnerText; //2004-03-05T01:59:49Z
                //string label = "WS-Security";
                ////byte [] baKey = P_SHA1.DeriveKey(password, label, nonce, created, 24);
                //byte [] baKey = P_SHA1.DeriveKey(String.Empty, label, String.Empty, strCreated, 24);
                //HMACSHA1 hs = new HMACSHA1(baKey);
                //baSig = hs.ComputeHash(baSigInfo);
                byte [] hashKey;
                if (SigObj.derKeyTok != null)
                {
                    hashKey = SigObj.derKeyTok.derKey;
                }
                else
                {
                    hashKey = SigObj.securityContextKey;
                }
                HMACSHA1 hs = new HMACSHA1(hashKey);
                baSig = hs.ComputeHash(baSigInfo);
            }

            //add SignatureValue
            XmlElement sigValElem = plainDoc.CreateElement(Pre.ds, Elem.SignatureValue, Ns.ds);

            sigValElem.InnerText = OpenNETCF.Security.Cryptography.NativeMethods.Format.GetB64(baSig);
            sigElem.AppendChild(sigValElem);
            //add KeyInfo
            XmlElement   keyInfoElem   = plainDoc.CreateElement(Pre.ds, Elem.KeyInfo, Ns.ds);
            XmlElement   secTokRefElem = plainDoc.CreateElement(Pre.wsse, Elem.SecurityTokenReference, Ns.wsseLatest);
            XmlElement   sigRefElem    = plainDoc.CreateElement(Pre.wsse, Elem.Reference, Ns.wsseLatest);
            XmlAttribute uri           = plainDoc.CreateAttribute(Attrib.URI);

            uri.Value = "#" + secTokId;
            sigRefElem.Attributes.Append(uri);
            XmlAttribute valueType = plainDoc.CreateAttribute(Attrib.ValueType);

            valueType.Value = "#" + secTokId;
            sigRefElem.Attributes.Append(valueType);

            if (SigObj.UserTok != null)
            {
                XmlAttribute valType = plainDoc.CreateAttribute(Attrib.ValueType);
                valType.Value = Misc.tokenProfUsername + "#UsernameToken";
                sigRefElem.Attributes.Append(valType);
            }
            if (SigObj.BinSecTok != null)
            {
                XmlAttribute valType = plainDoc.CreateAttribute(Attrib.ValueType);
                valType.Value = Misc.tokenProfX509 + "#X509v3";
                sigRefElem.Attributes.Append(valType);
            }

            secTokRefElem.AppendChild(sigRefElem);
            keyInfoElem.AppendChild(secTokRefElem);
            sigElem.AppendChild(keyInfoElem);

            //SigObj = null;
            return(plainDoc);
        }
예제 #3
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;
            }
        }
예제 #4
0
        public static XmlDocument DecryptXml(XmlDocument cipherDoc)
        {
            SecConvObj = null;
            if (DecObj == null)
            {
                return(cipherDoc);                //no keys to decrypt with
            }
            XmlElement envelope = cipherDoc.DocumentElement;

            //add namespace
            //XmlAttribute xenc = xd.CreateAttribute(Pre.xmlns, Pre.xenc, Ns.xmlns);
            //xenc.Value = Ns.xenc;
            //envelope.Attributes.Append(xenc);

            XmlElement headerOrBody = (XmlElement)envelope.ChildNodes[0];
            XmlElement header       = null;
            XmlElement body         = null;

            if (headerOrBody.LocalName == Elem.Header)
            {
                header = (XmlElement)envelope.ChildNodes[0];
                body   = (XmlElement)envelope.ChildNodes[1];
            }
            else             //no header
            {
                body = (XmlElement)envelope.ChildNodes[0];
            }

            string encKeyMethod = null;

            byte [] baEncKey = null;
            string  encKeyId = null;
            //UsernameToken encryption
            XmlElement nonce   = null;
            XmlElement created = null;

            //search for Security in Header, remove MustUnderstand
            if (header != null)
            {
                XmlElement securityElem = LameXpath.SelectSingleNode(header, Elem.Security);
                if (securityElem != null)
                {
                    XmlAttribute mustUndAtt = securityElem.Attributes[Attrib.mustUnderstand, Ns.soap];
                    if (mustUndAtt != null)
                    {
                        mustUndAtt.Value = "0";
                    }
                    //securityElem.ParentNode.RemoveChild(securityElem);

                    XmlElement encKeyElem = LameXpath.SelectSingleNode(securityElem, Elem.EncryptedKey);
                    if (encKeyElem != null)
                    {
                        XmlElement encMethodElem = LameXpath.SelectSingleNode(encKeyElem, Elem.EncryptionMethod);
                        if (encMethodElem != null)
                        {
                            encKeyMethod = encMethodElem.Attributes[Attrib.Algorithm].Value;
                        }
                        //ignore KeyInfo, use SecurityTokenReference instead

                        XmlElement cipherValElem = LameXpath.SelectSingleNode(securityElem, Elem.CipherValue);
                        if (cipherValElem != null)
                        {
                            baEncKey = OpenNETCF.Security.Cryptography.Internal.Format.GetB64(cipherValElem.InnerText);
                        }
                    }

                    XmlElement refListElem = LameXpath.SelectSingleNode(securityElem, Elem.ReferenceList);
                    if (refListElem != null)
                    {
                        //ignore refList, just do straight to encData
                    }
                    XmlElement keyIdElem = LameXpath.SelectSingleNode(securityElem, Elem.KeyIdentifier);
                    if (keyIdElem != null)                    //get keyId
                    {
                        string valueType = keyIdElem.Attributes[Attrib.ValueType].Value;
                        //"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509SubjectKeyIdentifier
                        if (valueType.EndsWith("#X509SubjectKeyIdentifier") == false && valueType != "wsse:X509v3")
                        {
                            throw new Exception("only support X.509v3 certificates");
                        }
                        encKeyId = keyIdElem.InnerText;
                    }
                    XmlElement refElem = LameXpath.SelectSingleNode(securityElem, Elem.Reference);
                    if (refElem != null)                    //get keyUri
                    {
                        string refUri = refElem.Attributes[Attrib.URI].Value;
                    }
                    XmlElement userTokElem = LameXpath.SelectSingleNode(securityElem, Elem.UsernameToken);
                    if (userTokElem != null)
                    {
                        nonce   = LameXpath.SelectSingleNode(userTokElem, Elem.Nonce);
                        created = LameXpath.SelectSingleNode(userTokElem, Elem.Created);
                    }
                }
                //end header processing
            }

            byte [] baPlainKey = null;
            if (encKeyMethod != null)            //decrypt key, assume RSA
            {
                baPlainKey = DecObj.RSACSP.Decrypt(baEncKey, false);
                KeyExchangeFormatter fmt = DecObj.SymmAlg.KeyExchangeFormatter;
                DecObj.SymmAlg.Key.Key = baPlainKey;
            }
            //UsernameToken decryption
            if (DecObj.ClearPassword != null)
            {
                //use XmlSigHandler values, because will more than likely be signing
                int numKeyBytes = DecObj.SymmAlg.Key.Key.Length;
                if (nonce == null || created == null)
                {
                    baPlainKey = P_SHA1.DeriveKey(DecObj.ClearPassword, XmlSigHandler.StrKeyLabel, DecObj.UserTok.Nonce.Text, DecObj.UserTok.Created, numKeyBytes);
                }
                else
                {
                    baPlainKey = P_SHA1.DeriveKey(DecObj.ClearPassword, XmlSigHandler.StrKeyLabel, nonce.InnerText, created.InnerText, numKeyBytes);
                }
                DecObj.SymmAlg.Key.Key = baPlainKey;
            }

            //TODO EncryptedKey in body?, multiple EncryptedData in body

            string     encBodMethod = null;
            string     keyName      = null;
            XmlElement cipherElem   = LameXpath.SelectSingleNode(cipherDoc, Elem.EncryptedData);

            //if(cipherElem == null)
            //	return cipherDoc; //nothing to decrypt
            if (cipherElem != null)
            {
                XmlElement encMethodElemBod = LameXpath.SelectSingleNode(cipherElem, Elem.EncryptionMethod);
                if (encMethodElemBod != null)
                {
                    encBodMethod = encMethodElemBod.Attributes[Attrib.Algorithm].Value;
                    if (encBodMethod == Alg.aes128cbc)
                    {
                        if (DecObj.SymmAlg is TripleDES)
                        {
                            throw new Exception("device expects TripleDES, not AES");
                        }
                    }
                    if (encBodMethod == Alg.tripledesCbc)
                    {
                        if ((DecObj.SymmAlg is TripleDES) == false)
                        {
                            throw new Exception("device expects AES, not TripleDES");
                        }
                    }
                }
                XmlElement keyNameElem = LameXpath.SelectSingleNode(cipherElem, Elem.KeyName);
                if (keyNameElem != null)
                {
                    keyName = keyNameElem.InnerText;
                }

                XmlElement cipherValueElem = LameXpath.SelectSingleNode(cipherElem, Elem.CipherValue);
                byte[]     baCipher        = OpenNETCF.Security.Cryptography.Internal.Format.GetB64(cipherValueElem.InnerText);

                //should have encMethod, key, and cipherData now

                System.Security.Cryptography.SymmetricAlgorithm sa = DecObj.SymmAlg.Key;
                byte[] baClear = DecObj.SymmAlg.EncryptionFormatter.Decrypt(baCipher);

                /*
                 * PlainTextType ptType = PlainTextType.Content; //default
                 * if(cipherElem.Attributes["Type"] != null)
                 * {
                 *      string strType = cipherElem.Attributes["Type"].Value;
                 *      if(strType == "http://www.w3.org/2001/04/xmlenc#Element")
                 *              ptType = PlainTextType.Element;
                 * }
                 */

                string strClear = OpenNETCF.Security.Cryptography.Internal.Format.GetString(baClear); //for debugging
                cipherElem.ParentNode.InnerXml = strClear;
            }

            //MOD for SecureConversation
            //XmlElement rstrElem = LameXpath.SelectSingleNode(body, Elem.RequestSecurityToken); //temp for testing
            XmlElement rstrElem = LameXpath.SelectSingleNode(body, Elem.RequestSecurityTokenResponse);

            if (rstrElem != null)
            {
                SecConvObj = new SecConvObject();
                //<TokenType/>
                XmlElement ttElem = LameXpath.SelectSingleNode(rstrElem, Elem.TokenType);
                if (ttElem != null)
                {
                    SecConvObj.tokenType           = new TokenType();
                    SecConvObj.tokenType.InnerText = ttElem.InnerText;
                }
                //ignore <AppliesTo/> for now

                //Entropy
                XmlElement entropyElem = LameXpath.SelectSingleNode(rstrElem, Elem.Entropy);
                if (entropyElem != null)
                {
                    XmlElement encKeyElem = LameXpath.SelectSingleNode(entropyElem, Elem.EncryptedKey);
                    if (encKeyElem != null)
                    {
                        XmlElement cipherValElem = LameXpath.SelectSingleNode(encKeyElem, Elem.CipherValue);
                        if (cipherValElem != null)
                        {
                            baEncKey = OpenNETCF.Security.Cryptography.Internal.Format.GetB64(cipherValElem.InnerText);
                        }
                        XmlElement encMethodElem = LameXpath.SelectSingleNode(encKeyElem, Elem.EncryptionMethod);
                        if (encMethodElem != null)
                        {
                            encKeyMethod = encMethodElem.Attributes[Attrib.Algorithm].Value;
                            if (encKeyMethod == Alg.kwTripledes)
                            {
                                throw new Exception("return Entropy with kw-TripleDes is not supported");
                            }
                            if (encKeyMethod == Alg.kwAes128)
                            {
                                XmlElement keyNameElem = LameXpath.SelectSingleNode(encKeyElem, Elem.KeyName);
                                if (keyNameElem != null)
                                {
                                    keyName = keyNameElem.InnerText;
                                }
                                if (DecObj.SymmAlg.Key is System.Security.Cryptography.TripleDES)
                                {
                                    throw new Exception("device expects TripleDES, not AES128");
                                }
                                //the request entropy is encrypted with RSA
                                //it passes a symmetric key
                                //the response is encrypted with kw-aes128
                                //the key for the kw-aes128 seems to be the symm key passed by RSA?
                                System.Security.Cryptography.SymmetricAlgorithm sa = DecObj.keyWrap;
                                //key should have already been set
                                byte[] unwrappedKey = Decrypt(sa, baEncKey);
                                SecConvObj.entropyKey = unwrappedKey;
                            }
                            if (encKeyMethod == Alg.rsa15)
                            {
                                //TODO - this scenario is not expected?
                                XmlElement keyIdElem = LameXpath.SelectSingleNode(encKeyElem, Elem.KeyIdentifier);
                                if (keyIdElem != null)
                                {
                                    keyName = keyIdElem.InnerText;
                                }
                                baPlainKey            = DecObj.RSACSP.DecryptValue(baEncKey);
                                SecConvObj.secConvKey = baPlainKey;
                                //went from 128 bytes to 16 decrypted - AES?
                                //DecObj.SymmAlg.Key.Key = baPlainKey;
                            }
                        }
                        XmlElement carriedKeyNameElem = LameXpath.SelectSingleNode(encKeyElem, Elem.CarriedKeyName);
                        if (carriedKeyNameElem != null)
                        {
                            keyName = carriedKeyNameElem.InnerText;
                        }
                    }
                }

                //RST
                XmlElement rstElem = LameXpath.SelectSingleNode(rstrElem, Elem.RequestedSecurityToken);
                if (rstElem != null)
                {
                    SecConvObj.requestedSecurityToken = rstElem;
                }
                //RPT
                XmlElement rptElem = LameXpath.SelectSingleNode(rstrElem, Elem.RequestedProofToken);
                if (rptElem != null)
                {
                    SecConvObj.requestedProofToken = rptElem;

                    //figure out if key is computed
                    //TODO use this later on
                    bool       computed    = false;
                    XmlElement compKeyElem = LameXpath.SelectSingleNode(rptElem, Elem.ComputedKey);
                    if (compKeyElem != null)
                    {
                        computed = true;
                    }
                    if (computed == true)
                    {
                        //throw new Exception("not handling computed return keys yet");
                        byte [] entropy1        = DecObj.keyWrap.Key;
                        byte [] entropy2        = SecConvObj.entropyKey;
                        byte [] concatEntropies = new byte[entropy1.Length + entropy2.Length];
                        Array.Copy(entropy1, 0, concatEntropies, 0, entropy1.Length);
                        Array.Copy(entropy2, 0, concatEntropies, entropy1.Length, entropy2.Length);
                        SecConvObj.secConvKey = P_SHA1.DeriveKey(entropy1, entropy2, XmlSigHandler.NumKeyBytes);
                    }

                    XmlElement encMethodElemBod = LameXpath.SelectSingleNode(rptElem, Elem.EncryptionMethod);
                    if (encMethodElemBod != null)
                    {
                        encBodMethod = encMethodElemBod.Attributes[Attrib.Algorithm].Value;
                        if (encBodMethod == Alg.kwAes128)
                        {
                            //throw new Exception("only supports TripleDes, no AES on device");
                            XmlElement cvElem = LameXpath.SelectSingleNode(rptElem, Elem.CipherValue);
                            //byte [] baPKey = null;
                            if (cvElem != null)
                            {
                                byte[] baCipher = OpenNETCF.Security.Cryptography.Internal.Format.GetB64(cvElem.InnerText);

                                int    numKeyBytes = DecObj.SymmAlg.Key.Key.Length;
                                string tempLabel   = XmlSigHandler.StrKeyLabel;                               //WS-Security

                                baPlainKey = P_SHA1.DeriveKey(DecObj.ClearPassword, tempLabel, nonce.InnerText, created.InnerText, numKeyBytes);

                                //TODO make TripleDES below work like this too - common codebase
                                System.Security.Cryptography.SymmetricAlgorithm sa = DecObj.keyWrap;
                                sa.Key = baPlainKey;
                                byte[] unwrappedKey = Decrypt(sa, baCipher);

                                SecConvObj.secConvKey = unwrappedKey;
                            }
                        }
                        else if (encBodMethod == Alg.kwTripledes)
                        {
                            XmlElement cvElem = LameXpath.SelectSingleNode(rptElem, Elem.CipherValue);
                            //byte [] baPKey = null;
                            if (cvElem != null)
                            {
                                byte[] baCipher = OpenNETCF.Security.Cryptography.Internal.Format.GetB64(cvElem.InnerText);

                                int    numKeyBytes = DecObj.SymmAlg.Key.Key.Length;
                                string tempLabel   = XmlSigHandler.StrKeyLabel;                               //WS-Security
                                //string tempLabel = "WS-SecureConversation";

                                baPlainKey = P_SHA1.DeriveKey(DecObj.ClearPassword, tempLabel, nonce.InnerText, created.InnerText, numKeyBytes);

                                //TODO make this work with KeyWrap interface
                                //SymmetricAlgorithm sa = DecObj.SymmAlg;
                                System.Security.Cryptography.TripleDESCryptoServiceProvider sa = (System.Security.Cryptography.TripleDESCryptoServiceProvider)DecObj.SymmAlg.Key;
                                sa.Key = baPlainKey;
                                TripleDesKeyWrap tdkw         = new TripleDesKeyWrap(sa);
                                byte []          unwrappedKey = tdkw.DecryptValue(baCipher);

                                SecConvObj.secConvKey = unwrappedKey;
                            }
                        }
                        else                         //http://www.w3.org/2001/04/xmlenc#rsa-1_5
                        {
                            XmlElement cvElem = LameXpath.SelectSingleNode(rptElem, Elem.CipherValue);
                            byte []    baPKey = null;
                            if (cvElem != null)
                            {
                                byte[] baEKey = OpenNETCF.Security.Cryptography.Internal.Format.GetB64(cvElem.InnerText);
                                baPKey = DecObj.RSACSP.DecryptValue(baEKey);
                                SecConvObj.secConvKey = baPKey;
                            }
                        }
                    }
                    //else
                    //{
                    //	throw new Exception("EncryptionMethod not specified");
                    //}
                }
                //ignore <LifeTime/> for now
            }

            DecObj = null;
            return(cipherDoc);
        }
예제 #5
0
        public static XmlDocument EncryptXml(XmlDocument plainDoc)
        {
            if (EncObj == null)
            {
                return(plainDoc);                //nothing to encrypt
            }
            XmlElement envelope = plainDoc.DocumentElement;

            //add namespace
            //XmlAttribute xenc = xd.CreateAttribute(Pre.xmlns, Pre.xenc, Ns.xmlns);
            //xenc.Value = Ns.xenc;
            //envelope.Attributes.Append(xenc);

            XmlElement headerOrBody = (XmlElement)envelope.ChildNodes[0];
            XmlElement header;
            XmlElement body;

            if (headerOrBody.LocalName == Elem.Body)
            {
                header = plainDoc.CreateElement(headerOrBody.Prefix, Elem.Header, headerOrBody.NamespaceURI);
                envelope.InsertBefore(header, headerOrBody);
            }
            header = (XmlElement)envelope.ChildNodes[0];
            body   = (XmlElement)envelope.ChildNodes[1];
            XmlNodeList headers  = header.ChildNodes;
            XmlElement  security = null;

            foreach (XmlNode xn in headers)
            {
                if (xn.LocalName == Elem.Security)
                {
                    security = (XmlElement)xn;
                }
            }
            if (security == null)
            {
                //used to work for SymmetricEncryptionV1
                //if(EncObj.SecTokRef != null) //symmetric is older
                //	security = plainDoc.CreateElement(Pre.wsse, Elem.Security, Ns.wsse0207);
                //else //newest
                security = plainDoc.CreateElement(Pre.wsse, Elem.Security, Ns.wsseLatest);
                XmlAttribute mustUnderstand = plainDoc.CreateAttribute(Pre.soap, Attrib.mustUnderstand, Ns.soap);
                mustUnderstand.Value = "1";
                security.Attributes.Append(mustUnderstand);
                header.AppendChild(security);
            }
            XmlElement tokenElem = null;

            if (EncObj.UserTok != null)
            {
                XmlElement userTokElem = LameXpath.SelectSingleNode(security, Elem.UsernameToken);
                if (userTokElem == null)
                {
                    EncObj.UserTok.WriteXml(plainDoc, security);
                }
                tokenElem = userTokElem;
                //secTokId = SigObj.UserTok.Id;
                //sigAlgVal = "http://www.w3.org/2000/09/xmldsig#hmac-sha1";
            }

            /*
             * <wsse:Security soap:mustUnderstand="1">
             * <wsse:BinarySecurityToken ValueType="wsse:X509v3"
             *      EncodingType="wsse:Base64Binary"
             *      xmlns:wsu="http://schemas.xmlsoap.org/ws/2002/07/utility"
             *      wsu:Id="SecurityToken-b2adaba3-09f7-45a0-aa0d-0c4da15d0725">
             *              MIIBxDCCAW6...==
             * </wsse:BinarySecurityToken>
             * </wsse:Security>
             */
            if (EncObj.BinSecTok != null)
            {
                XmlElement binSecTok = LameXpath.SelectSingleNode(security, Elem.BinarySecurityToken);
                if (binSecTok == null)
                {
                    EncObj.BinSecTok.WriteXml(plainDoc, security);
                }

                tokenElem = binSecTok;
            }

            /*
             * <wsse:Security soap:mustUnderstand="1" xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/07/secext">
             * <xenc:ReferenceList xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
             * <xenc:DataReference URI="#EncryptedContent-c163b16f-44c7-4eea-ac65-a6ce744e2651" />
             * </xenc:ReferenceList>
             * </wsse:Security>
             */
            if (EncObj.SecTokRef != null)            // || EncObj.ClearPassword != null
            {
                //security.Attributes["xmlns"].Value = Ns.wsse0207;

                XmlElement   referenceList = plainDoc.CreateElement(Pre.xenc, Elem.ReferenceList, Ns.xenc);
                XmlElement   dataReference = plainDoc.CreateElement(Pre.xenc, Elem.DataReference, Ns.xenc);
                XmlAttribute uri           = plainDoc.CreateAttribute(Attrib.URI);
                uri.Value = "#" + EncObj.Id;
                dataReference.Attributes.Append(uri);
                referenceList.AppendChild(dataReference);
                if (SignFirst == false)
                {
                    security.AppendChild(referenceList);                     //just append
                }
                else
                {
                    security.InsertAfter(referenceList, tokenElem);                     //after token
                }
            }

            /*
             * <wsse:Security soap:mustUnderstand="1">
             * <xenc:EncryptedKey xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
             *  <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" />
             *  <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
             *    <wsse:SecurityTokenReference>
             *      <wsse:KeyIdentifier ValueType="wsse:X509v3">gBfo0147lM6cKnTbbMSuMVvmFY4=</wsse:KeyIdentifier>
             *    </wsse:SecurityTokenReference>
             *  </KeyInfo>
             *  <xenc:CipherData>
             *    <xenc:CipherValue>CKc0qzMkc...==</xenc:CipherValue>
             *  </xenc:CipherData>
             *  <xenc:ReferenceList>
             *    <xenc:DataReference URI="#EncryptedContent-702cd57e-c5ca-44c6-9bd8-b8639762b036" />
             *  </xenc:ReferenceList>
             * </xenc:EncryptedKey>
             * </wsse:Security>
             */
            if (EncObj.EncKey != null)
            {
                XmlElement encKeyElem = plainDoc.CreateElement(Pre.xenc, Elem.EncryptedKey, Ns.xenc);

                XmlElement   encMethElem = plainDoc.CreateElement(Pre.xenc, Elem.EncryptionMethod, Ns.xenc);
                XmlAttribute alg         = plainDoc.CreateAttribute(Attrib.Algorithm);
                alg.Value = Alg.rsa15;
                encMethElem.Attributes.Append(alg);
                encKeyElem.AppendChild(encMethElem);

                XmlElement   keyInfoElem   = plainDoc.CreateElement(Pre.ds, Elem.KeyInfo, Ns.ds);
                XmlElement   secTokRefElem = plainDoc.CreateElement(Pre.wsse, Elem.SecurityTokenReference, Ns.wsseLatest);
                XmlElement   keyIdElem     = plainDoc.CreateElement(Pre.wsse, Elem.KeyIdentifier, Ns.wsseLatest);
                XmlAttribute valueType     = plainDoc.CreateAttribute(Attrib.ValueType);
                //valueType.Value = "wsse:X509v3";
                valueType.Value = Misc.tokenProfX509 + "#X509SubjectKeyIdentifier";
                keyIdElem.Attributes.Append(valueType);
                keyIdElem.InnerText = EncObj.KeyId;
                secTokRefElem.AppendChild(keyIdElem);
                keyInfoElem.AppendChild(secTokRefElem);
                encKeyElem.AppendChild(keyInfoElem);

                //encrypt key
                EncryptionFormatter fmt          = EncObj.SymmAlg.EncryptionFormatter;
                byte []             baSessKey    = EncObj.SymmAlg.Key.Key;
                byte []             baEncSessKey = EncObj.RSACSP.Encrypt(baSessKey, false);     //ok to use since the key is of the right size - no padding required
                XmlElement          ciphDataElem = plainDoc.CreateElement(Pre.xenc, Elem.CipherData, Ns.xenc);
                XmlElement          ciphValElem  = plainDoc.CreateElement(Pre.xenc, Elem.CipherValue, Ns.xenc);
                ciphValElem.InnerText = OpenNETCF.Security.Cryptography.Internal.Format.GetB64(baEncSessKey);
                ciphDataElem.AppendChild(ciphValElem);
                encKeyElem.AppendChild(ciphDataElem);

                XmlElement   refListElem = plainDoc.CreateElement(Pre.xenc, Elem.ReferenceList, Ns.xenc);
                XmlElement   dataRefElem = plainDoc.CreateElement(Pre.xenc, Elem.DataReference, Ns.xenc);
                XmlAttribute uri         = plainDoc.CreateAttribute(Attrib.URI);
                uri.Value = "#" + EncObj.Id;
                dataRefElem.Attributes.Append(uri);
                refListElem.AppendChild(dataRefElem);
                encKeyElem.AppendChild(refListElem);

                //security.PrependChild(encKeyElem);
                if (SignFirst == false)
                {
                    security.AppendChild(encKeyElem);                     //just append
                }
                else
                {
                    security.InsertAfter(encKeyElem, tokenElem);                     //after token
                }
            }
            //SecurityContextToken - add here, or with Signature
            string secTokId = null;

            if (EncObj.securityContextToken != null)
            {
                XmlNode sctNode = LameXpath.SelectSingleNode(header, Elem.SecurityContextToken);

                if (sctNode == null)
                {
                    //i need to import this node 1st
                    sctNode = plainDoc.ImportNode(EncObj.securityContextToken, true);
                    string     dupeId   = sctNode.Attributes[Attrib.Id, Ns.wsuLatest].Value;
                    XmlElement dupeElem = LameXpath.SelectSingleNode(dupeId, security);
                    if (dupeElem == null)
                    {
                        security.AppendChild(sctNode);
                    }
                    else
                    {
                        sctNode = LameXpath.SelectSingleNode(dupeId, security);
                    }
                }
                //<wsse:SecurityContextToken wsu:Id=\"SecurityToken-feb27552-6eb5-4a27-a831-e1bdfca326e2\">
                secTokId = sctNode.Attributes[Attrib.Id, Ns.wsuLatest].Value;

                //add ReferenceList too for SecureConversation
                //<xenc:ReferenceList xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
                //  <xenc:DataReference URI="#EncryptedContent-cb7efc1c-e4dd-4737-9214-aec967789d2d" />
                //</xenc:ReferenceList>
                XmlElement referenceListElem = plainDoc.CreateElement(Pre.xenc, Elem.ReferenceList, Ns.xenc);
                //security.AppendChild(referenceListElem);
                XmlElement   dataReferenceElem = plainDoc.CreateElement(Pre.xenc, Elem.DataReference, Ns.xenc);
                XmlAttribute uriAttrib         = plainDoc.CreateAttribute(Attrib.URI);
                uriAttrib.Value = "#" + EncObj.Id;
                dataReferenceElem.Attributes.Append(uriAttrib);
                referenceListElem.AppendChild(dataReferenceElem);
                security.InsertAfter(referenceListElem, sctNode);

                if (EncObj.derKeyTok != null)
                {
                    XmlNode idElem = LameXpath.SelectSingleNode(sctNode, Elem.Identifier);
                    if (idElem != null)
                    {
                        EncObj.derKeyTok.secTokRef.Reference.URI = idElem.InnerText;
                    }

                    XmlElement derKeyTokElem = EncObj.derKeyTok.WriteXml(plainDoc, security, (XmlElement)sctNode);
                    secTokId = EncObj.derKeyTok.id;

                    EncObj.SymmAlg.Key.Key = EncObj.derKeyTok.derKey;
                }
            }

            if (EncObj.UserTok != null)
            {
                int     numBytes = EncObj.SymmAlg.Key.Key.Length;
                byte [] derKey   = P_SHA1.DeriveKey(EncObj.ClearPassword, XmlSigHandler.StrKeyLabel, EncObj.UserTok.Nonce.Text, EncObj.UserTok.Created, numBytes);
                EncObj.SymmAlg.Key.Key = derKey;
            }

            //possibly add BinSecTok, but dont encrypt
            if (EncObj.SymmAlg == null)
            {
                return(plainDoc);
            }
            if (EncObj.RSACSP == null && EncObj.UserTok == null && EncObj.securityContextKey == null && (EncObj.derKeyTok == null || EncObj.derKeyTok.derKey == null))
            {
                return(plainDoc);
            }

            XmlElement plainElement = LameXpath.SelectSingleNode(envelope, EncObj.TargetElement);

            if (plainElement == null)
            {
                throw new Exception("element not found to encrypt");
            }

            byte [] baPlain;
            if (EncObj.Type == PlainTextType.Element)
            {
                baPlain = OpenNETCF.Security.Cryptography.Internal.Format.GetBytes(plainElement.OuterXml);
            }
            else if (EncObj.Type == PlainTextType.Content)
            {
                baPlain = OpenNETCF.Security.Cryptography.Internal.Format.GetBytes(plainElement.InnerXml);
            }
            else
            {
                throw new Exception("only support #Element and #Content");
            }

            //diff algorithms
            System.Security.Cryptography.SymmetricAlgorithm sa = EncObj.SymmAlg.Key;
            byte[] baCipher = EncObj.SymmAlg.EncryptionFormatter.Encrypt(baPlain);

            /*
             * <xenc:EncryptedData Id="EncryptedContent-c163b16f-44c7-4eea-ac65-a6ce744e2651" Type="http://www.w3.org/2001/04/xmlenc#Content" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
             * <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc" />
             * <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
             *  <KeyName>WSE Sample Symmetric Key</KeyName> //NORMAL
             *  <wsse:SecurityTokenReference> //SecureConversation
             * <wsse:Reference URI="#SecurityToken-be84969f-41c7-4dff-95a4-7319a3122142" />
             * </wsse:SecurityTokenReference>
             * </KeyInfo>
             * <xenc:CipherData>
             *  <xenc:CipherValue>1+uBlSL/pxXyl2FdeT/EVM6TZgW9cv1AjwlJ9LZyKejet9TgjK37QoURZklglS9z+yGd5XooIDhtWPLaw3ApuhRCky6Y8eP1+3mT6v+t3o28idscfYOrkFmVaI25AwHK</xenc:CipherValue>
             * </xenc:CipherData>
             * </xenc:EncryptedData>
             */
            XmlElement   encryptedData = plainDoc.CreateElement(Pre.xenc, Elem.EncryptedData, Ns.xenc);
            XmlAttribute id            = plainDoc.CreateAttribute(Attrib.Id);

            id.Value = EncObj.Id;
            encryptedData.Attributes.Append(id);
            XmlAttribute type = plainDoc.CreateAttribute(Attrib.Type);

            type.Value = Misc.plainTextTypeContent;             //xeo.Type.ToString();
            encryptedData.Attributes.Append(type);
            XmlElement   encryptionMethod = plainDoc.CreateElement(Pre.xenc, Elem.EncryptionMethod, Ns.xenc);
            XmlAttribute algorithm        = plainDoc.CreateAttribute(Attrib.Algorithm);

            if (EncObj.SymmAlg is TripleDES)
            {
                algorithm.Value = Alg.tripledesCbc;                 //xeo.AlgorithmEnum.ToString();
            }
            else
            {
                algorithm.Value = Alg.aes128cbc;
            }
            encryptionMethod.Attributes.Append(algorithm);
            encryptedData.AppendChild(encryptionMethod);
            if ((EncObj.KeyName != null && EncObj.KeyName != String.Empty) || EncObj.securityContextToken != null || EncObj.ClearPassword != null)
            {
                XmlElement keyInfo = plainDoc.CreateElement(Pre.ds, Elem.KeyInfo, Ns.ds);
                if (EncObj.KeyName != null && EncObj.KeyName != String.Empty)
                {
                    XmlElement keyName = plainDoc.CreateElement(Pre.ds, Elem.KeyName, Ns.ds);
                    keyName.InnerText = EncObj.KeyName;
                    keyInfo.AppendChild(keyName);
                }
                if (EncObj.securityContextToken != null || EncObj.ClearPassword != null)
                {
                    XmlElement securityTokenReferenceElem = plainDoc.CreateElement(Pre.wsse, Elem.SecurityTokenReference, Ns.wsseLatest);
                    keyInfo.AppendChild(securityTokenReferenceElem);
                    XmlElement referenceElem = plainDoc.CreateElement(Pre.wsse, Elem.Reference, Ns.wsseLatest);
                    securityTokenReferenceElem.AppendChild(referenceElem);
                    if (EncObj.securityContextToken != null)
                    {
                        XmlAttribute uriAttrib = plainDoc.CreateAttribute(Attrib.URI);
                        uriAttrib.Value = "#" + secTokId;
                        referenceElem.Attributes.Append(uriAttrib);
                    }
                    if (EncObj.UserTok != null)
                    {
                        XmlAttribute uriAttrib = plainDoc.CreateAttribute(Attrib.URI);
                        uriAttrib.Value = "#" + EncObj.UserTok.Id;
                        referenceElem.Attributes.Append(uriAttrib);

                        XmlAttribute valueTypeAttrib = plainDoc.CreateAttribute(Attrib.ValueType);
                        valueTypeAttrib.Value = Misc.tokenProfUsername + "#UsernameToken";
                        referenceElem.Attributes.Append(valueTypeAttrib);
                    }
                }
                encryptedData.AppendChild(keyInfo);
            }
            XmlElement cipherData  = plainDoc.CreateElement(Pre.xenc, Elem.CipherData, Ns.xenc);
            XmlElement cipherValue = plainDoc.CreateElement(Pre.xenc, Elem.CipherValue, Ns.xenc);

            cipherValue.InnerText = OpenNETCF.Security.Cryptography.Internal.Format.GetB64(baCipher);
            cipherData.AppendChild(cipherValue);
            encryptedData.AppendChild(cipherData);

            if (EncObj.Type == PlainTextType.Element)
            {
                plainElement.ParentNode.InnerXml = encryptedData.OuterXml;
            }
            else             //content
            {
                plainElement.InnerXml = encryptedData.OuterXml;
            }

            SecConvObj = null;
            EncObj     = null;
            return(plainDoc);
        }
예제 #6
0
        public static void TokenIssuerOut(XmlDocument plainDoc)
        {
            if (SecConv == null)
            {
                return;                 //nothing to secureConversate :)
            }
            XmlElement envelope = plainDoc.DocumentElement;

            XmlElement headerOrBody = (XmlElement)envelope.ChildNodes[0];
            XmlElement header;
            XmlElement body;

            if (headerOrBody.LocalName == Elem.Body)
            {
                header = plainDoc.CreateElement(headerOrBody.Prefix, Elem.Header, headerOrBody.NamespaceURI);
                envelope.InsertBefore(header, headerOrBody);
            }
            header = (XmlElement)envelope.ChildNodes[0];
            body   = (XmlElement)envelope.ChildNodes[1];

            //TODO header for actual request?

            //do request token stuff to Body
            //<wst:RequestSecurityToken xmlns:wst="http://schemas.xmlsoap.org/ws/2004/04/trust">
            XmlElement reqSecTokElem = LameXpath.SelectSingleNode(body, Elem.RequestSecurityToken);

            if (reqSecTokElem != null)
            {
                //<wst:TokenType>http://schemas.xmlsoap.org/ws/2004/04/security/sc/sct</wst:TokenType>
                XmlElement tokenTypeElem = plainDoc.CreateElement(Pre.wst, Elem.TokenType, Ns.wst);
                tokenTypeElem.InnerText = SecConv.tokenType.InnerText;
                reqSecTokElem.AppendChild(tokenTypeElem);

                //<wst:RequestType>http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue</wst:RequestType>
                XmlElement requestTypeElem = plainDoc.CreateElement(Pre.wst, Elem.RequestType, Ns.wst);
                requestTypeElem.InnerText = SecConv.requestType.InnerText;
                reqSecTokElem.AppendChild(requestTypeElem);

                //<wst:Base>
                //	<wsse:SecurityTokenReference>
                //		<wsse:Reference URI="#SecurityToken-b2aa8429-e44f-42a3-b181-f068f5c23cba" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#UsernameToken" />
                //		<wsse:KeyIdentifier ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509SubjectKeyIdentifier">bBwPfItvKp3b6TNDq+14qs58VJQ=</wsse:KeyIdentifier>
                //	</wsse:SecurityTokenReference>
                //</wst:Base>
                XmlElement baseElem = plainDoc.CreateElement(Pre.wst, Elem.Base, Ns.wst);
                reqSecTokElem.AppendChild(baseElem);
                XmlElement secTokRefElem = plainDoc.CreateElement(Pre.wsse, Elem.SecurityTokenReference, Ns.wsseLatest);
                baseElem.AppendChild(secTokRefElem);
                //if(SecConv.base_.SecurityTokenReference.Reference != null)
                //{
                XmlElement refElem = plainDoc.CreateElement(Pre.wsse, Elem.Reference, Ns.wsseLatest);
                secTokRefElem.AppendChild(refElem);
                XmlAttribute uriAttrib = plainDoc.CreateAttribute(Attrib.URI);
                uriAttrib.Value = SecConv.base_.SecurityTokenReference.Reference.URI;
                refElem.Attributes.Append(uriAttrib);
                XmlAttribute valTypeAttrib = plainDoc.CreateAttribute(Attrib.ValueType);
                valTypeAttrib.Value = SecConv.base_.SecurityTokenReference.Reference.ValueType;
                refElem.Attributes.Append(valTypeAttrib);
                //}
                //else
                //{
                //	XmlElement keyIdElem = plainDoc.CreateElement(Pre.wsse, Elem.KeyIdentifier, Ns.wsseLatest);
                //	secTokRefElem.AppendChild(keyIdElem);
                //	XmlAttribute uriAttrib = plainDoc.CreateAttribute(Attrib.URI);
                //	uriAttrib.Value = SecConv.base_.SecurityTokenReference.KeyIdentifier.URI;
                //	keyIdElem.Attributes.Append(uriAttrib);
                //	XmlAttribute valTypeAttrib = plainDoc.CreateAttribute(Attrib.ValueType);
                //	valTypeAttrib.Value = SecConv.base_.SecurityTokenReference.KeyIdentifier.ValueType;
                //	keyIdElem.Attributes.Append(valTypeAttrib);
                //	keyIdElem.InnerText = SecConv.base_.SecurityTokenReference.KeyIdentifier.InnerText;
                //}

                //<wst:Entropy>
                //	<xenc:EncryptedKey xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
                //		<xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" />
                //		<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
                //			<wsse:SecurityTokenReference>
                //				<wsse:KeyIdentifier ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509SubjectKeyIdentifier">bBwPfItvKp3b6TNDq+14qs58VJQ=</wsse:KeyIdentifier>
                //			</wsse:SecurityTokenReference>
                //		</KeyInfo>
                //		<xenc:CipherData>
                //			<xenc:CipherValue>qhCkEPVYmSVkO30i8oeD+Yj3zYqfQGvSRWt+VS3UZFTfbfZR1GGH2kL+lxySu5mwcJ6/a8NxQPfIvepNdola5NDnJU8mJJ3G8b7iQ6E7Byd6rxa4/RnYs37X3apK4vj0CQe1DyUFf4u999jllmi5nMVQ/G/ZzauKgerf5Rb1hwM=</xenc:CipherValue>
                //		</xenc:CipherData>
                //		<xenc:CarriedKeyName>SecurityToken-bbe94668-fe29-422a-bac6-9d4d41914313</xenc:CarriedKeyName>
                //	</xenc:EncryptedKey>
                //</wst:Entropy>
                if (SecConv.entropy != null)
                {
                    //TODO entropy
                    XmlElement entropyElem = plainDoc.CreateElement(Pre.wst, Elem.Entropy, Ns.wst);
                    reqSecTokElem.AppendChild(entropyElem);

                    //encrypted key
                    XmlElement encKeyElem = plainDoc.CreateElement(Pre.xenc, Elem.EncryptedKey, Ns.xenc);
                    entropyElem.AppendChild(encKeyElem);

                    //encryption method
                    XmlElement   encMethElem = plainDoc.CreateElement(Pre.xenc, Elem.EncryptionMethod, Ns.xenc);
                    XmlAttribute alg         = plainDoc.CreateAttribute(Attrib.Algorithm);
                    alg.Value = Alg.rsa15;
                    encMethElem.Attributes.Append(alg);
                    encKeyElem.AppendChild(encMethElem);

                    //key info
                    XmlElement   keyInfoElem    = plainDoc.CreateElement(Pre.ds, Elem.KeyInfo, Ns.ds);
                    XmlElement   secTokRefElem2 = plainDoc.CreateElement(Pre.wsse, Elem.SecurityTokenReference, Ns.wsseLatest);
                    XmlElement   keyIdElem      = plainDoc.CreateElement(Pre.wsse, Elem.KeyIdentifier, Ns.wsseLatest);
                    XmlAttribute valueType      = plainDoc.CreateAttribute(Attrib.ValueType);
                    //valueType.Value = "wsse:X509v3";
                    valueType.Value = Misc.tokenProfX509 + "#X509SubjectKeyIdentifier";
                    keyIdElem.Attributes.Append(valueType);
                    keyIdElem.InnerText = SecConv.KeyId;
                    secTokRefElem2.AppendChild(keyIdElem);
                    keyInfoElem.AppendChild(secTokRefElem2);
                    encKeyElem.AppendChild(keyInfoElem);

                    //encrypt key
                    byte []    baSessKey    = SecConv.SymmAlg.Key;
                    byte []    baEncSessKey = SecConv.RSACSP.EncryptValue(baSessKey);
                    XmlElement ciphDataElem = plainDoc.CreateElement(Pre.xenc, Elem.CipherData, Ns.xenc);
                    XmlElement ciphValElem  = plainDoc.CreateElement(Pre.xenc, Elem.CipherValue, Ns.xenc);
                    ciphValElem.InnerText = OpenNETCF.Security.Cryptography.NativeMethods.Format.GetB64(baEncSessKey);
                    ciphDataElem.AppendChild(ciphValElem);
                    encKeyElem.AppendChild(ciphDataElem);

                    //carried key
                    XmlElement carriedKeyNameElem = plainDoc.CreateElement(Pre.xenc, Elem.CarriedKeyName, Ns.xenc);
                    carriedKeyNameElem.InnerText = SecConv.CarriedKeyName;
                    encKeyElem.AppendChild(carriedKeyNameElem);
                }

                //<wsp:AppliesTo xmlns:wsp="http://schemas.xmlsoap.org/ws/2002/12/policy">
                //	<wsa:EndpointReference>
                //		<wsa:Address>http://localhost/SecureConvCodeService/SecureConvService.asmx</wsa:Address>
                //	</wsa:EndpointReference>
                //</wsp:AppliesTo>
                XmlElement appliesToElem = plainDoc.CreateElement(Pre.wsp, Elem.AppliesTo, Ns.wsp);
                reqSecTokElem.AppendChild(appliesToElem);
                XmlElement endRefElem = plainDoc.CreateElement(Pre.wsa, Elem.EndpointReference, Ns.wsaLatest);
                appliesToElem.AppendChild(endRefElem);
                XmlElement addressElem = plainDoc.CreateElement(Pre.wsa, Elem.Address, Ns.wsaLatest);
                addressElem.InnerText = SecConv.appliesTo.EndpointReference.Address.InnerText;
                endRefElem.AppendChild(addressElem);

                //<wst:LifeTime>
                //	<wsu:Expires>2004-06-14T17:55:18Z</wsu:Expires>
                //</wst:LifeTime>
                XmlElement lifeTimeElem = plainDoc.CreateElement(Pre.wst, Elem.LifeTime, Ns.wst);
                reqSecTokElem.AppendChild(lifeTimeElem);
                XmlElement expiresElem = plainDoc.CreateElement(Pre.wsu, Elem.Expires, Ns.wsuLatest);
                expiresElem.InnerText = SecConv.lifeTime.Expires.InnerText;
                lifeTimeElem.AppendChild(expiresElem);
            }
        }
예제 #7
0
        /*
         * ChainStream
         * BeforeSerial
         * AfterSerial
         * ChainStream
         * BeforeDeserial
         * AfterDeserial
         */

        public void BeforeDeserialize(SoapMessage message)         //StreamIn
        {
            Copy(oldStream, newStream);
            newStream.Position = 0;

            //Hack MemoryStream below because of XmlDocument bug closing stream
            byte []      tempBa    = new byte[newStream.Length];
            int          bytesRead = newStream.Read(tempBa, 0, (int)newStream.Length);
            MemoryStream ms        = new MemoryStream(tempBa);
            //BUG NOTE this closes the underlying stream on .NETcf
            XmlDocument xd = new XmlDocument();

            xd.Load(ms);             //MemoryStream will be closed now

            //INCOMING

            int        xmlSigCnt   = 0;
            XmlElement xmlSigElem  = LameXpath.SelectSingleNode(xd, Elem.Signature, null, ref xmlSigCnt);
            int        xmlEncCnt   = 0;
            XmlElement xmlEncElem  = LameXpath.SelectSingleNode(xd, Elem.EncryptedKey, null, ref xmlEncCnt);
            int        xmlEncCnt2  = 0;
            XmlElement xmlEncElem2 = LameXpath.SelectSingleNode(xd, Elem.ReferenceList, null, ref xmlEncCnt2);

            //TODO make sure not 0
            xmlEncCnt = Math.Min(xmlEncCnt, xmlEncCnt2);

            if (xmlSigElem != null && (xmlEncElem != null || xmlEncElem2 != null))
            {
                if (xmlSigCnt <= xmlEncCnt)
                {
                    //Signature then Encryption means encrypt 1st (Release)
                    XmlSigHandler.VerifySig(xd);
                    xd = XmlEncHandler.DecryptXml(xd);
                }
                else
                {
                    //Encryption then Signature means sign 1st (TechPreview) sign what you see
                    xd = XmlEncHandler.DecryptXml(xd);
                    XmlSigHandler.VerifySig(xd);
                }
                HeadersHandler.CheckHeaders(xd);
            }
            else             //default to 2.0 Release
            {
                //Trace
                XmlSigHandler.VerifySig(xd);                 //used to be after for TP
                xd = XmlEncHandler.DecryptXml(xd);
                HeadersHandler.CheckHeaders(xd);
                //timestamp and routing
            }

            //custom filters
            foreach (object oSif in InputFilters)
            {
                SoapInputFilter sif = (SoapInputFilter)oSif;
                SoapEnvelope    se  = new SoapEnvelope();
                se.LoadXml(xd.OuterXml);
                se.Context = ResponseSoapContext;
                sif.ProcessMessage(se);
                xd.LoadXml(se.OuterXml);                 //not performant
            }
            ResponseSoapContext.Clear();
            InputFilters.Clear();

            //newStream is too big now
            newStream.SetLength(0);             //doing a new MemoryStream here was bad
            XmlTextWriter xtw = new XmlTextWriter(newStream, System.Text.Encoding.UTF8);

            xtw.Namespaces = true;
            xd.WriteTo(xtw);
            xtw.Flush();
            //xtw.Close();
            newStream.Position = 0;
            return;
        }