> For the complete documentation index, see [llms.txt](https://www.alanqthomas.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://www.alanqthomas.io/scala/parsing-certs-keys-from-strings-in-scala.md).

# Parsing certs/keys from Strings in Scala

I found it surprisingly difficult to get a straight answer online about how to parse the text of an RSA key-pair or certificate into their corresponding Java objects. Here's a basic step-by-step of how to do that. (All of this should basically apply to Java as well). A full example is at the bottom.

### Create a factory what you're trying to decode.

```scala
// For X.509 certificates
val x509CertFactory: CertificateFactory = CertificateFactory.getInstance("X.509")

// For RSA keys
val rsaKeyFactory: KeyFactory = KeyFactory.getInstance("RSA")
```

### Strip unnecessary characters. Remove new lines and header/footer tags.

```scala
def stripCertText(certText: String): String =
  certText
    .stripMargin
    .replace("\n", "")
    .replace("-----BEGIN CERTIFICATE-----", "")
    .replace("-----END CERTIFICATE-----", "")

def stripPrivateKeyText(keyText: String): String =
  keyText
    .stripMargin
    .replace("\n", "")
    .replace("-----BEGIN PRIVATE KEY-----", "")
    .replace("-----END PRIVATE KEY-----", "")

def stripPublicKeyText(keyText: String): String =
  keyText
    .stripMargin
    .replace("\n", "")
    .replace("-----BEGIN PUBLIC KEY-----", "")
    .replace("-----END PUBLIC KEY-----", "")
```

{% hint style="info" %}
The header/footer tag text may be different depending on what type of key you're decoding.
{% endhint %}

### Decode base-64

```scala
val bytes = Base64.getDecoder.decode(strippedKeyText)
```

### Generate certificate/key

```scala
val x509Cert: X509Certificate = x509CertFactory
      .generateCertificate(new ByteArrayInputStream(certBytes))
      .asInstanceOf[X509Certificate] // Needs to get cast because CertificateFactory is lame

val rsaPublicKey: PublicKey = rsaKeyFactory.generatePublic(new X509EncodedKeySpec(bytes))
val rsaPrivateKey: PrivateKey = rsaKeyFactory.generatePrivate(new PKCS8EncodedKeySpec(bytes))
```

{% hint style="info" %}
Use the `EncodedKeySpec` based on the type of your keys. In this example, I used `X509EncodedKeySpec` for the public key and `PKCS8EncodedKeySpec` for the private key.

The certificate factory just takes in a `ByteArrayInputStream`.
{% endhint %}

### Full example for parsing a certificate:

```scala
import java.io.ByteArrayInputStream
import java.security.cert.{ CertificateFactory, X509Certificate }
import java.util.Base64

val certText: String = "-----BEGIN CERTIFICATE-----\nMIIDHDCCAgSgAwIBAgIIW <...> IeilJ1C7Xtj+hKJEsk=-----END CERTIFICATE-----\n"
val factory: CertificateFactory = CertificateFactory.getInstance("X.509")
val strippedCertText: String = certText
  .stripMargin
  .replace("\n", "")
  .replace("-----BEGIN CERTIFICATE-----", "")
  .replace("-----END CERTIFICATE-----", "")
val certBytes: Array[Byte] = Base64.getDecoder.decode(strippedCertText)
val certByteArrayInputStream: ByteArrayInputStream = new ByteArrayInputStream(certBytes)
val x509Cert: X509Certificate = factory.generateCertificate(certByteArrayInputStream).asInstanceOf[X509Certificate]
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://www.alanqthomas.io/scala/parsing-certs-keys-from-strings-in-scala.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
