PUBLIC OBJECT

X.509 Certificates in Kotlin

I learned most of what I know about TLS certificates through reading APIs, source code, and specs. My instincts from dealing with ASN.1, X.509, and TLS as a user is that it the APIs are complex, and I should stay away️ from the even more complex implementations.

But I’m foolish and I don’t like that okhttp-tls depends on Bouncy Castle to create certificates. “How hard could it be to create a well-formed TLS certificate? It’s just bytes!...”

So I read lots of specs. I found these difficult to learn from because they aren’t self-contained. Each builds upon others and some go back to the days before ASCII! But I did find a couple very helpful guides: this one from Let’s Encrypt and one from RSA written in 1993.

Next I started writing tests and code, building up from small ASN.1 primitives all the way to full nested objects with type hints. Yesterday I reached my goal and changed okhttp-tls to not need Bouncy Castle to create certificates. The code that does it is about 2,000 lines of Kotlin. Hooray!

Now that I have the code I’m shocked at how simple this stuff can be. It takes just six data classes to model a signed certificate:

data class Certificate(
  val tbsCertificate: TbsCertificate,
  val signatureAlgorithm: AlgorithmIdentifier,
  val signatureValue: ByteString
)

data class TbsCertificate(
  val version: Long,
  val serialNumber: BigInteger,
  val signature: AlgorithmIdentifier,
  val issuer: Map<String, Any?>,
  val validity: Validity,
  val subject: Map<String, Any?>,
  val subjectPublicKeyInfo: SubjectPublicKeyInfo,
  val extensions: List<Extension>
)

data class AlgorithmIdentifier(
  val algorithm: String,
  val parameters: Any?
)

data class Validity(
  val notBefore: Instant,
  val notAfter: Instant
)

data class SubjectPublicKeyInfo(
  val algorithm: AlgorithmIdentifier,
  val publicKey: ByteString
)

data class Extension(
  val id: String,
  val critical: Boolean,
  val value: Any?
)

The above code is simplified from certificates.kt in OkHttp, but not by much. It feels great to learn that certificates aren’t so scary; it was just the specs and APIs that were wrapped around them.