title: How to implement a Security token in a WCF soap response?
body: <p>I am implementing an API from a bank and they require a security token to be provided. In the header of every soap message there is something which looks as follows:</p>
  
  <pre><code>&lt;soapenv:Header&gt;
    &lt;tpw:BinarySecurityToken ValueType="MAC" Id="DesMacToken" EncodingType="Base64" Value="**xvz**"/&gt;
  &lt;/soapenv:Header&gt;
  </code></pre>
  
  <p>According to their documentation I need to generate an 8 byte MAC value on the body of each message. The MAC is generated by the CBC-MAC algorithm and DES as the block cipher. The contents of the soapenv:Body tag of each message is used as the data for the MAC calculation. </p>
  
  <p>So my question is how do I get WCF to do this? I have put the following code together to create the MAC value, but am unsure how to get this into the header of every message.</p>
  
  <pre><code>private string GenerateMAC(string SoapXML)
          {
              ASCIIEncoding encoding = new ASCIIEncoding();
  
              //Convert from Hex to Bin
              byte[] Key = StringToByteArray(HexKey);
              //Convert String to Bytes
              byte[] XML = encoding.GetBytes(SoapXML);
  
              //Perform the Mac goodies
              MACTripleDES DesMac = new MACTripleDES(Key);
              byte[] Mac = DesMac.ComputeHash(XML);
  
              //Base64 the Mac
              string Base64Mac = Convert.ToBase64String(Mac);
  
              return Base64Mac;
          }
  
          public static byte[] StringToByteArray(string Hex)
          {
              if (Hex.Length % 2 != 0)
              {
                  throw new ArgumentException();
              }
  
              byte[] HexAsBin = new byte[Hex.Length / 2];
              for (int index = 0; index &lt; HexAsBin.Length; index++)
              {
                  string bytevalue = Hex.Substring(index * 2, 2);
                  HexAsBin[index] = Convert.ToByte(bytevalue, 16);
              }
  
              return HexAsBin;
          }
  </code></pre>
  
  <p>Any help will be greatly appreciated.</p>
  
  <p><strong>More info:</strong>
  The bank has provided a WSDL which I have used as a service reference. An example of a response that is sent:</p>
  
  <pre><code>[System.Diagnostics.DebuggerStepThroughAttribute()]
  [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
  [System.ServiceModel.MessageContractAttribute(WrapperName="LogonRequest", WrapperNamespace="http://webservice.com", IsWrapped=true)]
  public partial class LogonRequest {
  
      [System.ServiceModel.MessageHeaderAttribute(Namespace="http://webservice.com")]
      public DataAccess.BankService.BinarySecurityToken BinarySecurityToken;
  </code></pre>
  
  <p>The BinarySecurityToken (that goes in the header) looks as follows:</p>
  
  <pre><code> [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.0.30319.233")]
      [System.SerializableAttribute()]
      [System.Diagnostics.DebuggerStepThroughAttribute()]
      [System.ComponentModel.DesignerCategoryAttribute("code")]
      [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="http://webservice.com")]
      public partial class BinarySecurityToken : object, System.ComponentModel.INotifyPropertyChanged {
  
          private string valueTypeField;
  
          private string idField;
  
          private string encodingTypeField;
  
          private string valueField;
  
          public BinarySecurityToken() {
              this.valueTypeField = "MAC";
              this.idField = "DesMacToken";
              this.encodingTypeField = "Base64";
          }
  </code></pre>