
org.apache.pekko.pki.pem.PEMDecoder.scala Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of pekko-pki_3 Show documentation
Show all versions of pekko-pki_3 Show documentation
Apache Pekko is a toolkit for building highly concurrent, distributed, and resilient message-driven applications for Java and Scala.
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* license agreements; and to You under the Apache License, version 2.0:
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* This file is part of the Apache Pekko project, which was derived from Akka.
*/
/*
* Copyright (C) 2020-2022 Lightbend Inc.
*/
package org.apache.pekko.pki.pem
import java.util.Base64
import org.apache.pekko.annotation.ApiMayChange
/**
* Decodes lax PEM encoded data, according to
*
* https://tools.ietf.org/html/rfc7468
*/
object PEMDecoder {
// I believe this regex matches the RFC7468 Lax ABNF semantics jkhdft exactly.
private val PEMRegex = {
// Luckily, Java Pattern's \s matches the RFCs W ABNF expression perfectly
// (space, tab, carriage return, line feed, form feed, vertical tab)
// The variables here are named to match the expressions in the RFC7468 ABNF
// description. The content of the regex may not match the structure of the
// expression because sometimes there are nicer way to do things in regexes.
// All printable ASCII characters minus hyphen
val labelchar = """[\p{Print}&&[^-]]"""
// Starts and finishes with a labelchar, with as many label chars and hyphens or
// spaces in between, but no double spaces or hyphens, also may be empty.
val label = raw"""(?:$labelchar(?:[\- ]?$labelchar)*)?"""
// capturing group so we can extract the label
val preeb = raw"""-----BEGIN ($label)-----"""
// we don't extract the end label because the RFC says we can ignore it (it
// doesn't have to match the begin label)
val posteb = raw"""-----END $label-----"""
// Any of the base64 chars (alphanum, +, /) and whitespace, followed by at most 2
// padding characters, separated by zero to many whitespace characters
val laxbase64text = """[A-Za-z0-9\+/\s]*(?:=\s*){0,2}"""
val laxtextualmessage = raw"""\s*$preeb($laxbase64text)$posteb\s*"""
laxtextualmessage.r
}
/**
* Decodes a PEM String into an identifier and the DER bytes of the content.
*
* See https://tools.ietf.org/html/rfc7468 and https://en.wikipedia.org/wiki/Privacy-Enhanced_Mail
*
* @param pemData the PEM data (pre-eb, base64-MIME data and ponst-eb)
* @return the decoded bytes and the content type.
*/
@throws[PEMLoadingException](
"If the `pemData` is not valid PEM format (according to https://tools.ietf.org/html/rfc7468).")
@ApiMayChange
def decode(pemData: String): DERData = {
pemData match {
case PEMRegex(label, base64) =>
try {
new DERData(label, Base64.getMimeDecoder.decode(base64))
} catch {
case iae: IllegalArgumentException =>
throw new PEMLoadingException(
s"Error decoding base64 data from PEM data (note: expected MIME-formatted Base64)",
iae)
}
case _ => throw new PEMLoadingException("Not a PEM encoded data.")
}
}
@ApiMayChange
final class DERData(val label: String, val bytes: Array[Byte])
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy