From 26e90c6688ab6ab97c4b8221018402a02e6343cd Mon Sep 17 00:00:00 2001 From: CastagnaIT Date: Sun, 25 Aug 2024 10:14:35 +0200 Subject: [PATCH 1/3] [ClearKey] Fix base64 encoding/decoding --- .../ClearKeyCencSingleSampleDecrypter.cpp | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/decrypters/clearkey/ClearKeyCencSingleSampleDecrypter.cpp b/src/decrypters/clearkey/ClearKeyCencSingleSampleDecrypter.cpp index f3f96f87a..14cc94756 100644 --- a/src/decrypters/clearkey/ClearKeyCencSingleSampleDecrypter.cpp +++ b/src/decrypters/clearkey/ClearKeyCencSingleSampleDecrypter.cpp @@ -25,6 +25,21 @@ using namespace UTILS; +namespace +{ +void CkB64Encode(std::string& str) +{ + STRING::ReplaceAll(str, "+", "-"); + STRING::ReplaceAll(str, "/", "_"); +} + +void CkB64Decode(std::string& str) +{ + STRING::ReplaceAll(str, "-", "+"); + STRING::ReplaceAll(str, "_", "/"); +} +} + CClearKeyCencSingleSampleDecrypter::CClearKeyCencSingleSampleDecrypter( std::string_view licenseUrl, const std::map& licenseHeaders, @@ -177,6 +192,7 @@ std::string CClearKeyCencSingleSampleDecrypter::CreateLicenseRequest( */ std::string b64Kid = UTILS::BASE64::Encode(defaultKeyId, false); + CkB64Encode(b64Kid); rapidjson::Document jDoc; jDoc.SetObject(); @@ -253,8 +269,8 @@ bool CClearKeyCencSingleSampleDecrypter::ParseLicenseResponse(std::string data) if (!b64Key.empty() && !b64KeyId.empty()) { - UTILS::STRING::ReplaceAll(b64Key, "-", "+"); - UTILS::STRING::ReplaceAll(b64KeyId, "-", "+"); + CkB64Decode(b64Key); + CkB64Decode(b64KeyId); // pad b64 int left = 4 - (b64Key.length() % 4); From e02150633628e0bec3d9aad0dcb592c9ebd46634 Mon Sep 17 00:00:00 2001 From: CastagnaIT Date: Sun, 25 Aug 2024 10:43:20 +0200 Subject: [PATCH 2/3] [ClearKey] Moved padding method to BASE64 utils --- .../ClearKeyCencSingleSampleDecrypter.cpp | 22 +++---------------- src/utils/Base64Utils.cpp | 14 ++++++++++++ src/utils/Base64Utils.h | 2 ++ 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/decrypters/clearkey/ClearKeyCencSingleSampleDecrypter.cpp b/src/decrypters/clearkey/ClearKeyCencSingleSampleDecrypter.cpp index 14cc94756..a6b63a357 100644 --- a/src/decrypters/clearkey/ClearKeyCencSingleSampleDecrypter.cpp +++ b/src/decrypters/clearkey/ClearKeyCencSingleSampleDecrypter.cpp @@ -270,26 +270,10 @@ bool CClearKeyCencSingleSampleDecrypter::ParseLicenseResponse(std::string data) if (!b64Key.empty() && !b64KeyId.empty()) { CkB64Decode(b64Key); - CkB64Decode(b64KeyId); + BASE64::AddPadding(b64Key); - // pad b64 - int left = 4 - (b64Key.length() % 4); - if (b64Key.length() % 4) - { - for (int i = 0; i < left; i++) - { - b64Key.push_back('='); - } - } - - left = 4 - (b64KeyId.length() % 4); - if (b64KeyId.length() % 4) - { - for (int i = 0; i < left; i++) - { - b64KeyId.push_back('='); - } - } + CkB64Decode(b64KeyId); + BASE64::AddPadding(b64KeyId); m_keyPairs.emplace(b64KeyId, b64Key); break; diff --git a/src/utils/Base64Utils.cpp b/src/utils/Base64Utils.cpp index ca0a2db0f..6a07d5b40 100644 --- a/src/utils/Base64Utils.cpp +++ b/src/utils/Base64Utils.cpp @@ -217,3 +217,17 @@ bool UTILS::BASE64::IsValidBase64(const std::string& input) std::regex base64Regex(REGEX.data()); return std::regex_match(input, base64Regex); } + +bool UTILS::BASE64::AddPadding(std::string& base64str) +{ + const int mod = static_cast(base64str.length() % 4); + if (mod > 0) + { + for (int i = 4 - mod; i > 0; --i) + { + base64str.push_back(PADDING); + } + return true; + } + return false; +} diff --git a/src/utils/Base64Utils.h b/src/utils/Base64Utils.h index c4fc602f6..d155ff9d7 100644 --- a/src/utils/Base64Utils.h +++ b/src/utils/Base64Utils.h @@ -30,5 +30,7 @@ std::string DecodeToStr(std::string_view input); bool IsValidBase64(const std::string& input); +bool AddPadding(std::string& base64str); + } // namespace BASE64 } // namespace UTILS From 2001365f2b24aa53bd20ccaf464c97f48b5cbeaf Mon Sep 17 00:00:00 2001 From: CastagnaIT Date: Sun, 25 Aug 2024 10:52:53 +0200 Subject: [PATCH 3/3] [ClearKey][cleanup] Removed unneeded namespace --- .../clearkey/ClearKeyCencSingleSampleDecrypter.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/decrypters/clearkey/ClearKeyCencSingleSampleDecrypter.cpp b/src/decrypters/clearkey/ClearKeyCencSingleSampleDecrypter.cpp index a6b63a357..bb31e8dde 100644 --- a/src/decrypters/clearkey/ClearKeyCencSingleSampleDecrypter.cpp +++ b/src/decrypters/clearkey/ClearKeyCencSingleSampleDecrypter.cpp @@ -94,7 +94,7 @@ CClearKeyCencSingleSampleDecrypter::CClearKeyCencSingleSampleDecrypter( return; } - const std::string b64DefaultKeyId = UTILS::BASE64::Encode(defaultKeyId); + const std::string b64DefaultKeyId = BASE64::Encode(defaultKeyId); if (!STRING::KeyExists(m_keyPairs, b64DefaultKeyId)) { LOG::LogF(LOGERROR, "Key not found on license server response"); @@ -127,10 +127,10 @@ CClearKeyCencSingleSampleDecrypter::CClearKeyCencSingleSampleDecrypter( } else // Key provided in Kodi props { - const std::string hexDefKid = UTILS::STRING::ToHexadecimal(defaultKeyId); + const std::string hexDefKid = STRING::ToHexadecimal(defaultKeyId); if (STRING::KeyExists(keys, hexDefKid)) - UTILS::STRING::ToHexBytes(keys.at(hexDefKid), hexKey); + STRING::ToHexBytes(keys.at(hexDefKid), hexKey); else LOG::LogF(LOGERROR, "Missing KeyId \"%s\" on DRM configuration", defaultKeyId.data()); } @@ -191,7 +191,7 @@ std::string CClearKeyCencSingleSampleDecrypter::CreateLicenseRequest( * "type":"temporary" } */ - std::string b64Kid = UTILS::BASE64::Encode(defaultKeyId, false); + std::string b64Kid = BASE64::Encode(defaultKeyId, false); CkB64Encode(b64Kid); rapidjson::Document jDoc;