From 5b37d2fb274bd8e873cb7bbe9dc6fedf9259e767 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Fri, 16 Jan 2026 02:55:24 -0600 Subject: [PATCH] [helpers] Support `base64url` encoding (#13264) --- esphome/core/helpers.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/esphome/core/helpers.cpp b/esphome/core/helpers.cpp index b5bf849c30..96b2d46d78 100644 --- a/esphome/core/helpers.cpp +++ b/esphome/core/helpers.cpp @@ -487,19 +487,26 @@ static constexpr const char *BASE64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" "0123456789+/"; -// Helper function to find the index of a base64 character in the lookup table. +// Helper function to find the index of a base64/base64url character in the lookup table. // Returns the character's position (0-63) if found, or 0 if not found. +// Supports both standard base64 (+/) and base64url (-_) alphabets. // NOTE: This returns 0 for both 'A' (valid base64 char at index 0) and invalid characters. // This is safe because is_base64() is ALWAYS checked before calling this function, // preventing invalid characters from ever reaching here. The base64_decode function // stops processing at the first invalid character due to the is_base64() check in its // while loop condition, making this edge case harmless in practice. static inline uint8_t base64_find_char(char c) { + // Handle base64url variants: '-' maps to '+' (index 62), '_' maps to '/' (index 63) + if (c == '-') + return 62; + if (c == '_') + return 63; const char *pos = strchr(BASE64_CHARS, c); return pos ? (pos - BASE64_CHARS) : 0; } -static inline bool is_base64(char c) { return (isalnum(c) || (c == '+') || (c == '/')); } +// Check if character is valid base64 or base64url +static inline bool is_base64(char c) { return (isalnum(c) || (c == '+') || (c == '/') || (c == '-') || (c == '_')); } std::string base64_encode(const std::vector &buf) { return base64_encode(buf.data(), buf.size()); }