From b2aa25e40cd4c96a6cdc614717a214584e042a0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A7alo=20Frade?= <106541307+beatt83@users.noreply.github.com> Date: Tue, 6 Feb 2024 17:45:34 +0000 Subject: [PATCH] fix: on multi encryption master ephemeral key ecdh1pu and ecdhes (#6) Also fixes a bug for encrypting without any recipients. --- .../Encryptors/AESEncryptor.swift | 1 + .../Encryptors/DirectEncrypter.swift | 1 + .../Encryptors/ECDH1PUEncrypter.swift | 21 +++++---- .../Encryptors/ECDHEncrypter.swift | 9 ++-- .../Encryptors/JWEEncrypter.swift | 3 ++ .../Encryptors/MultiEncryptor.swift | 5 +++ .../Encryptors/PasswordBasedEncrypter.swift | 1 + .../Encryptors/RSAEncrypter.swift | 1 + Sources/JSONWebEncryption/JWEParts.swift | 43 +++++++++++++++---- Tests/JWETests/PBES2Tests.swift | 3 ++ 10 files changed, 66 insertions(+), 22 deletions(-) diff --git a/Sources/JSONWebEncryption/EncryptionModule/Encryptors/AESEncryptor.swift b/Sources/JSONWebEncryption/EncryptionModule/Encryptors/AESEncryptor.swift index fbdac09..d309e1a 100644 --- a/Sources/JSONWebEncryption/EncryptionModule/Encryptors/AESEncryptor.swift +++ b/Sources/JSONWebEncryption/EncryptionModule/Encryptors/AESEncryptor.swift @@ -55,6 +55,7 @@ struct AESJWEEncryptor: JWEEncryptor { password: Data?, saltLength: Int?, iterationCount: Int?, + ephemeralKey: JWK?, hasMultiRecipients: Bool ) throws -> JWEParts
{ guard let alg = getKeyAlgorithm( diff --git a/Sources/JSONWebEncryption/EncryptionModule/Encryptors/DirectEncrypter.swift b/Sources/JSONWebEncryption/EncryptionModule/Encryptors/DirectEncrypter.swift index 11de5e3..a2337e2 100644 --- a/Sources/JSONWebEncryption/EncryptionModule/Encryptors/DirectEncrypter.swift +++ b/Sources/JSONWebEncryption/EncryptionModule/Encryptors/DirectEncrypter.swift @@ -50,6 +50,7 @@ struct DirectJWEEncryptor: JWEEncryptor { password: Data?, saltLength: Int?, iterationCount: Int?, + ephemeralKey: JWK?, hasMultiRecipients: Bool ) throws -> JWEParts
{ guard let enc = getEncoding( diff --git a/Sources/JSONWebEncryption/EncryptionModule/Encryptors/ECDH1PUEncrypter.swift b/Sources/JSONWebEncryption/EncryptionModule/Encryptors/ECDH1PUEncrypter.swift index 39ed172..115c515 100644 --- a/Sources/JSONWebEncryption/EncryptionModule/Encryptors/ECDH1PUEncrypter.swift +++ b/Sources/JSONWebEncryption/EncryptionModule/Encryptors/ECDH1PUEncrypter.swift @@ -59,6 +59,7 @@ struct ECDH1PUJWEEncryptor: JWEEncryptor { password: Data?, saltLength: Int?, iterationCount: Int?, + ephemeralKey: JWK?, hasMultiRecipients: Bool ) throws -> JWEParts
{ guard let alg = getKeyAlgorithm( @@ -100,11 +101,9 @@ struct ECDH1PUJWEEncryptor: JWEEncryptor { throw JWE.JWEError.missingRecipientKey } - guard let ephemeralKeyPair = try getEphemeralKey( - protectedHeader: protectedHeader, - unprotectedHeader: unprotectedHeader, - recipientHeader: recipientHeader - ) ?? senderKey.keyGeneration?.generateKeyPairJWK(purpose: .keyAgreement) else { + guard let ephemeralKeyPair = try ephemeralKey ?? + senderKey.keyGeneration?.generateKeyPairJWK(purpose: .keyAgreement) + else { throw JWE.JWEError.missingEphemeralKey } @@ -144,7 +143,8 @@ struct ECDH1PUJWEEncryptor: JWEEncryptor { recipientHeader: finalRecipientHeader, cek: cek, initializationVector: initializationVector, - additionalAuthenticationData: aad + additionalAuthenticationData: aad, + ephemeralKey: ephemeralKeyPair ) } @@ -160,7 +160,8 @@ struct ECDH1PUJWEEncryptor: JWEEncryptor { recipientHeader: R?, cek: Data?, initializationVector: Data?, - additionalAuthenticationData: Data + additionalAuthenticationData: Data, + ephemeralKey: JWK ) throws -> JWEParts
{ guard let alg = getKeyAlgorithm( protectedHeader: protectedHeader, @@ -239,7 +240,8 @@ struct ECDH1PUJWEEncryptor: JWEEncryptor { encryptedKey: encryptedKey.encryptedKey, additionalAuthenticationData: additionalAuthenticationData, initializationVector: contentIv, - authenticationTag: encryptionResult.authenticationData + authenticationTag: encryptionResult.authenticationData, + ephemeralKey: ephemeralKey ) } else { let cek = try deriveSharedKey( @@ -294,7 +296,8 @@ struct ECDH1PUJWEEncryptor: JWEEncryptor { encryptedKey: nil, additionalAuthenticationData: additionalAuthenticationData, initializationVector: contentIv, - authenticationTag: encryptionResult.authenticationData + authenticationTag: encryptionResult.authenticationData, + ephemeralKey: ephemeralKey ) } } diff --git a/Sources/JSONWebEncryption/EncryptionModule/Encryptors/ECDHEncrypter.swift b/Sources/JSONWebEncryption/EncryptionModule/Encryptors/ECDHEncrypter.swift index e254a63..c87a8c3 100644 --- a/Sources/JSONWebEncryption/EncryptionModule/Encryptors/ECDHEncrypter.swift +++ b/Sources/JSONWebEncryption/EncryptionModule/Encryptors/ECDHEncrypter.swift @@ -58,6 +58,7 @@ struct ECDHJWEEncryptor: JWEEncryptor { password: Data?, saltLength: Int?, iterationCount: Int?, + ephemeralKey: JWK?, hasMultiRecipients: Bool ) throws -> JWEParts
{ guard let alg = getKeyAlgorithm( @@ -95,11 +96,9 @@ struct ECDHJWEEncryptor: JWEEncryptor { throw JWE.JWEError.missingRecipientKey } - guard let ephemeralKeyPair = try getEphemeralKey( - protectedHeader: protectedHeader, - unprotectedHeader: unprotectedHeader, - recipientHeader: recipientHeader - ) ?? recipientKey.keyGeneration?.generateKeyPairJWK(purpose: .keyAgreement) else { + guard let ephemeralKeyPair = try ephemeralKey + ?? recipientKey.keyGeneration?.generateKeyPairJWK(purpose: .keyAgreement) + else { throw JWE.JWEError.missingEphemeralKey } diff --git a/Sources/JSONWebEncryption/EncryptionModule/Encryptors/JWEEncrypter.swift b/Sources/JSONWebEncryption/EncryptionModule/Encryptors/JWEEncrypter.swift index 8ef8a51..a058fd2 100644 --- a/Sources/JSONWebEncryption/EncryptionModule/Encryptors/JWEEncrypter.swift +++ b/Sources/JSONWebEncryption/EncryptionModule/Encryptors/JWEEncrypter.swift @@ -56,6 +56,7 @@ public protocol JWEEncryptor { password: Data?, saltLength: Int?, iterationCount: Int?, + ephemeralKey: JWK?, hasMultiRecipients: Bool ) throws -> JWEParts
} @@ -130,6 +131,7 @@ extension JWEEncryptor { password: Data? = nil, saltLength: Int? = nil, iterationCount: Int? = nil, + ephemeralKey: JWK? = nil, multiRecipients: Bool = false ) throws -> JWEParts
{ try self.encrypt( @@ -145,6 +147,7 @@ extension JWEEncryptor { password: password, saltLength: saltLength, iterationCount: iterationCount, + ephemeralKey: ephemeralKey, hasMultiRecipients: multiRecipients ) } diff --git a/Sources/JSONWebEncryption/EncryptionModule/Encryptors/MultiEncryptor.swift b/Sources/JSONWebEncryption/EncryptionModule/Encryptors/MultiEncryptor.swift index 7f0872e..9446ca6 100644 --- a/Sources/JSONWebEncryption/EncryptionModule/Encryptors/MultiEncryptor.swift +++ b/Sources/JSONWebEncryption/EncryptionModule/Encryptors/MultiEncryptor.swift @@ -37,6 +37,9 @@ struct MultiEncryptor: JWEMultiEncryptor { iterationCount: Int?, encryptionModule: JWEEncryptionModule = .default ) throws -> [JWEParts
] { + guard !recipients.isEmpty else { + throw JWE.JWEError.noRecipients + } guard let enc = getEncoding( protectedHeader: protectedHeader, unprotectedHeader: unprotectedHeader, @@ -70,6 +73,7 @@ struct MultiEncryptor: JWEMultiEncryptor { password: password, saltLength: saltLength, iterationCount: iterationCount, + ephemeralKey: nil, hasMultiRecipients: true ) @@ -95,6 +99,7 @@ struct MultiEncryptor: JWEMultiEncryptor { password: password, saltLength: saltLength, iterationCount: iterationCount, + ephemeralKey: firstEncryption.ephemeralKey, hasMultiRecipients: true ) } diff --git a/Sources/JSONWebEncryption/EncryptionModule/Encryptors/PasswordBasedEncrypter.swift b/Sources/JSONWebEncryption/EncryptionModule/Encryptors/PasswordBasedEncrypter.swift index 1713cb9..63095ab 100644 --- a/Sources/JSONWebEncryption/EncryptionModule/Encryptors/PasswordBasedEncrypter.swift +++ b/Sources/JSONWebEncryption/EncryptionModule/Encryptors/PasswordBasedEncrypter.swift @@ -56,6 +56,7 @@ struct PasswordBasedJWEEncryptor: JWEEncryptor { password: Data?, saltLength: Int?, iterationCount: Int?, + ephemeralKey: JWK?, hasMultiRecipients: Bool ) throws -> JWEParts
{ let iterationCount = getSaltCount( diff --git a/Sources/JSONWebEncryption/EncryptionModule/Encryptors/RSAEncrypter.swift b/Sources/JSONWebEncryption/EncryptionModule/Encryptors/RSAEncrypter.swift index 272a6bc..d62682d 100644 --- a/Sources/JSONWebEncryption/EncryptionModule/Encryptors/RSAEncrypter.swift +++ b/Sources/JSONWebEncryption/EncryptionModule/Encryptors/RSAEncrypter.swift @@ -52,6 +52,7 @@ struct RSAJWEEncryptor: JWEEncryptor { password: Data?, saltLength: Int?, iterationCount: Int?, + ephemeralKey: JWK?, hasMultiRecipients: Bool ) throws -> JWEParts
{
guard let alg = getKeyAlgorithm(
diff --git a/Sources/JSONWebEncryption/JWEParts.swift b/Sources/JSONWebEncryption/JWEParts.swift
index 7657196..745f3d4 100644
--- a/Sources/JSONWebEncryption/JWEParts.swift
+++ b/Sources/JSONWebEncryption/JWEParts.swift
@@ -15,6 +15,7 @@
*/
import Foundation
+import JSONWebKey
// `JWEParts` represents the constituent parts of a JSON Web Encryption (JWE) object.
/// It's a generic struct that can accommodate different types of headers for both protected and recipient-specific data.
@@ -23,25 +24,28 @@ import Foundation
/// - R: A type conforming to `JWERegisteredFieldsHeader` used for the recipient-specific header.
public struct JWEParts