]> localhost Git - gists.git/commitdiff
Add magstripe serialization program for MSR605X
authormisomosi <[email protected]>
Mon, 3 Aug 2026 17:38:33 +0000 (13:38 -0400)
committermisomosi <[email protected]>
Mon, 3 Aug 2026 17:38:33 +0000 (13:38 -0400)
MSR605X/mxser.py [new file with mode: 0644]

diff --git a/MSR605X/mxser.py b/MSR605X/mxser.py
new file mode 100644 (file)
index 0000000..b99a7da
--- /dev/null
@@ -0,0 +1,74 @@
+#!/usr/bin/env python3
+import argparse
+import datetime
+import getpass
+import sys
+
+def main(argv):
+    parser = argparse.ArgumentParser(prog=argv[0])
+    parser.add_argument('-n', '--name', default='', help='Name of card holder')
+    parser.add_argument('-e', '--expires', default='9912', help='Date of expiration on card (Format: YYMM)')
+    parser.add_argument('-s', '--service', default='121', help='Service code of card (TODO: help for service code)')
+    parser.add_argument('-p', '--pan', default='', help='Primary account number of card (CAUTION: COMMAND LINE SAVED IN SHELL HISTORIES)')
+    parser.add_argument('FILE')
+    args = parser.parse_args(args=argv[1:])
+
+    exitcode = 0
+    NAME = args.name
+    if len(NAME) != 0 and not NAME.isalnum():
+        print(f'Name ({NAME}) is not alphanumeric!')
+        exitcode |= 2
+    if len(NAME) > 26:
+        print(f'Name ({NAME}) is longer than 26 characters!')
+        exitcode |= 2
+
+    SVC = args.service
+    if len(SVC) != 0 and not SVC.isdigit():
+        print(f'Service code ({SVC}) is not numeric, not 3 characters, or is not a known service code!')
+        exitcode |= 4
+    if len(SVC) != 3:
+        print(f'Service code ({SVC}) is not 3 characters, or is not a known service code!')
+        exitcode |= 4
+    if SVC[0] not in '125679' or SVC[1] not in '024' or SVC[2] not in '01234567':
+        print(f'Service code ({SVC}) is not a known service code!')
+        exitcode |= 4
+
+    EXP = args.expires
+    if len(EXP) != 0 and not EXP.isdigit():
+        print(f'Expiration date ({EXP}) is not numeric, not 4 characters, not a valid date, or is already expired!')
+        exitcode |= 8
+    if len(EXP) != 4:
+        print(f'Expiration date ({EXP}) is not 4 characters')
+        exitcode |= 8
+    if not (1 <= int(EXP[2:4]) <= 12):
+        print(f'Expiration date ({EXP}) is not a valid date, or is already expired!')
+        exitcode |= 8
+
+    TODAY = datetime.datetime.now()
+    if datetime.datetime(2000 + int(EXP[0:2]), int(EXP[2:4]), 1) <= TODAY:
+        print(f'Expiration date ({EXP}) is not a valid date, or is already expired!')
+        exitcode |= 8
+
+    PAN = args.pan
+    if not PAN and exitcode == 0:
+        PAN = getpass.getpass("Enter PAN here: ")
+    if not PAN.isdigit() or len(PAN) >= 20:
+        print(f'Primary account number is not numeric or is longer than 19 characters!')
+        exitcode |= 16
+
+    if exitcode != 0:
+        return exitcode
+
+    # Write file and add a couple of newlines normally emitted by the
+    # MSR605X reader/writer program when reading magstripe cards
+    T1 = f'%B{PAN}^{NAME}^{EXP}{SVC}^^^?'
+    T2 = f';{PAN}={EXP}{SVC}===?'
+    T3 = '+?'
+    with open(args.FILE, 'w') as fp:
+        datestr = TODAY.strftime('%Y.%m.%d    %H:%M:%S')
+        fp.write('\n'.join([datestr, T1, T2, T3, '', '']))
+
+    return 0
+
+if __name__ == '__main__':
+    sys.exit(main(sys.argv))