[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[libeufin] branch master updated: Importing passphrase protection into t
From: |
gnunet |
Subject: |
[libeufin] branch master updated: Importing passphrase protection into the Web server. |
Date: |
Thu, 21 Nov 2019 04:50:31 +0100 |
This is an automated email from the git hooks/post-receive script.
marcello pushed a commit to branch master
in repository libeufin.
The following commit(s) were added to refs/heads/master by this push:
new 0e3fc33 Importing passphrase protection into the Web server.
0e3fc33 is described below
commit 0e3fc336694f42c2844b940015ec8e43b42f851c
Author: Marcello Stanisci <address@hidden>
AuthorDate: Thu Nov 21 04:50:06 2019 +0100
Importing passphrase protection into the Web server.
---
nexus/src/main/kotlin/JSON.kt | 12 ++++-
nexus/src/main/kotlin/Main.kt | 62 ++++++++++++++++++----
.../kotlin/tech/libeufin/sandbox/CryptoUtil.kt | 4 +-
sandbox/src/test/kotlin/CryptoUtilTest.kt | 6 +--
4 files changed, 68 insertions(+), 16 deletions(-)
diff --git a/nexus/src/main/kotlin/JSON.kt b/nexus/src/main/kotlin/JSON.kt
index 5691f58..7dcb0a6 100644
--- a/nexus/src/main/kotlin/JSON.kt
+++ b/nexus/src/main/kotlin/JSON.kt
@@ -4,8 +4,18 @@ import com.google.gson.annotations.JsonAdapter
import com.squareup.moshi.JsonClass
-data class EbicsKeysBackup(
+data class EbicsBackupRequest(
+ val passphrase: String
+)
+
+/**
+ * This object is used twice: as a response to the backup request,
+ * and as a request to the backup restore. Note: in the second case
+ * the client must provide the passphrase.
+ */
+data class EbicsKeysBackup(
+ val passphrase: String? = null,
val authBlob: ByteArray,
val encBlob: ByteArray,
val sigBlob: ByteArray
diff --git a/nexus/src/main/kotlin/Main.kt b/nexus/src/main/kotlin/Main.kt
index 9bda6d7..26efa7c 100644
--- a/nexus/src/main/kotlin/Main.kt
+++ b/nexus/src/main/kotlin/Main.kt
@@ -30,14 +30,13 @@ import io.ktor.features.ContentNegotiation
import io.ktor.features.StatusPages
import io.ktor.gson.gson
import io.ktor.http.ContentType
+import io.ktor.http.HttpMethod
import io.ktor.http.HttpStatusCode
import io.ktor.request.receive
import io.ktor.request.uri
import io.ktor.response.respond
import io.ktor.response.respondText
-import io.ktor.routing.get
-import io.ktor.routing.post
-import io.ktor.routing.routing
+import io.ktor.routing.*
import io.ktor.server.engine.embeddedServer
import io.ktor.server.netty.Netty
import org.apache.commons.codec.digest.Crypt
@@ -63,6 +62,7 @@ import java.time.Instant.now
import java.util.*
import java.util.zip.DeflaterInputStream
import java.util.zip.InflaterInputStream
+import javax.crypto.EncryptedPrivateKeyInfo
import javax.xml.datatype.DatatypeFactory
import javax.xml.datatype.XMLGregorianCalendar
@@ -241,6 +241,7 @@ data class UnreachableBankError(val statusCode:
HttpStatusCode) : Exception("Cou
data class UnparsableResponse(val statusCode: HttpStatusCode, val rawResponse:
String) : Exception("bank responded: ${rawResponse}")
data class EbicsError(val codeError: String) : Exception("Bank did not
accepted EBICS request, error is: ${codeError}")
data class BadSignature(val statusCode: HttpStatusCode) : Exception("Signature
verification unsuccessful")
+data class BadBackup(val statusCode: HttpStatusCode) : Exception("Could not
restore backed up keys")
@@ -282,6 +283,11 @@ fun main() {
call.respondText("Bad request\n", ContentType.Text.Plain,
HttpStatusCode.BadRequest)
}
+ exception<BadBackup> { cause ->
+ logger.error("Exception while handling '${call.request.uri}'",
cause)
+ call.respondText("Bad backup, or passphrase incorrect\n",
ContentType.Text.Plain, HttpStatusCode.BadRequest)
+ }
+
exception<UnparsableResponse> { cause ->
logger.error("Exception while handling '${call.request.uri}'",
cause)
@@ -743,11 +749,32 @@ fun main() {
val body = call.receive<EbicsKeysBackup>()
val id = expectId(call.parameters["id"])
+ val (authKey, encKey, sigKey) = try {
+
+ val authKey = CryptoUtil.decryptKey(
+ EncryptedPrivateKeyInfo(body.authBlob),
body.passphrase!!
+ )
+
+ val encKey = CryptoUtil.decryptKey(
+ EncryptedPrivateKeyInfo(body.encBlob), body.passphrase
+ )
+
+ val sigKey = CryptoUtil.decryptKey(
+ EncryptedPrivateKeyInfo(body.sigBlob), body.passphrase
+ )
+
+ Triple(authKey, encKey, sigKey)
+
+ } catch (e: Exception) {
+ throw BadBackup(HttpStatusCode.BadRequest)
+ }
+
transaction {
val subscriber = EbicsSubscriberEntity.findById(id) ?:
throw SubscriberNotFoundError(HttpStatusCode.NotFound)
- subscriber.encryptionPrivateKey = SerialBlob(body.encBlob)
- subscriber.authenticationPrivateKey =
SerialBlob(body.authBlob)
- subscriber.signaturePrivateKey = SerialBlob(body.sigBlob)
+
+ subscriber.encryptionPrivateKey =
SerialBlob(authKey.encoded)
+ subscriber.authenticationPrivateKey =
SerialBlob(encKey.encoded)
+ subscriber.signaturePrivateKey = SerialBlob(sigKey.encoded)
}
call.respondText(
@@ -758,15 +785,30 @@ fun main() {
}
- get("/ebics/subscribers/{id}/backup") {
+ put("/ebics/subscribers/{id}/backup") {
val id = expectId(call.parameters["id"])
+ val body = call.receive<EbicsBackupRequest>()
+
val content = transaction {
val subscriber = EbicsSubscriberEntity.findById(id) ?:
throw SubscriberNotFoundError(HttpStatusCode.NotFound)
+
+
EbicsKeysBackup(
- authBlob =
subscriber.authenticationPrivateKey.toByteArray(),
- encBlob =
subscriber.encryptionPrivateKey.toByteArray(),
- sigBlob = subscriber.signaturePrivateKey.toByteArray()
+
+ authBlob = CryptoUtil.encryptKey(
+ subscriber.authenticationPrivateKey.toByteArray(),
+ body.passphrase
+ ),
+
+ encBlob = CryptoUtil.encryptKey(
+ subscriber.encryptionPrivateKey.toByteArray(),
+ body.passphrase),
+
+ sigBlob = CryptoUtil.encryptKey(
+ subscriber.signaturePrivateKey.toByteArray(),
+ body.passphrase
+ )
)
}
diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/CryptoUtil.kt
b/sandbox/src/main/kotlin/tech/libeufin/sandbox/CryptoUtil.kt
index fdd0233..4bf0c7a 100644
--- a/sandbox/src/main/kotlin/tech/libeufin/sandbox/CryptoUtil.kt
+++ b/sandbox/src/main/kotlin/tech/libeufin/sandbox/CryptoUtil.kt
@@ -213,7 +213,7 @@ object CryptoUtil {
}
- fun decryptSecret(data: EncryptedPrivateKeyInfo, passphrase: String):
RSAPrivateCrtKey {
+ fun decryptKey(data: EncryptedPrivateKeyInfo, passphrase: String):
RSAPrivateCrtKey {
/* make key out of passphrase */
val pbeKeySpec = PBEKeySpec(passphrase.toCharArray())
@@ -236,7 +236,7 @@ object CryptoUtil {
return priv
}
- fun encryptSecret(data: ByteArray, passphrase: String): ByteArray {
+ fun encryptKey(data: ByteArray, passphrase: String): ByteArray {
/* Cipher parameters: salt and hash count */
val hashIterations = 30
diff --git a/sandbox/src/test/kotlin/CryptoUtilTest.kt
b/sandbox/src/test/kotlin/CryptoUtilTest.kt
index bee8d0c..229e067 100644
--- a/sandbox/src/test/kotlin/CryptoUtilTest.kt
+++ b/sandbox/src/test/kotlin/CryptoUtilTest.kt
@@ -85,12 +85,12 @@ class CryptoUtilTest {
val secret = CryptoUtil.encryptEbicsE002(data, keyPair.public)
/* encrypt and decrypt private key */
- val encPriv = CryptoUtil.encryptSecret(keyPair.private.encoded,
"secret")
- val plainPriv =
CryptoUtil.decryptSecret(EncryptedPrivateKeyInfo(encPriv),"secret")
+ val encPriv = CryptoUtil.encryptKey(keyPair.private.encoded, "secret")
+ val plainPriv =
CryptoUtil.decryptKey(EncryptedPrivateKeyInfo(encPriv),"secret")
/* decrypt with decrypted private key */
val revealed = CryptoUtil.decryptEbicsE002(secret, plainPriv)
-
+
assertEquals(
String(revealed, charset = Charsets.UTF_8),
String(data, charset = Charsets.UTF_8)
--
To stop receiving notification emails like this one, please contact
address@hidden.
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [libeufin] branch master updated: Importing passphrase protection into the Web server.,
gnunet <=