If you run a private LTE network and you’ve decided to program your own SIM cards, every blank card needs four values written onto it: an IMSI, an ICCID, a Ki and an OPc. Two of those are secret keys, and your core has to hold the exact same keys, down to the last hex digit.
Operators keep running into this as they bring SIMs in-house. The values usually end up in a spreadsheet or a script someone wrote once, and a mistake there won’t show itself right away. A card with one wrong character looks just like a good one. You find out later, on the bench or up on the ladder, when the core logs an authentication failure.
So I built a free SIM card generator at The Edge Mile, and it went live today. It makes all four values for up to 10,000 SIMs in about a second. You get a CSV for your SIM writer and a script that loads the same batch into an Open5GS or Rapid5GS core. It all runs in your browser, and your keys never touch our server.
It’s free, and it doesn’t ask for an account or an email.
What Goes on a SIM
The IMSI is the card’s identity on your network. It’s 15 digits: your PLMN, which is a country code (the MCC) plus a network code (the MNC), followed by a subscriber number (the MSIN). The generator counts the subscriber numbers up from wherever you tell it to start. The ICCID is the serial number printed on the card, built from a prefix, then the IMSI, then a Luhn check digit. With the default 8901 prefix and a 20-digit ICCID, the whole IMSI fits inside, so you can read it straight off the card.
The Ki and the OPc are the secrets. The Ki is a 128-bit key the card shares with your core, and every card gets its own, pulled from your browser’s cryptographic random number generator, crypto.getRandomValues. A network usually has one operator key, the OP, and each card gets the OP mixed with its own Ki. That’s the OPc: OPc = AES-128(Ki, OP) XOR OP, the Milenage formula from 3GPP TS 35.206. The generator makes a fresh OP for each batch, or uses the one you already have, and works out the OPc for every card. You write the OPc to the card, so the OP itself never goes on a SIM. If the Ki or the OPc is off by a single character, Open5GS rejects the card with a MAC failure.
Setting Up a Batch
A batch starts with your PLMN. The default is 999-99, because ITU-T E.212 sets aside MCC 999 for private networks, where it won’t clash with a carrier. A CBRS network in the US can pick 315-010 and enter its four-digit IMSI Block Number, which becomes the first four digits of every subscriber number and leaves 100,000 IMSIs per block. There are also presets for 001-01 on the test bench, 901-70 for a Rapid5GS core that kept its install default, and 999-70 to match the Open5GS sample config. Watch the MNC length: to a phone or a CPE, 99 and 099 are two different networks.
A lot of WISPs run more than one APN per subscriber, say one to manage the CPE and one for the customer’s internet. The generator gives each SIM up to four APNs, which is the Open5GS limit, and each APN gets its own IP type: IPv4, IPv6 or IPv4v6. The first one is the default, the APN the core uses when a device doesn’t ask for a specific one. APNs live in the core, not on the card, so they go in the import file and the SIM CSV stays the same either way. (The free Rapid5GS build is happiest with one APN; Rapid5GS Pro manages several from its web GUI.) You also set a download cap and an upload cap per SIM, which Open5GS enforces as the AMBR for each SIM and each APN.
The Two Files
The CSV goes to your SIM writer, one row per card with the ICCID, IMSI, Ki and OPc. The import script loads the whole batch into Open5GS or Rapid5GS with one mongosh command. Open5GS doesn’t ship a CSV importer, and Rapid5GS doesn’t install open5gs-dbctl, so without the script you’re either clicking subscribers into the WebUI one at a time or writing your own importer. The script writes each subscriber the same way the WebUI does. It skips any IMSI that’s already in the database and never edits an existing subscriber, so running it twice won’t hurt anything, and when it finishes it tells you how many SIMs it added.

Keeping the Keys Private
The generator runs in a sandboxed frame with its own opaque origin, under a Content-Security-Policy of connect-src 'none'. Your browser blocks any network request the generator tries to make, and nothing else on the page, analytics included, can see into the frame. The keys are made in your browser and stay on your computer until you copy the files somewhere yourself.
It also checks its own math. Every time it loads, it runs the published test sets from 3GPP TS 35.208, and if either check fails, the Generate button stays off.
If you’d rather not trust a website at all, download the generator as one HTML file. The page publishes its SHA-256 so you can confirm your copy is the real one, and it runs fine on a computer with no network connection. Either way, treat the files like passwords, because anyone with a card’s Ki and OPc can clone that card.
Programming the Cards
The tool page walks through how to program SIM cards for a private LTE network: set your writer to Milenage, pick OPc if it has an OP/OPc switch, set the MNC length in the card’s EF_AD, add your PLMN to the card’s PLMN lists, and test one card before you write the rest. The ADM key for each card comes from your card vendor; the generator doesn’t make it. And don’t open the CSV in Excel and save it again. Excel turns a 20-digit ICCID into 8.90E+19, and the real digits are gone.
There’s also a section on which PLMN a private network should use, and for the morning a new card won’t come up, why a new SIM won’t attach lists the actual lines Open5GS prints in its log and what each one means.
Why It’s Free
The Edge Mile sells private LTE hardware and support, including Nokia AZQC CBRS kits and Rapid5GS Pro, and we run wireless networks ourselves. I built the generator because I wanted it for our own networks.
If you’re building on Open5GS, the Rapid5GS hub and the source on GitHub are good places to start. SIMs are the easy part, and when you need the rest of the network, The Edge Mile can help you get it on the air.

Join the conversation
Every comment goes through manual review before it appears here. It is a small stand against the dead internet, a way to be sure these are real people in a real conversation. Your email is never published.
Replying to .
Thank you.
Your comment is in the queue. I read every one and post the good-faith ones by hand, so look for it on the page before long.