This is an automated email from the ASF dual-hosted git repository. rcordier pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/james-project.git
commit 0ba0a6475c7ec7b65a4e7e2b0b75e4a769347d4f Author: Benoit Tellier <[email protected]> AuthorDate: Thu Oct 28 14:28:17 2021 +0700 JAMES-3539 Allow web push encryption --- pom.xml | 11 +++++++++ server/blob/blob-aes/pom.xml | 1 - server/data/data-jmap/pom.xml | 8 +++++++ .../james/jmap/api/model/PushSubscription.scala | 28 +++++++++++++++++++--- 4 files changed, 44 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 04ec3a3..fe0c09b 100644 --- a/pom.xml +++ b/pom.xml @@ -641,6 +641,7 @@ <jasypt.version>1.9.3</jasypt.version> <guice.version>5.0.1</guice.version> <logback.version>1.2.5</logback.version> + <tink.version>1.6.1</tink.version> <bouncycastle.version>1.69</bouncycastle.version> @@ -2077,6 +2078,16 @@ <version>1.2.0</version> </dependency> <dependency> + <groupId>com.google.crypto.tink</groupId> + <artifactId>apps-webpush</artifactId> + <version>${tink.version}</version> + </dependency> + <dependency> + <groupId>com.google.crypto.tink</groupId> + <artifactId>tink</artifactId> + <version>${tink.version}</version> + </dependency> + <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>${guava.version}</version> diff --git a/server/blob/blob-aes/pom.xml b/server/blob/blob-aes/pom.xml index b84693a..b612894 100644 --- a/server/blob/blob-aes/pom.xml +++ b/server/blob/blob-aes/pom.xml @@ -59,7 +59,6 @@ <dependency> <groupId>com.google.crypto.tink</groupId> <artifactId>tink</artifactId> - <version>1.6.1</version> </dependency> <dependency> <groupId>com.google.guava</groupId> diff --git a/server/data/data-jmap/pom.xml b/server/data/data-jmap/pom.xml index daec8fc..4048502 100644 --- a/server/data/data-jmap/pom.xml +++ b/server/data/data-jmap/pom.xml @@ -100,6 +100,14 @@ <scope>test</scope> </dependency> <dependency> + <groupId>com.google.crypto.tink</groupId> + <artifactId>apps-webpush</artifactId> + </dependency> + <dependency> + <groupId>com.google.crypto.tink</groupId> + <artifactId>tink</artifactId> + </dependency> + <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> </dependency> diff --git a/server/data/data-jmap/src/main/scala/org/apache/james/jmap/api/model/PushSubscription.scala b/server/data/data-jmap/src/main/scala/org/apache/james/jmap/api/model/PushSubscription.scala index 31080f7..a88a5f8 100644 --- a/server/data/data-jmap/src/main/scala/org/apache/james/jmap/api/model/PushSubscription.scala +++ b/server/data/data-jmap/src/main/scala/org/apache/james/jmap/api/model/PushSubscription.scala @@ -20,8 +20,14 @@ package org.apache.james.jmap.api.model import java.net.URL -import java.time.{Clock, ZonedDateTime} -import java.util.UUID +import java.security.interfaces.ECPublicKey +import java.time.ZonedDateTime +import java.util.{Base64, UUID} + +import com.google.crypto.tink.HybridEncrypt +import com.google.crypto.tink.apps.webpush.WebPushHybridEncrypt +import com.google.crypto.tink.subtle.EllipticCurves + import scala.util.Try object PushSubscriptionId { @@ -49,7 +55,23 @@ case class PushSubscriptionExpiredTime(value: ZonedDateTime) { def isBefore(date: ZonedDateTime): Boolean = value.isBefore(date) } -case class PushSubscriptionKeys(p256dh: String, auth: String) +object PushSubscriptionKeys { + def validate(keys: PushSubscriptionKeys): Try[PushSubscriptionKeys] = Try(keys.asHybridEncrypt()).map(_ => keys) +} + +case class PushSubscriptionKeys(p256dh: String, auth: String) { + // Follows https://datatracker.ietf.org/doc/html/rfc8291 + // Message Encryption for Web Push + def encrypt(payload: Array[Byte]): Array[Byte] = asHybridEncrypt() + .encrypt(payload, null) + + private def asHybridEncrypt(): HybridEncrypt = new WebPushHybridEncrypt.Builder() + .withAuthSecret(Base64.getDecoder().decode(auth)) + .withRecipientPublicKey(asECPublicKey()) + .build() + + private def asECPublicKey(): ECPublicKey = EllipticCurves.getEcPublicKey(Base64.getDecoder.decode(p256dh)) +} case class PushSubscriptionCreationRequest(deviceClientId: DeviceClientId, url: PushSubscriptionServerURL, --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
