Day: February 7, 2026

cyber-posts

Bouncy Castle crypto

What is Bouncy Castle?

Bouncy Castle is an open-source cryptography library for Java (and C#). It provides a clean, well-maintained implementation of a very wide range of cryptographic algorithms and standards. The project is run by the Legion of the Bouncy Castle, a non-profit group in Australia, and has been actively developed since 2000.

The two main APIs are:

  • Lightweight API – direct, low-level access to algorithms (similar to how you’d use them in C).
  • JCA/JCE Provider API – implements the standard Java Cryptography Architecture (JCA) and Java Cryptography Extension (JCE), so you can plug it in as an additional security provider alongside the built-in Sun/Oracle providers.

Why use Bouncy Castle in certificate/identity/credential systems?

In your domain (handling X.509 certificates, digital signatures, PKCS objects, credential issuance/validation), Bouncy Castle is extremely common for several practical reasons:

  1. Broader algorithm support
    Java’s default providers support only a subset of algorithms (and some are restricted by old export rules). Bouncy Castle adds many modern and legacy algorithms: ECDSA with named curves, EdDSA (Ed25519/Ed448), RSA-PSS, CMAC, GCM with large nonces, newer hash functions, etc.
  2. Excellent ASN.1 and certificate handling
    X.509 certificates, CRLs, OCSP responses, PKCS#10 requests, PKCS#12 keystores, CMS signed data, etc., are all complex ASN.1 structures. Bouncy Castle has battle-tested parsers/generators that are more robust and feature-complete than the built-in java.security.cert classes.
  3. Provider model integration
    You can register Bouncy Castle as a JCA provider with one line of code:
   Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());

After that, standard Java APIs (KeyStore, CertificateFactory, Signature, Cipher, etc.) automatically gain access to all Bouncy Castle algorithms without changing your existing code.

  1. FIPS-compliant variants
    There are separate Bouncy Castle FIPS jars that are certified for use in regulated environments (government, finance, healthcare).
  2. Used by almost every major Java library
    Libraries like Apache PDFBox, iText, Spring Security, Bouncy Castle is often already on the classpath indirectly. Using it directly avoids reinventing the wheel.
  3. Lightweight and performant
    Compared to alternatives like OpenSSL bindings (JNI overhead) or commercial libraries, Bouncy Castle is pure Java, easy to bundle, and has good performance for most use cases.

