/*public MSRTrackData RetrieveTrackData(byte[] trackInformation) * { * MSRTrackData trackData = new MSRTrackData() * { * PANData = string.Empty, * Name = string.Empty, * ExpirationDate = string.Empty, * DiscretionaryData = string.Empty * }; * * // xF�E�t�24180001234563^FDCS TEST CARD /MASTERCARD^25121010001111123456789012?C� * //string decryptedTrack = ConversionHelper.ByteArrayToUTF8String(trackInformation); * //string decryptedTrack = ConversionHelper.ByteArrayToAsciiString(trackInformation); * * // xF?E?t?24180001234563^FDCS TEST CARD /MASTERCARD^25121010001111123456789012?C? * string decryptedTrack = Regex.Replace(ConversionHelper.ByteArrayToAsciiString(trackInformation), @"[^\u0020-\u007E]", string.Empty); * * // expected format: PAN^NAME^ADDITIONAL DATA^DISCRETIONARY DATA * //MatchCollection match = Regex.Matches(decryptedTrack, "(?:[^^^?]+)", RegexOptions.Compiled); * MatchCollection match = Regex.Matches(decryptedTrack, "([^^^]+)", RegexOptions.Compiled); * * if (match.Count >= 3) * { * // PAN DATA * MatchCollection pan = Regex.Matches(match[0].Value, "(?:[^^^?]+)", RegexOptions.Compiled); * * if (pan.Count >= 4) * { * trackData.PANData = Regex.Replace(pan[3].Value, @"[^\u0020-\u007E]", string.Empty); * } * * // NAME * trackData.Name = match[1].Value; * * // ADDITIONAL DATA * MatchCollection track1 = Regex.Matches(match[2].Value, "(?:[^^^?]+)", RegexOptions.Compiled); * * if (track1.Count >= 1) * { * trackData.ExpirationDate = track1[0].Value.Substring(0, 4); * trackData.ServiceCode = track1[0].Value.Substring(4, 3); * * if (track1.Count >= 2) * { * MatchCollection discretionary = Regex.Matches(track1[1].Value, "^[[:ascii:]]+"); * if (discretionary.Count > 0) * { * trackData.DiscretionaryData = discretionary[0].Value; * } * } * } * } * * return trackData; * }*/ /// <summary> /// The Track 1 structure is specified as: /// STX : Start sentinel "%" /// FC : Format code "B" (The format described here.Format "A" is reserved for proprietary use.) /// PAN : Payment card number 4400664987366029, up to 19 digits /// FS : Separator "^" /// NM : Name, 2 to 26 characters(including separators, where appropriate, between surname, first name etc.) /// FS : Separator "^" /// ED : Expiration data, 4 digits or "^" /// SC : Service code, 3 digits or "^" /// DD : Discretionary data, balance of characters /// ETX : End sentinel "?" /// LRC : Longitudinal redundancy check, calculated according to ISO/IEC 7811-2 /// /// REGULAR EXPRESSION /// ^%B([0-9]{1,19})\^([^\^]{2,26})\^([0-9]{4}|\^)([0-9]{3}|\^)([^\?]+)\?$ /// /// </summary> /// <param name="trackInformation"></param> /// <returns></returns> public OnlinePinData RetrievePinData(byte[] pinInformation) { OnlinePinData pinData = new OnlinePinData() { PANData = string.Empty, }; // clean up track data string decryptedPin = Regex.Replace(ConversionHelper.ByteArrayToAsciiString(pinInformation), @"[^\u0020-\u007E]", string.Empty, RegexOptions.Compiled); Debug.WriteLine($"DECRYPTED _: {decryptedPin}"); // expected format: PAN^NAME^ADDITIONAL-DATA^DISCRETIONARY-DATA MatchCollection match = Regex.Matches(decryptedPin, @"%B([0-9 ]{1,19})\^([^\^]{2,26})\^([0-9]{4}|\^)([0-9]{3}|\^)([^\?]+)\?", RegexOptions.Compiled); // DISCRETIONARY DATA is optional if (match.Count == 1 && match[0].Groups.Count >= 5) { // PAN DATA pinData.PANData = match[0].Groups[1].Value; } return(pinData); }
static void InternalTesting() { try { foreach (var item in trackPayload) { PinDecryptor decryptor = new PinDecryptor(); // decryptor in action byte[] trackInformation = decryptor.DecryptData(item.KSN, item.EncryptedData); string decryptedTrack = ConversionHelper.ByteArrayToHexString(trackInformation); //1234567890|1234567890|12345 Debug.WriteLine($"OUTPUT ____: {decryptedTrack}"); Console.WriteLine($"OUTPUT : [{decryptedTrack}]"); byte[] expectedValue = ConversionHelper.HexToByteArray(item.DecryptedData); bool result = StructuralComparisons.StructuralEqualityComparer.Equals(expectedValue, trackInformation); Console.WriteLine($"EQUAL : [{result}]"); OnlinePinData pinData = decryptor.RetrievePinData(trackInformation); Console.WriteLine($"CHOLDER: [{pinData.PANData}]"); } } catch (Exception e) { Console.WriteLine($"EXCEPTION: {e.Message}"); } }
static void DecryptOnlinePin(IConfiguration configuration, int index) { var onlinePin = configuration.GetSection("OnlinePinGroup:OnlinePin") .GetChildren() .ToList() .Select(x => new { onlinePinKsn = x.GetValue <string>("KSN"), onlinePinPan = x.GetValue <string>("PAN"), onlineEncryptedPin = x.GetValue <string>("EncryptedPin"), onlineDecryptedPin = x.GetValue <string>("DecryptedPin") }); // Is there a matching item? if (onlinePin.Count() > index) { string onlinePinKsn = onlinePin.ElementAt(index).onlinePinKsn; string onlinePinPan = onlinePin.ElementAt(index).onlinePinPan; string onlineEncryptedPin = onlinePin.ElementAt(index).onlineEncryptedPin; string onlineDecryptedPin = onlinePin.ElementAt(index).onlineDecryptedPin; try { //1234567890|1234567890|12345 Console.WriteLine($"==== [ ONLINE PIN DECRYPTION ] ===="); PinDecryptor decryptor = new PinDecryptor(); Debug.WriteLine($"KSN : {onlinePinKsn}"); Console.WriteLine($"KSN : {onlinePinKsn}"); Console.WriteLine($"DATA : {onlineEncryptedPin}"); // decryptor in action byte[] pinInformation = decryptor.DecryptData(onlinePinKsn, onlineEncryptedPin); string decryptedPin = ConversionHelper.ByteArrayToHexString(pinInformation); //1234567890|1234567890|12345 Console.WriteLine($"OUTPUT : {decryptedPin}"); Debug.WriteLine($"OUTPUT ____: {decryptedPin}"); OnlinePinData pinInfo = decryptor.RetrievePinData(pinInformation); //1234567890|1234567890|12345 Debug.WriteLine($"PAN DATA : {pinInfo.PANData}"); byte[] expectedValue = ConversionHelper.HexToByteArray(onlineDecryptedPin); bool result = StructuralComparisons.StructuralEqualityComparer.Equals(expectedValue, pinInformation); Console.WriteLine($"EQUAL ___: [{result}]"); } catch (Exception e) { Console.WriteLine($"EXCEPTION: {e.Message}"); } } }
static void ConfigurationLoad() { // Get appsettings.json config. IConfiguration configuration = new ConfigurationBuilder() .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) .AddEnvironmentVariables() .Build(); var onlinePin = configuration.GetSection("OnlinePinGroup:OnlinePin") .GetChildren() .ToList() .Select(x => new { onlinePinKsn = x.GetValue <string>("KSN"), onlinePinData = x.GetValue <string>("EncryptedData") }); // set the target index int index = 0; if (onlinePin.Count() > index) { string onlinePinKsn = onlinePin.ElementAt(index).onlinePinKsn; string onlinePinData = onlinePin.ElementAt(index).onlinePinData; try { PinDecryptor decryptor = new PinDecryptor(); Debug.WriteLine($"KSN : {onlinePinKsn}"); Console.WriteLine($"KSN : {onlinePinKsn}"); Console.WriteLine($"DATA : {onlinePinData}"); // decryptor in action byte[] trackInformation = decryptor.DecryptData(onlinePinKsn, onlinePinData); string decryptedTrack = ConversionHelper.ByteArrayToHexString(trackInformation); //1234567890|1234567890|12345 Console.WriteLine($"OUTPUT : {decryptedTrack}"); Debug.WriteLine($"OUTPUT ____: {decryptedTrack}"); //MSRTrackData trackInfo = decryptor.RetrieveAdditionalData(trackInformation); OnlinePinData pinInfo = decryptor.RetrievePinData(trackInformation); //1234567890|1234567890|12345 Debug.WriteLine($"PAN DATA : {pinInfo.PANData}"); } catch (Exception e) { Console.WriteLine($"EXCEPTION: {e.Message}"); } } }