0

I have seen some posts saying extension constructors don't exist, but I am wondering if there is another way of achieving this.

Essentially, I am tasked with building a series of web services (as message proxies) where potentially full credit card details may be passed into any of the text fields.

The problem I have is that no matter which field somebody puts a full credit card number (on purpose or otherwise), I need to ensure the data is appropriately obfuscated before allowing the data to be used or go anywhere.

Rather than coding a whole raft of explicit calls, and potentially missing fields in the process, I figured it would be great if I could modify the default behaviour of string objects to perform this check whenever they are instantiated. Then there's no chance whatsoever of the data slipping through.

Ignoring the potential performance issues with this approach, is there any way of actually achieving this?

  • 7
    are you saying that you are passing plain text credit card numbers over the wire? – Mitch Wheat Apr 02 '13 at 23:34
  • 1
    Irrespective of whether what you're doing is secure, if you needed to hold cc numbers and other data requiring obfuscation automatically, it would be better to have your own type for doing this. You could create a class/type that encapsulates the string value(s) and deals the obfuscation/encryption internally. – sambomartin Apr 02 '13 at 23:40
  • @MitchWheat - All web services are https, with at least 1024bit certs, so its not totally in the clear. The problem are all the text fields that were not intended for credit card details; for example, comments fields or customer name were not intended for credit card details, but if I do not mask them, then we could potantially end up recording them somewhere we don't want to (e.g. logging) –  Apr 03 '13 at 08:42
  • @sambomartin - I suspected that might be where I would have to go, I was just looking to see if there was an alternative. –  Apr 03 '13 at 08:43

2 Answers2

3

System.Security.SecureString class

http://msdn.microsoft.com/en-us/library/system.security.securestring.aspx

Moho
  • 15,457
  • 1
  • 30
  • 31
  • @Moho - Nice, I didn't know this class existed, so thanks for that. However I don't think it would quite resolve my problem. This string class was designed for a value where you want to obscure the entirety of the data. I'm looking to mask a portion of it instead. E.g. somebody stupidly sends through a comment field saying: "Customer 123 Renewal Payment 1111222233334444", I want to just mask the 111122******4444, not make the whole of it unreadable. –  Apr 03 '13 at 08:48
0

In the end, I opted for the approach suggested by @sambomartin

I produced a different class to encapsulate the strings in the properties of my objects.

The real trick was the implicit operator override. Coupled with some of the same interfaces as strings implement, this allowed me to create a class that (so far) operates fairly seemlessly within the code.

public class MyString : IComparable, IComparable<string>, IEnumerable<char>, IEnumerable, IEquatable<string>
{
    #region Static Operators
    public static implicit operator MyString(string value)
    {
        return new MyString(value);
    }

    public static implicit operator string(MyString value)
    {
        return value.value;
    }

    public static bool operator !=(MyString a, MyString b)
    {
        return a.value != b.value;
    }

    public static bool operator ==(MyString a, MyString b)
    {
        return a.value == b.value;
    }

    public static bool operator !=(MyString a, string b)
    {
        return a.value != b;
    }

    public static bool operator ==(MyString a, string b)
    {
        return a.value == b;
    }

    public static bool operator !=(string a, MyString b)
    {
        return a != b.value;
    }

    public static bool operator ==(string a, MyString b)
    {
        return a == b.value;
    }
    #endregion

    private string value;

    public int Length
    {
        get { return (value != null) ? value.Length : 0; }
    }

    public MyString(string value)
    {
        this.value = PciCleaner.Clean(value);
    }

    #region Object Overrides
    public override string ToString()
    {
        return value;
    }

    public override bool Equals(object obj)
    {
        return (value != null) ? value.Equals(obj) : false;
    }

    public override int GetHashCode()
    {
        return (value != null) ? value.GetHashCode() : new object().GetHashCode();
    }
    #endregion

    #region IComparable
    public int CompareTo(object obj)
    {
        return (value != null) ? value.CompareTo(obj) : -1;
    }
    #endregion

    #region IComparable<string>
    public int CompareTo(string other)
    {
        return (value != null) ? value.CompareTo(other) : -1;
    }
    #endregion

    #region IEnumerable<char>
    public IEnumerator<char> GetEnumerator()
    {
        return (value != null) ? value.GetEnumerator() : null;
    }
    #endregion

    #region IEnumerable
    IEnumerator IEnumerable.GetEnumerator()
    {
        return (value != null) ? (value as IEnumerable).GetEnumerator() : null;
    }
    #endregion

    #region IEquatable<string>
    public bool Equals(string other)
    {
        return (value != null) ? value.Equals(other) : false;
    }
    #endregion
}