RecoverMyMac

Minter Technical Processes and Explanations

Minter — Technical Processes & Explanations

Architecture and implementation detail for the Minter licensing system. Companion to the Minter User Guide. Not linked from any menu.

Architecture Overview

Minter is split into two components deliberately kept separate:

VBA never implements cryptography itself and never receives a private key value. It communicates with Signer.exe over stdin/stdout JSON — never via command-line arguments, so no sensitive value is ever visible in a process list or command-line log.

The Mint Sequence, Exactly

Every mint follows a fixed order. LicenceLog.txt is the sole source of truth for licence data — the Excel table is always a refreshed view derived from it, never written to independently.

  1. Sign — Signer.exe produces the signed licence string. Nothing is persisted yet.
  2. Write LicenceLog.txt — the licence becomes real and committed at this point.
  3. Write LicenceHistory.txt — append-only MINT audit entry.
  4. Refresh Excel — the on-screen table is reloaded from LicenceLog.txt.
  5. Create PDF — certificate generated; PDF_CREATED audit entry appended.
Failure pointTreated as
Signing failsNothing recorded — full stop
LicenceLog.txt write failsNothing recorded — signature discarded
History write failsLicence valid; audit gap flagged narrowly
Excel refresh failsLicence valid; use Rebuild From Audit File
PDF generation failsLicence valid; use Regenerate PDF

Key Lifecycle & Rotation Math

Each product (Trust Armory, Support Funnel) has an independent key history. Exactly one key per product may be Active at a time. Generating a key never auto-activates it; restoring from an encrypted backup never auto-activates it either — activation is always a separate, explicit action.

Safe-to-retire calculation for an old key in the plugin’s PUBLIC_KEYS verification array:

safe_to_remove_date = MAX(ExpiryDate) across all LicenceLog rows for that KeyVersion, + applicable grace period

Encrypted Key Backup / Restore — Technical Detail

Two distinct encryption mechanisms exist in this system, and they are not interchangeable:

keystore.datKeyBackups\*.enc
Windows DPAPI (CryptProtectData), CurrentUser scopeAES-256-GCM, key derived via PBKDF2-HMAC-SHA256 (600,000 iterations) from a user-chosen password
Bound to this specific Windows account + machinePortable — works on any machine, given the password
Not a backup mechanismThe only supported migration/disaster-recovery path

Restoring a key backup merges recovered key records into the local keystore as archived, never active — this prevents a restore from silently starting to sign with an unexpected key. There is no “reveal private key” feature anywhere in the system; the encrypted backup file is the sole export path for key material.

Data Model

Data\LicenceLog.txt — tab-delimited, UTF-8, sole source of truth. Columns: ID, Product, ProductVersion, Domain, LicenceType, ExpiryDate, IssueDate, LicenceKey, KeyVersion, LicenceIdentifier, CustomerName, CompanyName, CustomerEmail, OrderReference, Notes, PdfPath, CreatedBy, CreatedTimestamp, LastModifiedTimestamp, LicenceStatus.

Data\LicenceHistory.txt — append-only, never rewritten. Columns: Timestamp, Action, Product, KeyVersion, Identifier, Domain. Audited actions: MINT, PDF_CREATED, PDF_REGENERATE, DELETE_RECORD, KEY_GENERATED, KEY_ACTIVATED, KEY_ARCHIVED, KEY_RESTORED, TRIAL_OVERRIDE, BACKUP_CREATED, REBUILD_EXECUTED.

Licence identifiers follow LIC-YYYY-NNNNNN, sequential, never reused even after a log record is deleted — deleting a Licence Log row removes the record only and does not revoke the underlying signed licence.

Plugin-Side Verification (Trust Armory example)

Licence format: PREFIX.base64url(payload).base64url(signature)TAL1. for Trust Armory, SFL1. for Support Funnel. Verification uses sodium_crypto_sign_verify_detached against a list of embedded public keys, tried in order, so a rotated-out key’s licences remain verifiable as long as its public key stays in the array.

Payload fields: v, tier, domain, exp, iat, id. Domain binding is normalised identically on both the minting and verification sides (lowercase, strip protocol/www/path). A domain-change grace period and a trial grace period both extend validity briefly past a literal state change or expiry.

Licensing gates customisation only — never core functionality. The Free tier is a fully working product, not a crippled demo.

Known Limitations

v1.1 Additions: New Modules

13 new modules and 2 new UserForms were added on top of the originally delivered architecture. Extracted and verified directly from the compiled VBA project (vbaProject.bin) in the uploaded workbook.

ModulePurpose
modHistoryViewer + frmHistoryLogFull searchable audit-trail UI reading LicenceHistory.txt, newest-first, double-click to jump to a licence or its PDF
modViewLicenceDetails + frmLicenceDetailsFormatted licence detail popup with editable Notes field
modOpenPdf, modCopyKey, modRegeneratePdf, modDeleteLicencePer-row actions on the selected Licence Log record
modSearchLive search across all 20 LicenceLog columns; jumps to and selects first match
modNavigationSheet navigation, including auto-clearing any active filter when entering the Licence Log
modEmailBuilt-out Outlook draft creation: template placeholder replacement, per-product From-address matching against configured Outlook accounts
modButtons, modPdfFolder, modTrialCOuntSupporting helpers — see caveats below

Known Issue: Hardcoded Path in Two Modules

modButtons.OpenLatestPdfForProduct and modOpenPdf.OpenSelectedPdf construct the PDF path as:

fullPath = “C:\Minter\” & pdfPath

instead of using modConfig.RootPath(), which every other module (including the original modPDF and the new modPdfFolder) uses to resolve paths relative to wherever the workbook actually lives. This reintroduces a hardcoded dependency on the workbook living at exactly C:\Minter\ for these two specific buttons only — they will fail to locate PDFs if the folder is moved (different drive, renamed folder, OneDrive-synced path) even though the rest of the system continues to resolve paths correctly.

Fix: replace the hardcoded string with modConfig.RootPath() in both locations, matching the pattern already used elsewhere.

Known Issue: Parallel Trial-Count Implementation

The original trial-duplicate check, modDataStore.FindPreviousTrial, reads LicenceLog.txt directly — the authoritative source of truth. The new modTrialCOunt.GetTrialCount instead scans the LicenceLog worksheet directly via a manual row loop.

These should normally agree, since the sheet is a refreshed view of the same file — but they are two independent code paths performing similar logic against two different data sources (file vs. worksheet). If the Excel view is ever stale (the specific scenario the core “Excel refresh fails” narrow-failure handling exists for), a caller using GetTrialCount would silently get a different answer than one using FindPreviousTrial, until Rebuild Workbook From Audit File is run.

No call site for GetTrialCount was found in the extracted modules — it may not yet be wired into the mint flow. Worth confirming whether it’s in active use before two divergent trial-check paths cause a real discrepancy.

Unchanged Core (Verified)

Full line-by-line comparison confirms the following remain exactly as originally designed: the mint sequence and its failure-handling rules, the encrypted key backup/restore flow (AES-256-GCM + PBKDF2), the full audit event set, domain normalisation, key rotation/activation logic, and the DPAPI-bound local keystore. The v1.1 additions are UI/workflow conveniences layered on top — none of them alter the underlying trust model.

Scroll to Top