PIV for TLS Client Certificates

In this guide, you’ll learn how to use PIV smartcards for TLS client certificate authentication.

Fork sample code on Github: Get Sample on Github

Add the SDK to Your Project

To get a username and password for our Maven repository, please contact us for a license.

Add this to your build.gradle:

repositories {
    google()
    jcenter()
    maven {
        credentials {
            username 'xxx'
            password 'xxx'
        }
        url "https://maven.cotech.de"
    }
}

dependencies {
    // Smartcard PIV protocol
    implementation 'de.cotech:hwsecurity-piv:2.2.1'
    // Smartcard dialog with keypad
    implementation 'de.cotech:hwsecurity-smartcard-ui:2.2.1'
    
    // OkHttp for HTTP requests
    implementation 'com.squareup.okhttp3:okhttp:3.14.2'
}

Initialize the Hardware Security SDK

To use the SDK’s functionality in your app, you need to initialize the SecurityKeyManager first. This is the central class of the SDK, which dispatches incoming NFC and USB connections. It is recommended to perform this initialization in the onCreate method of your Application subclass. This ensures Security Keys are reliably dispatched by your app while in the foreground.

@Override
public void onCreate() {
    super.onCreate();

    SecurityKeyManager securityKeyManager = SecurityKeyManager.getInstance();
    SecurityKeyManagerConfig config = new SecurityKeyManagerConfig.Builder()
        .setEnableDebugLogging(BuildConfig.DEBUG)
        .build();

    securityKeyManager.init(this, config);
}
override fun onCreate() {
    super.onCreate()

    val securityKeyManager = SecurityKeyManager.getInstance()
    val config = SecurityKeyManagerConfig.Builder()
        .setEnableDebugLogging(BuildConfig.DEBUG)
        .build()

    securityKeyManager.init(this, config)
}

Don’t forget to register your Application subclass in your AndroidManifest.xml:

<application 
   android:name=".SecurityKeyApplication"
   android:label="@string/app_name" 
...>

Show Smartcard Dialog and Receive Callbacks

In this guide, we use the SmartcardDialogFragment to show a neat kepad for PIN input. It also handles smartcard errors, for example when a wrong PIN is entered.

private void showSmartcardDialog() {
    SmartcardDialogOptions options = SmartcardDialogOptions.builder()
            //.setPinLength(4) // smartcards with a fixed PIN and PUK length improve the UX
            //.setPukLength(8)
            .build();

    smartcardDialogFragment = SmartcardDialogFactory.newPivInstance(options);
    smartcardDialogFragment.show(getSupportFragmentManager());
}

Implement SmartcardDialogCallback<PivSecurityKey> in your Activity and override onSmartcardDialogSecurityKeyDiscovered to receive callbacks from the SmartcardDialogFragment when a smartcard is discovered over NFC (or Security Keys over USB).

Using your favorite HTTP client, such as OkHttp, you can create a request using the SSLContext created by SecurityKeyTlsClientCertificateAuthenticator.

@Override
public void onSmartcardDialogSecurityKeyDiscovered(@NonNull PivSecurityKey securityKey, @NonNull PinProvider pinProvider) throws IOException {
    try {
        SecurityKeyTlsClientCertificateAuthenticator clientCertificateAuthenticator =
                securityKey.createSecurityKeyClientCertificateAuthenticator(pinProvider);
        SSLContext sslContext = clientCertificateAuthenticator.buildInitializedSslContext();

        // connection with OkHttp
        OkHttpClient httpClient = new OkHttpClient.Builder()
                .sslSocketFactory(sslContext.getSocketFactory())
                .build();
        Request request = new Request.Builder()
                .url("https://tls.hwsecurity.dev")
                .build();
        Response response = httpClient.newCall(request).execute();

        showDebugInfo(response);
    } catch (CertificateException e) {
        Timber.e(e);
    } catch (NoSuchAlgorithmException e) {
        Timber.e(e);
    } catch (KeyManagementException e) {
        Timber.e(e);
    }
}

Profit

That’s all! If you have any questions, don’t hesitate to contact us: