When implementing Apple VAS (Value Added Services) or NFC-based loyalty/payment systems, one common requirement is generating a Subject Public Key Info (SPKI) in compressed form. This is essential for embedding the public key in Apple Wallet passes and NFC terminal configurations.
This post covers three approaches: using OpenSSL, the dotnet-passbook library, and BouncyCastle for C#.
Why Use Compressed Public Keys?
EC (Elliptic Curve) public keys can be represented in two formats:
- Uncompressed: Contains both X and Y coordinates (65 bytes for P-256)
- Compressed: Contains only the X coordinate + a prefix byte (33 bytes for P-256)
Apple VAS and many NFC terminals require the compressed format to save space on the NFC chip.
Step 1: Generate Compressed Public Key with OpenSSL
If you have an existing EC private key in PEM format, use the following OpenSSL command to export the compressed public key:
openssl ec -in private_key.pem -pubout -out compressed_public_key.pem -conv_form compressed
This produces a PEM file containing the SPKI with the compressed point encoding.
Step 2: Use the Key with dotnet-passbook (Apple Wallet NFC)
When using the dotnet-passbook library to generate Apple Wallet passes with NFC support, pass the Base64-encoded compressed key to the Nfc constructor:
request.Nfc = new Nfc("15407F6", @"MDkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDIgAC/O3/C07TB7WkJuUZ1vZkAn4LZs+IGUpy7BMnh1bKrBY=");
The first parameter is the message, and the second is the Base64-encoded DER-encoded compressed public key.
Step 3: Read and Encode with BouncyCastle in C#
If you need to do this programmatically in C#, BouncyCastle makes it straightforward:
PemReader pemReader = new PemReader(new StringReader(pemString));
ECPublicKeyParameters ecPublicParameters = (ECPublicKeyParameters)pemReader.ReadObject();
// Get compressed encoding (true = compressed, false = uncompressed)
byte[] compressed = ecPublicParameters.Q.GetEncoded(true);
byte[] uncompressed = ecPublicParameters.Q.GetEncoded(false);
// Convert to Base64 for use in NFC/VAS configurations
string compressedBase64 = Convert.ToBase64String(compressed);
Summary
Compressed public keys are a fundamental requirement for Apple VAS and NFC terminal integrations. Whether you use OpenSSL for one-off conversions or BouncyCastle for runtime key handling in C#, the process is straightforward once you understand the encoding differences. Always verify the key length — a valid P-256 compressed key is 33 bytes.