kaega
kaega

Reputation: 95

Issues authenticating a post request with a certificate and private key in Kotlin / Java

I have a .pem certificate and private key which I require for SSL. Doing so is trivial in Python:

import httpx
import ssl

sslcontext = ssl.create_default_context()
sslcontext.load_cert_chain(
    "./public-cert.pem",
    "./private-key.pem",
)

response = httpx.post(
    url,
    verify=sslcontext,
)

But I'd like do the same in Kotlin / Java. I've been going through the following article but I'm having issues handling the private key: https://developer.android.com/training/articles/security-ssl

I believe I must read the private key through a KeyFactory like such:

fun loadPrivateKey(path: Path): PrivateKey {
    val keyText = InputStreamReader(FileInputStream(path.toString())).use {
        it.readText()
            .replace("-----BEGIN PRIVATE KEY-----\n", "")
            .replace("-----END PRIVATE KEY-----", "")
    }
    val encoded = Base64.getDecoder().decode(keyText)
    return KeyFactory.getInstance("RSA")
        .generatePrivate(PKCS8EncodedKeySpec(encoded))
}

And pass it into the key store. However, decoding results in an error:

Illegal base64 character a

I would like to avoid handling it like this if possible: https://stackoverflow.com/a/8224863/13669284 I'm a little lost at this point and any guidance on this matter would be much appreciated.

Upvotes: 2

Views: 384

Answers (1)

maximus
maximus

Reputation: 746

For basic encoding no line feed character allowed: Using java.util.Base64 Basic – Uses “The Base64 Alphabet” as specified in Table 1 of RFC 4648 and RFC 2045 for encoding and decoding operation. – Encoding: not add any line feed (line separator) character. – Decoding: not contain characters outside the Base64 Alphabet.

So you can replace all the occurrences of "\n" in the key:

fun loadPrivateKey(path: Path): PrivateKey {
    val keyText = InputStreamReader(FileInputStream(path.toString())).use {
        it.readText()
            .replace("\n", "")
            .replace("-----BEGIN PRIVATE KEY-----", "")
            .replace("-----END PRIVATE KEY-----", "")
    }
    val encoded = Base64.getDecoder().decode(keyText)
    return KeyFactory.getInstance("RSA")
        .generatePrivate(PKCS8EncodedKeySpec(encoded))
}

Upvotes: 2

Related Questions