An SOA odyssey

Friday, May 05, 2006

Message Security

As we gear up for the final deliverable (code-named Bread & Butter) of our project, one of the requirements we've implemented is message security.

Essentially, in this deliverable we'll be dealing with financial information and in order to comply with the Payment Card Industry Data Security Standard we need to be able to protect credit card and bank account information. This is also a part of a larger security initiative within the organization whereby data elements are tagged with a protection level and treated accordingly and includes the deployment of a PKI (public key infrastructure) solution.

Although that initiative is not yet in full swing we've implemented the ablility within our services to tag specific schema elements and attributes as requiring protection and then encrypting and decrypting those elements and attributes using public key cryptography.

Our solution includes the following components:

  • Encryption components – these are set of common components with a pluggable interface that allows for the encryption and decryption of fields and properties within .NET objects using public key encryption (in our first release just RSA is supported).


  • Message Encryption Handler – an EDAF handler that can be used to encrypt or decrypt messages sent to and from services


  • In the remainder of this post we'll look at the encryption components.

    Encryption Components
    The set of encryption components we've built are implemented in two assemblies named Compassion.Services.Security.Attributes.dll and Compassion.Services.Security.Common.dll. The types that are implemented in the two assemblies are discussed below.

    Compassion.Services.Security.Attribute
    This assembly contains the following types.

  • ProtectedDataAttribute class – this attribute can be used to decorate fields or properties within an object like so.

    [ProtectedData(EncryptionFormat.Inline)]
    public string AccountNumber;



  • EncryptionFormat enumeration – this enumeration is used to specify which encryption technique will be used to encrypt the data within the field or property marked with the attribute. Valid values include Inline and XMLEnc. Inline has been implemented in this release and will specify that data is encrypted directly within the parent element as in the following example.

    <CreditCardPaymentSourceData>
    <CardholderName>Daniel Ducat</CardholderName>
    <ExpirationDate>2007-03-31T00:00:00.0000000-07:00</ExpirationDate>
    <AccountNumber>AkxcG3qHALhDzqd+5Gxrod1tb2q7V8tYQ5MyJxfk/oFd+J0HkPPM
    +J67hMfq2XMgw97kmuDKqnlhiGA7KE3SNkLNAkvmPMwuWUCn7djOEPLKHb+7MDkN
    4JAX2rIGvgr0N1etazudfegNtGRg3fhLp2Nl8lTD8O/KY5gHVA051mU=
    </AccountNumber>
    <CardType>Visa</CardType>
    <Description>****1111</Description>
    </CreditCardPaymentSourceData>


    The value XMLEnc will be used to specify that the W3C XML Encryption Syntax and Processing specification will be used For example, that specification allows for the encryption of individual elements like so:


    <?xml version='1.0'?>
    <PaymentInfo xmlns='http://example.org/paymentv2'>
    <Name>John Smith</Name>
    <CreditCard Limit='5,000' Currency='USD'>
    <Number>4019 2445 0277 5567</Number>
    <Issuer>Example Bank</Issuer>
    <Expiration>04/02</Expiration>
    </CreditCard>
    </PaymentInfo>


    Where the CreditCard element is then encrypted as:


    <?xml version='1.0'?>
    <PaymentInfo xmlns='http://example.org/paymentv2'>
    <Name>John Smith</Name>
    <CreditCard Limit='5,000' Currency='USD'>
    <EncryptedData
    xmlns='http://www.w3.org/2001/04/xmlenc#'
    Type='http://www.w3.org/2001/04/xmlenc#Content'>
    <CipherData>
    <CipherValue>A23B45C56</CipherValue>
    </CipherData>
    </EncryptedData>
    </CreditCard>
    </PaymentInfo>


    The .NET Framework 2.0 exposes objects in the System.Security.Cryptography.Xml namespace to perform this encryption automatically. In order to implement this in the .NET Framework v1.1 the .NET component that will be implemented must perform the encryption behind the scenes. When we move to .NET 2.0 we’ll likely want to reimplement this class accordingly.

    Compassion.Services.Security.Common
    This assembly contains the following types.

  • IAsymmetricKeyProvider interface – this interface provides the methods used to retrieve key information and return a class derived from the System.Security.Cryptography.AsymmetricAlgorithm .NET type. The idea here is to abstract the retrieval of key information from the implementation of the encryption so that different providers may be implemented in the future. For example, the PKI project in our organization would provide a PKI server and key information could be retrieved using a provider that implements this interface.


  • KeyFileProvider class – because there is no PKI infrastructure in place today the provider that was built knows how to retrieve key information from XML files given the AsymmetricAlgorithm to use and a path. Application will configure the paths to the key information and protect those keys using NTFS permissions.


  • AsymmetricEncryptor class – this class uses the key provider to encrypt and decrypt data and can do so for both strings and byte arrays. This class may be used independently of the ObjectEncryptor by applications.


  • ObjectEncryptor class – this class uses the AsymmetricEncryptor to encrypt and decrypt objects which have fields or properties marked with the ProtectedDataAttribute. Clients such as the MessageEncryptionHandler we'll discuss in the next post may use this object to encrypt and decrypt messages as in the following example:

    RSACryptoServiceProvider aag =
    new RSACryptoServiceProvider();
    KeyFileProvider kfPublic = new KeyFileProvider(aag,
    @"C:\PublicOnlyKey.xml");
    ObjectEncryptor.Encrypt(pcr, kfPublic);

    Here the client instantiates the asymmetric algorithm to use, passes that into the IAsymmetricKeyProvider (in this case along with the path to the key) and finally uses the Encrypt method of the ObjectEncryptor to encrypt the object. Since the object is passed by reference the object will contain the newly encrypted data.


  • Next time we'll look at the handler we implemented so that service operations can encrypt and decrypt data.

    1 Comments:

    Anonymous Tim Ferris said...

    Hi Dan

    Enjoy your blog, lots of good information in there. However for your security component I would have expected to see you use WS-Security.

    Any reasons why not?

    3:19 PM

     

    Post a Comment

    << Home