Skip to content

Commit

Permalink
Flytter kode for prosesseringssteg til fellesmodul
Browse files Browse the repository at this point in the history
  • Loading branch information
thburnett committed Sep 26, 2023
1 parent 3b3524e commit f89767f
Show file tree
Hide file tree
Showing 15 changed files with 124 additions and 149 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package no.nav.emottak.ebms.processing

import io.ktor.server.plugins.BadRequestException
import no.nav.emottak.ebms.model.EbMSMessage
import no.nav.emottak.ebms.postPayloadRequest
import no.nav.emottak.melding.model.Header
Expand All @@ -26,22 +27,22 @@ class PayloadProcessor: Processor {

fun MessageHeader.payloadRequestHeader(): Header {
return Header(
messageId = this.id ?: throw RuntimeException("MessageID mangler fra header"),
cpaId = this.cpaId ?: throw RuntimeException("CPAID mangler fra header"),
messageId = this.id ?: throw BadRequestException("MessageID mangler fra header"),
cpaId = this.cpaId ?: throw BadRequestException("CPAID mangler fra header"),
conversationId = this.conversationId,
to = Party(
herID = this.to.partyId.herID(),
role = this.to.role ?: throw RuntimeException("Melding mangler role for en eller flere parter")
role = this.to.role ?: throw BadRequestException("Melding mangler role for en eller flere parter")
),
from = Party(
herID = this.from.partyId.herID(),
role = this.from.role ?: throw RuntimeException("Melding mangler role for en eller flere parter")
role = this.from.role ?: throw BadRequestException("Melding mangler role for en eller flere parter")
),
service = this.service.value ?: throw RuntimeException("Service mangler fra header"),
service = this.service.value ?: throw BadRequestException("Service mangler fra header"),
action = this.action
)
}

fun List<PartyId>.herID(): String {
return this.firstOrNull() { partyId -> partyId.type == "HER" }?.value ?: throw RuntimeException("Melding mangler HER-ID for en eller flere parter")
return this.firstOrNull() { partyId -> partyId.type == "HER" }?.value ?: throw BadRequestException("Melding mangler HER-ID for en eller flere parter")
}
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
package no.nav.emottak.util

import io.ktor.server.plugins.BadRequestException
import java.io.ByteArrayInputStream
import java.security.cert.CertificateException
import java.security.cert.CertificateFactory
import java.security.cert.X509Certificate

internal fun isSelfSigned(certificate: X509Certificate) =
fun isSelfSigned(certificate: X509Certificate) =
certificate.subjectX500Principal == certificate.issuerX500Principal

internal fun createX509Certificate(byteArray: ByteArray): X509Certificate {
fun createX509Certificate(byteArray: ByteArray): X509Certificate {
val cf = CertificateFactory.getInstance("X.509")
return try {
cf.generateCertificate(ByteArrayInputStream(byteArray)) as X509Certificate
}
catch (e: CertificateException) {
throw BadRequestException("")
throw RuntimeException("Kunne ikke opprette X509Certificate fra ByteArray", e)
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package no.nav.emottak.util

import io.ktor.server.plugins.BadRequestException
import no.nav.emottak.util.signatur.KeyValueKeySelector
import no.nav.emottak.util.signatur.SignatureException
import org.w3c.dom.Document
import org.w3c.dom.Node
import org.w3c.dom.NodeList
Expand Down Expand Up @@ -31,7 +31,7 @@ internal fun retrieveXMLSignature(validateContext: DOMValidateContext): XMLSigna

private fun retrieveSignatureElement(document: Document): Node {
val nodeList: NodeList = document.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature")
return nodeList.item(0) ?: throw BadRequestException("MANGLER_XML_SIGNATUR")
return nodeList.item(0) ?: throw SignatureException("Mangler xmldsig")
}

internal fun retrievePublicCertificateFromSignature(document: Document): X509Certificate {
Expand All @@ -46,13 +46,13 @@ private fun retrievePublicCertificateFromSignature(signature: XMLSignature): X50
}


internal fun createDocument(inputstream: InputStream): Document {
fun createDocument(inputstream: InputStream): Document {
val dbf = DocumentBuilderFactory.newInstance()
dbf.isNamespaceAware = true
return dbf.newDocumentBuilder().parse(inputstream)
}

internal fun getByteArrayFromDocument(doc: Document): ByteArray {
fun getByteArrayFromDocument(doc: Document): ByteArray {
val outputStream = ByteArrayOutputStream()
val xmlSource = DOMSource(doc)
val result = StreamResult(outputStream)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package no.nav.emottak.util.crypto

class EncryptionException(override val message: String, e: Exception? = null) : Exception(message, e) {
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
package no.nav.emottak.melding.process
package no.nav.emottak.util.crypto

import io.ktor.server.plugins.BadRequestException
import no.nav.emottak.melding.model.Header
import no.nav.emottak.melding.model.Melding
import no.nav.emottak.util.createX509Certificate
import no.nav.emottak.util.hentKrypteringssertifikat
import org.bouncycastle.asn1.ASN1ObjectIdentifier
import org.bouncycastle.cms.CMSAlgorithm
import org.bouncycastle.cms.CMSEnvelopedDataGenerator
Expand All @@ -17,30 +13,14 @@ import org.bouncycastle.jce.provider.BouncyCastleProvider
import java.security.cert.CertificateEncodingException
import java.security.cert.X509Certificate

private val kryptering = Kryptering()

fun krypter(byteArray: ByteArray, sertifikat: ByteArray) = kryptering.krypter(byteArray, sertifikat)

fun Melding.krypter(): Melding {
return this.copy(
processedPayload = kryptering.krypter(this.processedPayload, this.header),
kryptert = true
)
}

class Kryptering {

fun krypter(byteArray: ByteArray, header: Header): ByteArray {
val krypteringSertifikat = hentKrypteringssertifikat(header.cpaId, header.to.herID)
return krypter(byteArray, krypteringSertifikat)
}
fun krypter(byteArray: ByteArray, krypteringSertifikat: ByteArray): ByteArray {
if (byteArray.isEmpty()) {
throw BadRequestException("Meldingen er tom.")
throw EncryptionException("Meldingen er tom.")
}
val sertifikat = createX509Certificate(krypteringSertifikat)
return krypterDokument(byteArray, sertifikat)

}

}
Expand All @@ -55,7 +35,7 @@ private fun krypterDokument(doc: ByteArray, certificate: X509Certificate): ByteA
return try {
krypterDokument(doc, listOf(certificate))
} catch (e: Exception) {
throw e
throw EncryptionException("Feil ved kryptering av dokument", e)
}
}

Expand All @@ -75,8 +55,8 @@ private fun krypterDokument(input: ByteArray, certificates: List<X509Certificate
)
envelopedData.encoded
} catch (e: CertificateEncodingException) {
throw e
throw EncryptionException("Feil ved kryptering av dokument", e)
} catch (e: CMSException) {
throw e
throw EncryptionException("Feil ved kryptering av dokument", e)
}
}
Original file line number Diff line number Diff line change
@@ -1,27 +1,10 @@
package no.nav.emottak.melding.process
package no.nav.emottak.util.signatur

import io.ktor.server.plugins.BadRequestException
import no.nav.emottak.melding.model.Melding
import no.nav.emottak.util.createValidateContext
import no.nav.emottak.util.retrieveXMLSignature
import no.nav.emottak.util.signatur.validateAlgorithms
import no.nav.emottak.util.createDocument
import no.nav.emottak.util.getByteArrayFromDocument
import no.nav.emottak.util.signatur.AlgorithmNotSupportedException
import org.w3c.dom.Document
import java.io.ByteArrayInputStream
import javax.xml.crypto.dsig.XMLSignatureException

private val signatureVerifisering = SignaturVerifisering()

internal fun Melding.verifiserSignatur(): Melding {
return this.copy(
processedPayload = getByteArrayFromDocument(
signatureVerifisering.validerSignatur(createDocument( ByteArrayInputStream(this.processedPayload)))
),
signaturVerifisert = true
)
}

class SignaturVerifisering {

Expand All @@ -31,8 +14,6 @@ class SignaturVerifisering {
val signature = retrieveXMLSignature(validateContext)

try {
//TODO https://bugs.openjdk.java.net/browse/JDK-8259801
//Må vurderes opp mot java 17 for sha1
return if (signature.validate(validateContext)) {
validateAlgorithms(signature.signedInfo)
document
Expand All @@ -42,15 +23,13 @@ class SignaturVerifisering {
signature.signedInfo.references.forEach {
status += ", ${it.digestMethod.algorithm} validation status: ${it.validate(validateContext)}"
}
throw BadRequestException("Sertifikat er ugyldig: $status")
throw SignatureException("Sertifikat er ugyldig: $status")
}
} catch (signatureException: XMLSignatureException) {
throw signatureException
throw SignatureException("Feil ved validering av signatur", signatureException)
} catch (algorithmNotSupported: AlgorithmNotSupportedException) {
throw BadRequestException(algorithmNotSupported.message,algorithmNotSupported)
throw SignatureException("Feil ved validering av signatur", algorithmNotSupported)
}
}



}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package no.nav.emottak.util.signatur

class SignatureException(override val message: String, e: Exception? = null) : Exception(message, e) {
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
package no.nav.emottak.melding.process
package no.nav.emottak.util.signatur

import no.nav.emottak.melding.model.Melding
import no.nav.emottak.util.crypto.getSignerCertificate
import no.nav.emottak.util.crypto.getSignerKey
import no.nav.emottak.util.createDocument
import no.nav.emottak.util.getByteArrayFromDocument
import org.w3c.dom.Document
import java.io.ByteArrayInputStream
import java.security.Key
import java.security.cert.X509Certificate
import javax.xml.crypto.dsig.Reference
Expand All @@ -17,19 +13,6 @@ import javax.xml.crypto.dsig.dom.DOMSignContext
import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec
import javax.xml.crypto.dsig.spec.TransformParameterSpec

private val signering = Signering()
fun signer(document: Document) = signering.signerXML(document)
fun signer(document: Document, alias: String) = signering.signerXML(document, alias)

fun Melding.signer(): Melding {
return this.copy(
processedPayload = getByteArrayFromDocument(
signering.signerXML(createDocument( ByteArrayInputStream(this.processedPayload)))
),
signert = true
)
}


class Signering {

Expand All @@ -40,7 +23,7 @@ class Signering {

private val factory = XMLSignatureFactory.getInstance("DOM")

fun signerXML(doc: Document, alias: String = defaultAlias): Document {
fun signerXML(document: Document, alias: String = defaultAlias): Document {
val signerCertificate: X509Certificate = getSignerCertificate(alias)
val signerKey: Key = getSignerKey(alias)
val keyInfoFactory = factory.keyInfoFactory
Expand All @@ -49,21 +32,11 @@ class Signering {
val x509data = keyInfoFactory.newX509Data(x509Content)
val keyInfo = keyInfoFactory.newKeyInfo(listOf(x509data))

val dsc = DOMSignContext(signerKey, doc.documentElement)
val dsc = DOMSignContext(signerKey, document.documentElement)

val signature = factory.newXMLSignature(createSignedInfo(), keyInfo)
signature.sign(dsc)
return doc
}

private fun createReference(): Reference {
return factory.newReference(
"",
factory.newDigestMethod(digestAlgorithm, null),
listOf(factory.newTransform(Transform.ENVELOPED, null as TransformParameterSpec?)),
null,
null
)
return document
}

private fun createSignedInfo(): SignedInfo {
Expand All @@ -75,5 +48,15 @@ class Signering {
factory.newSignatureMethod(signatureAlgorithm, null), listOf(createReference())
)
}

private fun createReference(): Reference {
return factory.newReference(
"",
factory.newDigestMethod(digestAlgorithm, null),
listOf(factory.newTransform(Transform.ENVELOPED, null as TransformParameterSpec?)),
null,
null
)
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@ package no.nav.emottak.melding
import no.nav.emottak.melding.model.Melding
import no.nav.emottak.melding.model.PayloadRequest
import no.nav.emottak.melding.model.PayloadResponse
import no.nav.emottak.melding.model.dekrypter
import no.nav.emottak.melding.process.dekomprimer
import no.nav.emottak.melding.process.komprimer
import no.nav.emottak.melding.process.krypter
import no.nav.emottak.melding.process.signer
import no.nav.emottak.melding.process.verifiserSignatur
import no.nav.emottak.util.GZipUtil
import no.nav.emottak.util.signatur.SignaturVerifisering
import no.nav.emottak.util.createDocument
import no.nav.emottak.util.crypto.Dekryptering
import no.nav.emottak.util.crypto.Kryptering
import no.nav.emottak.util.getByteArrayFromDocument
import no.nav.emottak.util.hentKrypteringssertifikat
import no.nav.emottak.util.signatur.Signering
import java.io.ByteArrayInputStream

class Processor {

Expand Down Expand Up @@ -46,4 +49,58 @@ class Processor {
fun PayloadRequest.isIncomingMessage(): Boolean {
//TODO
return true
}
}

private val kryptering = Kryptering()
private val dekryptering = Dekryptering()
private val signering = Signering()
private val gZipUtil = GZipUtil()
private val signatureVerifisering = SignaturVerifisering()

fun Melding.dekrypter(isBase64: Boolean = false): Melding {
return this.copy(
processedPayload = dekryptering.dekrypter(this.processedPayload, isBase64),
dekryptert = true
)
}

fun Melding.signer(): Melding {
return this.copy(
processedPayload = getByteArrayFromDocument(
signering.signerXML(createDocument( ByteArrayInputStream(this.processedPayload)))
),
signert = true
)
}

fun Melding.dekomprimer(): Melding {
return this.copy(
processedPayload = gZipUtil.uncompress(this.processedPayload),
dekomprimert = true
)
}

fun Melding.komprimer(): Melding {
return this.copy(
processedPayload = gZipUtil.compress(this.processedPayload),
komprimert = true
)
}

fun Melding.verifiserSignatur(): Melding {
return this.copy(
processedPayload = getByteArrayFromDocument(
signatureVerifisering.validerSignatur(createDocument( ByteArrayInputStream(this.processedPayload)))
),
signaturVerifisert = true
)
}

fun Melding.krypter(): Melding {
val krypteringSertifikat = hentKrypteringssertifikat(header.cpaId, header.to.herID)
return this.copy(
processedPayload = kryptering.krypter(this.processedPayload, krypteringSertifikat),
kryptert = true
)
}

Loading

0 comments on commit f89767f

Please sign in to comment.