summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAntoine A <>2024-03-27 00:11:10 +0100
committerAntoine A <>2024-03-27 00:11:10 +0100
commit9dfbc9391fe27fc631bdf61e3e51dd3a124a4c60 (patch)
tree5cc6cae102a6983044778494388fae039b76b057
parent00e8988a760d8e73225424185701c1f59508840a (diff)
downloadlibeufin-9dfbc9391fe27fc631bdf61e3e51dd3a124a4c60.tar.gz
libeufin-9dfbc9391fe27fc631bdf61e3e51dd3a124a4c60.tar.bz2
libeufin-9dfbc9391fe27fc631bdf61e3e51dd3a124a4c60.zip
Improve self-signed certificate
-rw-r--r--common/src/main/kotlin/crypto/utils.kt80
-rw-r--r--common/src/test/kotlin/CryptoUtilTest.kt6
-rw-r--r--nexus/src/main/kotlin/tech/libeufin/nexus/KeyFiles.kt4
-rw-r--r--nexus/src/main/kotlin/tech/libeufin/nexus/PDF.kt2
-rw-r--r--nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsConstants.kt9
-rw-r--r--nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsKeyMng.kt6
-rw-r--r--nexus/src/test/kotlin/XmlUtilTest.kt2
7 files changed, 49 insertions, 60 deletions
diff --git a/common/src/main/kotlin/crypto/utils.kt b/common/src/main/kotlin/crypto/utils.kt
index 1228eb91..10fa195e 100644
--- a/common/src/main/kotlin/crypto/utils.kt
+++ b/common/src/main/kotlin/crypto/utils.kt
@@ -43,12 +43,8 @@ import javax.crypto.spec.PBEParameterSpec
import javax.crypto.spec.SecretKeySpec
import tech.libeufin.common.*
-/**
- * Helpers for dealing with cryptographic operations in EBICS / LibEuFin.
- */
+/** Helpers for dealing with cryptographic operations in EBICS / LibEuFin */
object CryptoUtil {
- // TODO split common and ebics crypto
-
/**
* RSA key pair.
*/
@@ -64,10 +60,8 @@ object CryptoUtil {
private val provider = BouncyCastleProvider()
- /**
- * Load an RSA private key from its binary PKCS#8 encoding.
- */
- fun loadRsaPrivateKey(encodedPrivateKey: ByteArray): RSAPrivateCrtKey {
+ /** Load an RSA private key from its binary PKCS#8 encoding */
+ fun loadRSAPrivate(encodedPrivateKey: ByteArray): RSAPrivateCrtKey {
val spec = PKCS8EncodedKeySpec(encodedPrivateKey)
val priv = KeyFactory.getInstance("RSA").generatePrivate(spec)
if (priv !is RSAPrivateCrtKey)
@@ -75,10 +69,8 @@ object CryptoUtil {
return priv
}
- /**
- * Load an RSA public key from its binary X509 encoding.
- */
- fun loadRsaPublicKey(encodedPublicKey: ByteArray): RSAPublicKey {
+ /** Load an RSA public key from its binary X509 encoding */
+ fun loadRSAPublic(encodedPublicKey: ByteArray): RSAPublicKey {
val spec = X509EncodedKeySpec(encodedPublicKey)
val pub = KeyFactory.getInstance("RSA").generatePublic(spec)
if (pub !is RSAPublicKey)
@@ -86,52 +78,42 @@ object CryptoUtil {
return pub
}
- /**
- * Load an RSA public key from its components.
- *
- * @param exponent
- * @param modulus
- * @return key
- */
- fun loadRsaPublicKeyFromComponents(modulus: ByteArray, exponent: ByteArray): RSAPublicKey {
+ /** Create an RSA public key from its components: [modulus] and [exponent] */
+ fun RSAPublicFromComponents(modulus: ByteArray, exponent: ByteArray): RSAPublicKey {
val modulusBigInt = BigInteger(1, modulus)
val exponentBigInt = BigInteger(1, exponent)
-
- val keyFactory = KeyFactory.getInstance("RSA")
- val tmp = RSAPublicKeySpec(modulusBigInt, exponentBigInt)
- return keyFactory.generatePublic(tmp) as RSAPublicKey
+ val spec = RSAPublicKeySpec(modulusBigInt, exponentBigInt)
+ return KeyFactory.getInstance("RSA").generatePublic(spec) as RSAPublicKey
}
- fun loadRsaPublicKeyFromCertificate(certificate: ByteArray): RSAPublicKey {
- val cf = CertificateFactory.getInstance("X.509");
- val c = cf.generateCertificate(certificate.inputStream());
- return c.getPublicKey() as RSAPublicKey
+ /** Extract an RSA public key from a [raw] X.509 certificate */
+ fun RSAPublicFromCertificate(raw: ByteArray): RSAPublicKey {
+ val certificate = CertificateFactory.getInstance("X.509").generateCertificate(raw.inputStream());
+ return certificate.getPublicKey() as RSAPublicKey
}
- /**
- * Load an RSA public key from its binary X509 encoding.
- */
- fun getRsaPublicFromPrivate(rsaPrivateCrtKey: RSAPrivateCrtKey): RSAPublicKey {
- val spec = RSAPublicKeySpec(rsaPrivateCrtKey.modulus, rsaPrivateCrtKey.publicExponent)
- val pub = KeyFactory.getInstance("RSA").generatePublic(spec)
- if (pub !is RSAPublicKey)
- throw Exception("wrong encoding")
- return pub
+ /** Generate an RSA public key from a [private] one */
+ fun RSAPublicFromPrivate(private: RSAPrivateCrtKey): RSAPublicKey {
+ val spec = RSAPublicKeySpec(private.modulus, private.publicExponent)
+ return KeyFactory.getInstance("RSA").generatePublic(spec) as RSAPublicKey
}
- fun certificateFromPrivate(rsaPrivateCrtKey: RSAPrivateCrtKey): X509Certificate {
- val now = System.currentTimeMillis()
+ /** Generate a self-signed X.509 certificate from an RSA [private] key */
+ fun X509CertificateFromRSAPrivate(private: RSAPrivateCrtKey, name: String): X509Certificate {
+ val start = Date()
val calendar = Calendar.getInstance()
- calendar.time = Date(now)
- calendar.add(Calendar.YEAR, 1) // TODO certificate validity
+ calendar.time = start
+ calendar.add(Calendar.YEAR, 1_000)
+ val end = calendar.time
+ val name = X500Name("CN=$name")
val builder = JcaX509v3CertificateBuilder(
- X500Name("CN=test"), // TODO certificate CN
- BigInteger(now.toString()), // TODO certificate serial number
- Date(now),
- calendar.time,
- X500Name("CN=test"),
- getRsaPublicFromPrivate(rsaPrivateCrtKey)
+ name,
+ BigInteger(20, Random()),
+ start,
+ end,
+ name,
+ RSAPublicFromPrivate(private)
)
@@ -148,7 +130,7 @@ object CryptoUtil {
))
builder.addExtension(Extension.basicConstraints, true, BasicConstraints(true))
- val certificate = JcaContentSignerBuilder("SHA256WithRSA").build(rsaPrivateCrtKey)
+ val certificate = JcaContentSignerBuilder("SHA256WithRSA").build(private)
return JcaX509CertificateConverter()
.setProvider(provider)
.getCertificate(builder.build(certificate))
diff --git a/common/src/test/kotlin/CryptoUtilTest.kt b/common/src/test/kotlin/CryptoUtilTest.kt
index 82f18ab9..f76701ad 100644
--- a/common/src/test/kotlin/CryptoUtilTest.kt
+++ b/common/src/test/kotlin/CryptoUtilTest.kt
@@ -35,7 +35,7 @@ class CryptoUtilTest {
@Test
fun loadFromModulusAndExponent() {
val keyPair = CryptoUtil.generateRsaKeyPair(1024)
- val pub2 = CryptoUtil.loadRsaPublicKeyFromComponents(
+ val pub2 = CryptoUtil.RSAPublicFromComponents(
keyPair.public.modulus.toByteArray(),
keyPair.public.publicExponent.toByteArray()
)
@@ -57,7 +57,7 @@ class CryptoUtilTest {
val encodedPriv = keyPair.private.encoded
val encodedPub = keyPair.public.encoded
val otherKeyPair =
- CryptoUtil.RsaCrtKeyPair(CryptoUtil.loadRsaPrivateKey(encodedPriv), CryptoUtil.loadRsaPublicKey(encodedPub))
+ CryptoUtil.RsaCrtKeyPair(CryptoUtil.loadRSAPrivate(encodedPriv), CryptoUtil.loadRSAPublic(encodedPub))
assertEquals(keyPair.private, otherKeyPair.private)
assertEquals(keyPair.public, otherKeyPair.public)
}
@@ -129,7 +129,7 @@ class CryptoUtilTest {
val expectedHash = expectedHashStr.replace(" ", "").replace("\n", "").toByteArray(Charsets.UTF_8)
- val pub = CryptoUtil.loadRsaPublicKeyFromComponents(moduloStr.decodeUpHex(), exponentStr.decodeUpHex())
+ val pub = CryptoUtil.RSAPublicFromComponents(moduloStr.decodeUpHex(), exponentStr.decodeUpHex())
println("echoed pub exp: ${pub.publicExponent.encodeHex()}")
println("echoed pub mod: ${pub.modulus.encodeHex()}")
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/KeyFiles.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/KeyFiles.kt
index fd91cfd4..b4acbb75 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/KeyFiles.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/KeyFiles.kt
@@ -58,7 +58,7 @@ object RSAPublicKeySerializer : KSerializer<RSAPublicKey> {
override fun deserialize(decoder: Decoder): RSAPublicKey {
val fieldValue = decoder.decodeString()
val bytes = Base32Crockford.decode(fieldValue)
- return CryptoUtil.loadRsaPublicKey(bytes)
+ return CryptoUtil.loadRSAPublic(bytes)
}
}
@@ -76,7 +76,7 @@ object RSAPrivateCrtKeySerializer : KSerializer<RSAPrivateCrtKey> {
override fun deserialize(decoder: Decoder): RSAPrivateCrtKey {
val fieldValue = decoder.decodeString()
val bytes = Base32Crockford.decode(fieldValue)
- return CryptoUtil.loadRsaPrivateKey(bytes)
+ return CryptoUtil.loadRSAPrivate(bytes)
}
}
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/PDF.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/PDF.kt
index a485477c..dd595d31 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/PDF.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/PDF.kt
@@ -73,7 +73,7 @@ fun generateKeysPdf(
}
fun writeKey(doc: Document, priv: RSAPrivateCrtKey) {
- val pub = CryptoUtil.getRsaPublicFromPrivate(priv)
+ val pub = CryptoUtil.RSAPublicFromPrivate(priv)
val hash = CryptoUtil.getEbicsPublicKeyHash(pub)
doc.add(Paragraph("Exponent:\n${formatHex(pub.publicExponent.toByteArray())}"))
doc.add(Paragraph("Modulus:\n${formatHex(pub.modulus.toByteArray())}"))
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsConstants.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsConstants.kt
index fc217c2a..8841866f 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsConstants.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsConstants.kt
@@ -46,9 +46,16 @@ enum class EbicsReturnCode(val code: String) {
EBICS_TX_SEGMENT_NUMBER_EXCEEDED("091104"),
EBICS_INVALID_REQUEST_CONTENT("091113"),
EBICS_PROCESSING_ERROR("091116"),
-
// Key-Management errors
+ EBICS_KEYMGMT_UNSUPPORTED_VERSION_SIGNATURE("091201"),
+ EBICS_KEYMGMT_UNSUPPORTED_VERSION_AUTHENTICATION("091202"),
+ EBICS_KEYMGMT_UNSUPPORTED_VERSION_ENCRYPTION("091203"),
+ EBICS_KEYMGMT_KEYLENGTH_ERROR_SIGNATURE("091204"),
+ EBICS_KEYMGMT_KEYLENGTH_ERROR_AUTHENTICATION("091205"),
+ EBICS_KEYMGMT_KEYLENGTH_ERROR_ENCRYPTION("091206"),
+ EBICS_X509_CERTIFICATE_EXPIRED("091208"),
+ EBICS_X509_CERTIFICATE_NOT_VALID_YET("091209"),
EBICS_X509_WRONG_KEY_USAGE("091210"),
EBICS_X509_WRONG_ALGORITHM("091211"),
EBICS_X509_INVALID_THUMBPRINT("091212"),
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsKeyMng.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsKeyMng.kt
index 02db79a0..9141430a 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsKeyMng.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsKeyMng.kt
@@ -111,7 +111,7 @@ class EbicsKeyMng(
private fun XmlBuilder.RSAKeyXml(key: RSAPrivateCrtKey) {
if (ebics3) {
- val cert = CryptoUtil.certificateFromPrivate(key)
+ val cert = CryptoUtil.X509CertificateFromRSAPrivate(key, cfg.myIbanAccount.name)
el("ds:X509Data") {
el("ds:X509Certificate", cert.encoded.encodeBase64())
}
@@ -175,10 +175,10 @@ class EbicsKeyMng(
fun XmlDestructor.rsaPubKey(): RSAPublicKey {
val cert = opt("X509Data")?.one("X509Certificate")?.text()?.decodeBase64()
return if (cert != null) {
- CryptoUtil.loadRsaPublicKeyFromCertificate(cert)
+ CryptoUtil.RSAPublicFromCertificate(cert)
} else {
one("PubKeyValue").one("RSAKeyValue") {
- CryptoUtil.loadRsaPublicKeyFromComponents(
+ CryptoUtil.RSAPublicFromComponents(
one("Modulus").text().decodeBase64(),
one("Exponent").text().decodeBase64(),
)
diff --git a/nexus/src/test/kotlin/XmlUtilTest.kt b/nexus/src/test/kotlin/XmlUtilTest.kt
index 03941f3f..a60e0904 100644
--- a/nexus/src/test/kotlin/XmlUtilTest.kt
+++ b/nexus/src/test/kotlin/XmlUtilTest.kt
@@ -67,7 +67,7 @@ class XmlUtilTest {
val doc = XMLUtil.parseIntoDom(docText)
val keyStream = classLoader.getResourceAsStream("signature1/public_key.txt")
val keyBytes = keyStream.decodeBase64().readAllBytes()
- val key = CryptoUtil.loadRsaPublicKey(keyBytes)
+ val key = CryptoUtil.loadRSAPublic(keyBytes)
assertTrue(XMLUtil.verifyEbicsDocument(doc, key, "H004"))
}
} \ No newline at end of file