namespace com.hitrust.trustpay.client { using System; using System.Text; public class Base64 { private const int EIGHT_BIT_MASK = 0xff; private const int LOWER_CASE_A_VALUE = 0x1a; private int mIndex = 0; private string mString; private const int PLUS_VALUE = 0x3e; private const int SIX_BIT_MASK = 0x3f; private const int SLASH_VALUE = 0x3f; private const int ZERO_VALUE = 0x34; private int convertUnsignedByteToInt(byte b) { if (b >= 0) { return b; } return (0x100 + b); } public byte[] decode(string data) { this.mString = data; this.mIndex = 0; int mUsefulLength = 0; int length = this.mString.Length; for (int i = 0; i < length; i++) { if (this.isUsefulChar(this.mString[i])) { mUsefulLength++; } } int byteArrayLength = (mUsefulLength * 3) / 4; byte[] result = new byte[byteArrayLength]; int byteTriplet = 0; int byteIndex = 0; while ((byteIndex + 2) < byteArrayLength) { byteTriplet = this.mapCharToInt(this.NextUsefulChar) << 6; byteTriplet |= this.mapCharToInt(this.NextUsefulChar); byteTriplet = byteTriplet << 6; byteTriplet |= this.mapCharToInt(this.NextUsefulChar); byteTriplet = byteTriplet << 6; byteTriplet |= this.mapCharToInt(this.NextUsefulChar); result[byteIndex + 2] = (byte) (byteTriplet & 0xff); byteTriplet = byteTriplet >> 8; result[byteIndex + 1] = (byte) (byteTriplet & 0xff); byteTriplet = byteTriplet >> 8; result[byteIndex] = (byte) (byteTriplet & 0xff); byteIndex += 3; } if (byteIndex == (byteArrayLength - 1)) { byteTriplet = this.mapCharToInt(this.NextUsefulChar) << 6; byteTriplet |= this.mapCharToInt(this.NextUsefulChar); byteTriplet = byteTriplet >> 4; result[byteIndex] = (byte) (byteTriplet & 0xff); } if (byteIndex == (byteArrayLength - 2)) { byteTriplet = this.mapCharToInt(this.NextUsefulChar) << 6; byteTriplet |= this.mapCharToInt(this.NextUsefulChar); byteTriplet = byteTriplet << 6; byteTriplet |= this.mapCharToInt(this.NextUsefulChar); byteTriplet = byteTriplet >> 2; result[byteIndex + 1] = (byte) (byteTriplet & 0xff); byteTriplet = byteTriplet >> 8; result[byteIndex] = (byte) (byteTriplet & 0xff); } return result; } public string encode(byte[] data) { byte b3; byte b2; byte b1; int charCount = ((data.Length * 4) / 3) + 4; StringBuilder result = new StringBuilder((charCount * 0x4d) / 0x4c); int byteArrayLength = data.Length; int byteArrayIndex = 0; int byteTriplet = 0; while (byteArrayIndex < (byteArrayLength - 2)) { byteTriplet = this.convertUnsignedByteToInt(data[byteArrayIndex++]) << 8; byteTriplet |= this.convertUnsignedByteToInt(data[byteArrayIndex++]); byteTriplet = byteTriplet << 8; byteTriplet |= this.convertUnsignedByteToInt(data[byteArrayIndex++]); byte b4 = (byte) (0x3f & byteTriplet); byteTriplet = byteTriplet >> 6; b3 = (byte) (0x3f & byteTriplet); byteTriplet = byteTriplet >> 6; b2 = (byte) (0x3f & byteTriplet); byteTriplet = byteTriplet >> 6; b1 = (byte) (0x3f & byteTriplet); result.Append(this.mapByteToChar(b1)); result.Append(this.mapByteToChar(b2)); result.Append(this.mapByteToChar(b3)); result.Append(this.mapByteToChar(b4)); } if (byteArrayIndex == (byteArrayLength - 1)) { byteTriplet = this.convertUnsignedByteToInt(data[byteArrayIndex++]) << 4; b2 = (byte) (0x3f & byteTriplet); byteTriplet = byteTriplet >> 6; b1 = (byte) (0x3f & byteTriplet); result.Append(this.mapByteToChar(b1)); result.Append(this.mapByteToChar(b2)); result.Append("=="); } if (byteArrayIndex == (byteArrayLength - 2)) { byteTriplet = this.convertUnsignedByteToInt(data[byteArrayIndex++]) << 8; byteTriplet |= this.convertUnsignedByteToInt(data[byteArrayIndex++]); byteTriplet = byteTriplet << 2; b3 = (byte) (0x3f & byteTriplet); byteTriplet = byteTriplet >> 6; b2 = (byte) (0x3f & byteTriplet); byteTriplet = byteTriplet >> 6; b1 = (byte) (0x3f & byteTriplet); result.Append(this.mapByteToChar(b1)); result.Append(this.mapByteToChar(b2)); result.Append(this.mapByteToChar(b3)); result.Append("="); } return result.ToString(); } private bool isUsefulChar(char c) { return (((((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z'))) || (((c >= '0') && (c <= '9')) || (c == '+'))) || (c == '/')); } private char mapByteToChar(byte b) { if (b < 0x1a) { return (char) (0x41 + b); } if (b < 0x34) { return (char) (0x61 + (b - 0x1a)); } if (b < 0x3e) { return (char) (0x30 + (b - 0x34)); } if (b == 0x3e) { return '+'; } if (b != 0x3f) { throw new ArgumentException("Byte " + b + " is not a valid Base64 value"); } return '/'; } private int mapCharToInt(char c) { if ((c >= 'A') && (c <= 'Z')) { return (c - 'A'); } if ((c >= 'a') && (c <= 'z')) { return ((c - 'a') + 0x1a); } if ((c >= '0') && (c <= '9')) { return ((c - '0') + 0x34); } if (c == '+') { return 0x3e; } if (c != '/') { throw new ArgumentException(c + " is not a valid Base64 character."); } return 0x3f; } private char NextUsefulChar { get { char result = '_'; while (!this.isUsefulChar(result)) { result = this.mString[this.mIndex++]; } return result; } } } }