Skip to main content

ipmkit

Lossless Mastercard IPM tooling. A drop-in replacement for cardutil with its bugs fixed.

IPM → CSV → IPM gives a file identical to the original, byte for byte. Nothing is converted, trimmed or masked.

Install

pip install ipmkit

The PIN block and key modules (ipmkit.pinblock, ipmkit.key) also need pip install "ipmkit[crypto]".

Convert files

ipmkit ipm2csv T112.ipm -o T112.csv
ipmkit csv2ipm T112.csv -o T112_rebuilt.ipm
ipmkit compare T112.ipm T112_rebuilt.ipm

The encoding is always EBCDIC cp037 unless you pass --encoding (for example --encoding latin_1 for an ASCII file). ipm2csv warns if the first MTI looks like ASCII. 1014 blocking is detected automatically; use --blocked/--unblocked to override it, or --config-file for a custom field config.

ipm2csv then verifies that the CSV rebuilds the identical file. If it doesn't, it fails instead of handing you a lossy CSV.

Speed on large files

Files with 20,000 or more records are split into chunks and converted on several CPU cores, one process per core up to 8. The chunks are joined back in their original order, so records keep their exact order and the CSV is byte-identical to a single-process run. Use --workers N to choose the number of processes (--workers 1 for a single process).

100,002 records (72 MB, cp037, 1014-blocked), on a 10-core Mac:

--workers 1 default
ipm2csv (includes verification) 5.8 s 1.8 s
ipm2csv --no-verify 3.6 s 1.0 s
csv2ipm 2.4 s 0.85 s

What's in the CSV

Column Content
ROW META for the file details row, otherwise the record number
MTI message type, exactly as in the file
BITMAP record bitmap in hex. A bit that is set marks the field present, even if the cell is empty
DEn field value exactly as in the file: spaces and leading zeros kept, dates not converted. Only the fields used in the file get a column
DE55 ICC data as hex, exactly as in the file
DE48, DE62, DE123–DE125 the PDS data exactly as in the file
RAW hex of a whole record that couldn't be parsed. It goes back unchanged. In the META row it holds the file details (encoding, blocking, end-of-file marker, trailing bytes)

A text value that can't sit safely in a CSV (control characters, or text that itself starts with hex:) is written as hex: followed by its bytes in hex.

Opening the CSV in Excel and saving it drops leading zeros and reformats values. Edit it with a text editor, or import every column as Text.

Editing the CSV

You can change values. Lengths for LLVAR/LLLVAR fields are recalculated and the 1014 blocking is redone. A fixed-length field with the wrong length is rejected, never silently padded or cut. To remove a field, clear its cell and its bit in BITMAP (or clear the BITMAP cell to have it recalculated).

Header and trailer generation

When the CSV has no file header (MTI 1644, DE24 697) or no trailer (MTI 1644, DE24 695), csv2ipm generates them:

  • header: DE48 = PDS 0105 File ID + PDS 0122 processing mode (--processing-mode: P production, the default, or T test); DE71 = 00000001
  • trailer: DE48 = PDS 0105 + PDS 0301 (sum of all DE4 amounts, 16 digits) + PDS 0306 (message count including header and trailer, 8 digits); DE71 = message count

The File ID is copied from the existing header or trailer if there is one. Otherwise it is built from --file-type, --file-date (YYMMDD, default today), --processor-id and --file-seq. A CSV made from an IPM file that had no header or trailer remembers that, so csv2ipm doesn't add one. --no-header-trailer turns generation off.

A hand-made CSV only needs MTI and DEn columns. It is written as cp037, not blocked, unless you pass --encoding / --blocked. A CSV made by ipm2csv remembers its encoding in the META row, and --encoding overrides that too.

Python API

from ipmkit import ipmcsv

ipmcsv.convert_ipm_to_csv('in.ipm', 'out.csv')          # verified
ipmcsv.convert_csv_to_ipm('out.csv', 'new.ipm')

ipm = ipmcsv.read_ipm(open('in.ipm', 'rb').read())      # IpmFile: records with raw field bytes
ipm.records[1].fields[42]                               # b'MERCHANT0000001'
data = ipmcsv.write_ipm(ipm)

cardutil compatibility

ipmkit.iso8583, ipmkit.mciipm, ipmkit.card, ipmkit.pinblock, ipmkit.key and ipmkit.config have the same API as cardutil 0.7.3. Change cardutil to ipmkit in your imports. The library functions (loads, dumps, IpmReader, IpmWriter) keep cardutil's latin_1 default so existing code behaves the same. The commands that read or write IPM files (mci_ipm_to_csv, mci_csv_to_ipm, mci_ipm_param_to_csv) default to cp037. The cardutil test suite passes against ipmkit, with one test changed because a value too long for its field now raises an error instead of being cut off.

ipmkit installs the same command names as cardutil (mci_ipm_to_csv, mideu and others). If both packages are installed in one environment, whichever was installed last provides those commands, so use separate environments if you need both.

Fixes (details in ANALYSIS.md):

  • messages with only a primary bitmap can be read; DE128 is processed
  • values too long for a field raise an error instead of being cut off or corrupting the length prefix
  • dumps() no longer changes the dict you pass in; too much PDS data raises a clear error
  • DE55 is parsed as real BER-TLV (multi-byte tags such as DF01, long-form lengths)
  • 10–12 digit PINs work in ISO-0/ISO-4 PIN blocks
  • Luhn validation works under python -O; short PANs are masked safely
  • loads is about 2.7× faster (it no longer builds a hex dump of every message when debug logging is off)

License

MIT. Based on cardutil, Copyright (c) 2019-2025 Anthony Delosa.

Metadata

Release files for ipmkit 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for ipmkit 0.1.1
File Size Uploaded Provenance Actions
ipmkit-0.1.1.tar.gz 68.6 kB With provenance Details for ipmkit-0.1.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for ipmkit 0.1.1
File Interpreter ABI Platform Actions
ipmkit-0.1.1-py3-none-any.whl Python 3 none any Details for ipmkit-0.1.1-py3-none-any.whl

Total release size: 127.8 kB

Release files / ipmkit-0.1.1.tar.gz

Download URL ipmkit-0.1.1.tar.gz
Size 68.6 kB
Tags Source
SHA-256 checksum
How to use checksums
81ff6757c9a428bb96c4a74b9325b5cb5f29d99fb80917ed3fcdd37aa2a0c419
BLAKE2b-256 checksum
How to use checksums
1c50b6079aba2d34eab35c0b8a286db8562f28243d3c9304e94862783570040d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 2, 2026.

Transparency log

Release files / ipmkit-0.1.1-py3-none-any.whl

Download URL ipmkit-0.1.1-py3-none-any.whl
Size 59.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
60699fe75fdc3f678543cb449c68cff70e5ccbb23de6581bb8b2468ca83da283
BLAKE2b-256 checksum
How to use checksums
46522069342c9c0baed2cd7275239af6a44cfedff3115e71e4422b6dbed21831
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 2, 2026.

Transparency log

Security for ipmkit 0.1.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for ipmkit-0.1.1.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 2, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page