From 47100c2d0eef09822c5f8e29b231fc5909f44185 Mon Sep 17 00:00:00 2001 From: Dimitri Bouniol Date: Sun, 2 Mar 2025 04:06:10 -0800 Subject: [PATCH 1/2] Added a failing test when an otherwise valid key ID is encoded using Base64 instead of URL-encoded Base64, and keys would therefor not match during lookups --- Tests/WebPushTests/VAPIDKeyTests.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/Tests/WebPushTests/VAPIDKeyTests.swift b/Tests/WebPushTests/VAPIDKeyTests.swift index 0c5650d..6a58353 100644 --- a/Tests/WebPushTests/VAPIDKeyTests.swift +++ b/Tests/WebPushTests/VAPIDKeyTests.swift @@ -101,6 +101,7 @@ import WebPushTesting @Test func decoding() throws { #expect(try JSONDecoder().decode(VAPID.Key.ID.self, from: Data("\"BLf3RZAljlexEovBgfZgFTjcEVUKBDr3lIH8quJioMdX4FweRdId_P72h613ptxtU-qSAyW3Tbt_3WgwGhOUxrs\"".utf8)) == .mockedKeyID1) + #expect(try JSONDecoder().decode(VAPID.Key.ID.self, from: Data("\"BLf3RZAljlexEovBgfZgFTjcEVUKBDr3lIH8quJioMdX4FweRdId/P72h613ptxtU+qSAyW3Tbt/3WgwGhOUxrs=\"".utf8)) == .mockedKeyID1) } } } From 3da8d4bf846c321460a20a1fc8878e1d7c78d034 Mon Sep 17 00:00:00 2001 From: Dimitri Bouniol Date: Sun, 2 Mar 2025 04:06:44 -0800 Subject: [PATCH 2/2] Fixed an issue where Base64-encoded key IDs would fail lookups against the known set of keys Fixes #65 --- .../WebPush/Helpers/DataProtocol+Base64URLCoding.swift | 10 +++++++++- Sources/WebPush/VAPID/VAPIDKey.swift | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/Sources/WebPush/Helpers/DataProtocol+Base64URLCoding.swift b/Sources/WebPush/Helpers/DataProtocol+Base64URLCoding.swift index fc8ed68..bbc4559 100644 --- a/Sources/WebPush/Helpers/DataProtocol+Base64URLCoding.swift +++ b/Sources/WebPush/Helpers/DataProtocol+Base64URLCoding.swift @@ -19,7 +19,15 @@ extension DataProtocol { func base64URLEncodedString() -> String { Data(self) .base64EncodedString() - .replacingOccurrences(of: "+", with: "-") + .transformToBase64URLEncoding() + } +} + +extension String { + /// Transform a regular Base64 encoded string to a Base64URL encoded one. + @usableFromInline + func transformToBase64URLEncoding() -> String { + self.replacingOccurrences(of: "+", with: "-") .replacingOccurrences(of: "/", with: "_") .replacingOccurrences(of: "=", with: "") } diff --git a/Sources/WebPush/VAPID/VAPIDKey.swift b/Sources/WebPush/VAPID/VAPIDKey.swift index f101d21..3355c28 100644 --- a/Sources/WebPush/VAPID/VAPIDKey.swift +++ b/Sources/WebPush/VAPID/VAPIDKey.swift @@ -86,7 +86,7 @@ extension VAPID.Key: Identifiable { public init(from decoder: any Decoder) throws { let container = try decoder.singleValueContainer() - self.rawValue = try container.decode(String.self) + self.rawValue = try container.decode(String.self).transformToBase64URLEncoding() } public func encode(to encoder: any Encoder) throws {