Beispiel #1
0
        public byte [] Decrypt(byte [] cipher)
        {
            //int iters = cipher.Length / 8;
            int blockSize = 8;
            int rem       = cipher.Length % blockSize;

            if (rem != 0)
            {
                throw new Exception("must be in 8 byte blocks");
            }

            byte [] lastBlock = new byte[blockSize];
            Array.Copy(cipher, cipher.Length - blockSize, lastBlock, 0, blockSize);

            //reuse passed in SymmAlg
            byte [] origKey = (byte[])_tdcsp.Key.Clone();
            byte [] origIv  = (byte[])_tdcsp.IV.Clone();
            _tdcsp.IV = lastBlock;

            _tdcsp.IV = lastBlock;

            //TODO make this support other lengths 0x01 - 0x07070707070707
            byte [] pkcs5        = new byte [] { 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08 };
            byte [] padPlus      = _tdcsp.EncryptValue(pkcs5);
            byte [] paddedCipher = new byte [cipher.Length + blockSize];
            Array.Copy(cipher, 0, paddedCipher, 0, cipher.Length);
            Array.Copy(padPlus, 0, paddedCipher, cipher.Length, blockSize);

            //no reset passed in SymmAlg
            _tdcsp.Key = origKey;
            _tdcsp.IV  = origIv;
            byte [] plain = _tdcsp.DecryptValue(paddedCipher);
            return(plain);
        }
        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.NativeMethods.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.DecryptValue(baEncKey);
                DecObj.SymmAlg.Key = baPlainKey;
            }
            //UsernameToken decryption
            if (DecObj.ClearPassword != null)
            {
                //use XmlSigHandler values, because will more than likely be signing
                int numKeyBytes = DecObj.SymmAlg.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 = 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 []    baCipherIv      = OpenNETCF.Security.Cryptography.NativeMethods.Format.GetB64(cipherValueElem.InnerText);

                //should have encMethod, key, and cipherData now

                SymmetricAlgorithm sa = DecObj.SymmAlg;
                Array.Copy(baCipherIv, 0, sa.IV, 0, sa.IV.Length);
                byte [] baCipher = new byte [baCipherIv.Length - sa.IV.Length];
                Array.Copy(baCipherIv, sa.IV.Length, baCipher, 0, baCipher.Length);
                byte [] baClear = sa.DecryptValue(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.NativeMethods.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.NativeMethods.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 is 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?
                                SymmetricAlgorithm sa = DecObj.keyWrap;
                                //key should have already been set
                                byte [] unwrappedKey = sa.DecryptValue(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 = 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.NativeMethods.Format.GetB64(cvElem.InnerText);

                                int    numKeyBytes = DecObj.SymmAlg.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
                                SymmetricAlgorithm sa = DecObj.keyWrap;
                                sa.Key = baPlainKey;
                                byte [] unwrappedKey = sa.DecryptValue(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.NativeMethods.Format.GetB64(cvElem.InnerText);

                                int    numKeyBytes = DecObj.SymmAlg.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;
                                TripleDESCryptoServiceProvider sa = (TripleDESCryptoServiceProvider)DecObj.SymmAlg;
                                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.NativeMethods.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);
        }