When you might not need it: If you only use very basic algorithms (RSA 2048 + SHA-256 + PKCS#12) and stay within the default Java provider limits, you can avoid the extra dependency. But as soon as you touch modern elliptic curves, post-quantum prep, or complex certificate extensions, Bouncy Castle becomes the de-facto choice.

Practical part – simple code example

Here’s a minimal, self-contained example that shows:

  • Adding Bouncy Castle as a provider
  • Generating a self-signed X.509 certificate with ECDSA (something the default provider can’t do easily on older JDKs)
import java.math.BigInteger;
import java.security.*;
import java.util.Date;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.x509.X509V3CertificateGenerator; // Legacy but simple API
import javax.security.auth.x500.X500Principal;

public class BouncyCastleExample {
    public static void main(String[] args) throws Exception {
        // 1. Register Bouncy Castle provider (do this once at app startup)
        Security.addProvider(new BouncyCastleProvider());

        // 2. Generate an EC key pair (curve prime256v1 = NIST P-256)
        KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC", "BC");
        kpg.initialize(256); // or use named curve: new ECGenParameterSpec("prime256v1")
        KeyPair kp = kpg.generateKeyPair();

        // 3. Generate a self-signed certificate (valid for 1 year)
        X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();
        X500Principal dn = new X500Principal("CN=Test Self-Signed Cert");

        certGen.setSerialNumber(BigInteger.valueOf(System.currentTimeMillis()));
        certGen.setIssuerDN(dn);
        certGen.setNotBefore(new Date());
        certGen.setNotAfter(new Date(System.currentTimeMillis() + 365L * 24 * 60 * 60 * 1000));
        certGen.setSubjectDN(dn);
        certGen.setPublicKey(kp.getPublic());
        certGen.setSignatureAlgorithm("SHA256withECDSA");

        java.security.cert.X509Certificate cert = certGen.generate(kp.getPrivate(), "BC");

        System.out.println("Generated certificate:");
        System.out.println(cert);
    }
}

Dependencies (Maven):

<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcprov-jdk18on</artifactId> <!-- or newer jdk version -->
    <version>1.78.1</version> <!-- check latest at https://www.bouncycastle.org/latest_releases.html -->
</dependency>

Run this snippet in any Java project and you’ll see a printed X.509 certificate that uses ECDSA – something you’d need in modern credential systems (e.g., for shorter signatures or post-quantum readiness).

This directly connects to your work: whenever you need to generate, parse, validate, or sign certificates programmatically in Java, Bouncy Castle is usually the safest and most capable choice.

cyber-posts

logical channels 7816

Logical Channels in ISO/IEC 7816-4

ISO/IEC 7816-4 defines logical channels as a mechanism to run multiple independent sessions on a single physical smart card connection. Each channel maintains its own state:

  • Currently selected application (DF – Dedicated File)
  • Current file (EF – Elementary File)
  • Security status (e.g., PIN verified, keys in use)

This is essential for multi-application cards (common in eID, health cards, or credential systems) where you might need to access identity data and a signing certificate at the same time without deselecting one to use the other.

Key facts

  • Channel 0 → basic channel, always open at card reset (ATR), cannot be closed.
  • Additional channels → typically 1–3 (total 4 channels); some modern/JavaCard implementations support up to 19.
  • Channels are independent → no interleaving of command-response pairs across channels (you finish one command before the next, but you can switch channels between commands).
  • Support level → indicated by the card (e.g., in ATR historical bytes or card capabilities data objects).

How the channel number is encoded (most common case – channels 0–3)
The channel number is in the CLA byte of every APDU, in bits b2 and b1:

Channelb2 b1CLA example (standard interindustry, no SM/chaining)
0000x00
1010x01
2100x02
3110x03

To switch channel in code: cla = (base_cla & 0xFC) | channel_number (clears low bits then ORs the number).

Opening and closing channels
Two ways:

  1. Implicit (most common): Send any command (usually SELECT) with CLA indicating a closed channel → the card opens it automatically if supported.
  2. Explicit: Use the MANAGE CHANNEL command (INS = 0x70).

MANAGE CHANNEL details

  • Open (P1 = 0x00):
  • P2 = 0x00 → card assigns an available channel and returns it.
  • P2 = 0x01–0x03 → request a specific channel.
  • Le = 0x01 if P2=0x00 (to get the assigned number), absent otherwise.
  • Close (P1 = 0x80):
  • P2 = channel number to close (bits b2 b1).

Practical examples (APDUs in hex)

  1. Explicit open, card assigns (sent on channel 0):
   Command:  00 70 00 00 01
   Response: 02 90 00   ← card assigned channel 2 (data byte = 02)
  1. Explicit open, request channel 1:
   Command:  00 70 00 01
   Response: 90 00        ← success, no data needed
  1. Use the channel – SELECT an application on channel 1:
   Command:  01 A4 04 00 0A A0 00 00 00 63 50 4B 43 53 2D 31 35   ← example PKSC#15 AID
  1. Close channel 1 (sent on channel 0):
   Command:  00 70 80 01
   Response: 90 00
  1. Implicit open example – directly open channel 2 and select:
   Command:  02 A4 04 00 ... (AID)

Quick code snippet (Python-like with pcsc/pyscard style)

def send_on_channel(conn, base_cla, ins, p1, p2, data=b'', le=None, channel=0):
    cla = (base_cla & 0xFC) | channel   # set channel in low bits
    apdu = bytes([cla, ins, p1, p2]) + len_field + data + le_field
    response, sw1, sw2 = conn.transmit(apdu)
    return response, sw1, sw2

# Example: open channel 1 implicitly by selecting on it
send_on_channel(conn, 0x00, 0xA4, 0x04, 0x00, data=aid, channel=1)

This gives you concurrent access – perfect for credential systems where one channel can stay authenticated to an identity app while another performs operations in a different app. Tomorrow you can build on this (e.g., how security status can be shared or isolated across channels).