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); }
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 byte [] baSessKey = EncObj.SymmAlg.Key; byte [] baEncSessKey = EncObj.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); 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 = EncObj.derKeyTok.derKey; } } if(EncObj.UserTok != null) { int numBytes = EncObj.SymmAlg.Key.Length; byte [] derKey = P_SHA1.DeriveKey(EncObj.ClearPassword, XmlSigHandler.StrKeyLabel, EncObj.UserTok.Nonce.Text, EncObj.UserTok.Created, numBytes); EncObj.SymmAlg.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.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.NativeMethods.Format.GetBytes(plainElement.OuterXml); else if(EncObj.Type == PlainTextType.Content) baPlain = OpenNETCF.Security.Cryptography.NativeMethods.Format.GetBytes(plainElement.InnerXml); else throw new Exception("only support #Element and #Content"); //diff algorithms SymmetricAlgorithm sa = EncObj.SymmAlg; sa.IV = OpenNETCF.Security.Cryptography.NativeMethods.Rand.GetRandomBytes(sa.IV.Length); byte [] baCipher = sa.EncryptValue(baPlain); byte [] baCipherIv = new byte[baCipher.Length + sa.IV.Length]; Array.Copy(sa.IV, 0, baCipherIv, 0, sa.IV.Length); Array.Copy(baCipher, 0, baCipherIv, sa.IV.Length, baCipher.Length); //byte [] baEncTest = Format.GetB64("JgiIRPjmEMW/QVXB6/KRICQrO5B9CSWo8pgqWoAA4TL2BFSkeuerfumauP6lneK8eRHz+iSG2Bcvu+4FXnYjRkQO4We7MdEL5C9HB9hFu7+GTnmTcL+aVh3Ue3bfrJq0"); //byte [] baTest = tCsp.DecryptValue(baEncTest); //string strEncText = Format.GetString(baTest); /* <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.NativeMethods.Format.GetB64(baCipherIv); 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; }
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); }
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; }