Skip to content

Commit 4dc096c

Browse files
Crypto Algorithms (#189)
* LegacyCryptoAlgorithm *AesCbcCryptoAlgorithm * CryptoModule * Deprecated CipherKey and RIV and updated tests with Crypto * Newtonsoft.Json vulnerability fix * sub key validation for subscribe call * Update LICENSE
1 parent 05c4020 commit 4dc096c

File tree

74 files changed

+2601
-385
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

74 files changed

+2601
-385
lines changed

.github/workflows/run-tests.yml

+1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ jobs:
3333
2.1.519
3434
5.0.x
3535
6.0.x
36+
7.0.x
3637
- name: Build packages
3738
env:
3839
WORKSPACE_PATH: ${{ github.workspace }}

.gitignore

+9-1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,14 @@ src/.vs/Pubnub/v15/sqlite3/storage.ide
4848
/src/Api/PubnubApiUWP/obj/*
4949
/src/Api/PubnubApiUWP/*.user
5050

51+
/src/Api/PubnubApiUnity/bin/*
52+
/src/Api/PubnubApiUnity/bin/Debug/*
53+
/src/Api/PubnubApiUnity/obj/Debug/*
54+
/src/Api/PubnubApiUnity/bin/Release/*
55+
/src/Api/PubnubApiUnity/obj/Release/*
56+
/src/Api/PubnubApiUnity/obj/*
57+
/src/Api/PubnubApiUnity/*.user
58+
5159
/src/packages/*
5260

5361
/src/UnitTests/PubnubApi.Tests/bin/Debug/*
@@ -168,4 +176,4 @@ src/UnitTests/MockServer/obj/*
168176
##################
169177
.github/.release
170178

171-
.idea
179+
.idea

.pubnub.yml

+18-7
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,19 @@
11
name: c-sharp
2-
version: "6.18.0"
2+
version: "6.19.0"
33
schema: 1
44
scm: github.com/pubnub/c-sharp
55
changelog:
6+
- date: 2023-10-16
7+
version: v6.19.0
8+
changes:
9+
- type: feature
10+
text: "Add crypto module that allows configure SDK to encrypt and decrypt messages."
11+
- type: bug
12+
text: "Improved security of crypto implementation by adding enhanced AES-CBC cryptor."
13+
- type: bug
14+
text: "Fixes Newtonsoft Json vulnerability with MaxDepth and upgrade to version for non-PCL."
15+
- type: improvement
16+
text: "Add SubscribeKey validation for subscribe feature."
617
- date: 2023-09-04
718
version: v6.18.0
819
changes:
@@ -730,7 +741,7 @@ features:
730741
- QUERY-PARAM
731742
supported-platforms:
732743
-
733-
version: Pubnub 'C#' 6.18.0
744+
version: Pubnub 'C#' 6.19.0
734745
platforms:
735746
- Windows 10 and up
736747
- Windows Server 2008 and up
@@ -740,7 +751,7 @@ supported-platforms:
740751
- .Net Framework 4.5
741752
- .Net Framework 4.6.1+
742753
-
743-
version: PubnubPCL 'C#' 6.18.0
754+
version: PubnubPCL 'C#' 6.19.0
744755
platforms:
745756
- Xamarin.Android
746757
- Xamarin.iOS
@@ -760,7 +771,7 @@ supported-platforms:
760771
- .Net Core
761772
- .Net 6.0
762773
-
763-
version: PubnubUWP 'C#' 6.18.0
774+
version: PubnubUWP 'C#' 6.19.0
764775
platforms:
765776
- Windows Phone 10
766777
- Universal Windows Apps
@@ -784,7 +795,7 @@ sdks:
784795
distribution-type: source
785796
distribution-repository: GitHub
786797
package-name: Pubnub
787-
location: https://github.com/pubnub/c-sharp/releases/tag/v6.18.0.0
798+
location: https://github.com/pubnub/c-sharp/releases/tag/v6.19.0.0
788799
requires:
789800
-
790801
name: ".Net"
@@ -1067,7 +1078,7 @@ sdks:
10671078
distribution-type: source
10681079
distribution-repository: GitHub
10691080
package-name: PubNubPCL
1070-
location: https://github.com/pubnub/c-sharp/releases/tag/v6.18.0.0
1081+
location: https://github.com/pubnub/c-sharp/releases/tag/v6.19.0.0
10711082
requires:
10721083
-
10731084
name: ".Net Core"
@@ -1426,7 +1437,7 @@ sdks:
14261437
distribution-type: source
14271438
distribution-repository: GitHub
14281439
package-name: PubnubUWP
1429-
location: https://github.com/pubnub/c-sharp/releases/tag/v6.18.0.0
1440+
location: https://github.com/pubnub/c-sharp/releases/tag/v6.19.0.0
14301441
requires:
14311442
-
14321443
name: "Universal Windows Platform Development"

CHANGELOG

+9
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
v6.19.0 - October 16 2023
2+
-----------------------------
3+
- Added: add crypto module that allows configure SDK to encrypt and decrypt messages.
4+
5+
- Fixed: improved security of crypto implementation by adding enhanced AES-CBC cryptor.
6+
- Fixed: fixes Newtonsoft Json vulnerability with MaxDepth and upgrade to version for non-PCL.
7+
8+
- Modified: add SubscribeKey validation for subscribe feature.
9+
110
v6.18.0 - September 04 2023
211
-----------------------------
312
- Fixed: allow name param as optional in SetChannelMetadata. Removed default empty value.

LICENSE

+25-23
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,29 @@
1-
PubNub Real-time Cloud-Hosted Push API and Push Notification Client Frameworks
2-
Copyright (c) 2013 PubNub Inc.
3-
http://www.pubnub.com/
4-
http://www.pubnub.com/terms
1+
PubNub Software Development Kit License Agreement
2+
Copyright © 2023 PubNub Inc. All rights reserved.
53

6-
Permission is hereby granted, free of charge, to any person obtaining a copy
7-
of this software and associated documentation files (the "Software"), to deal
8-
in the Software without restriction, including without limitation the rights
9-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10-
copies of the Software, and to permit persons to whom the Software is
11-
furnished to do so, subject to the following conditions:
4+
Subject to the terms and conditions of the license, you are hereby granted
5+
a non-exclusive, worldwide, royalty-free license to (a) copy and modify
6+
the software in source code or binary form for use with the software services
7+
and interfaces provided by PubNub, and (b) redistribute unmodified copies
8+
of the software to third parties. The software may not be incorporated in
9+
or used to provide any product or service competitive with the products
10+
and services of PubNub.
1211

13-
The above copyright notice and this permission notice shall be included in
14-
all copies or substantial portions of the Software.
12+
The above copyright notice and this license shall be included
13+
in or with all copies or substantial portions of the software.
1514

16-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22-
THE SOFTWARE.
15+
This license does not grant you permission to use the trade names, trademarks,
16+
service marks, or product names of PubNub, except as required for reasonable
17+
and customary use in describing the origin of the software and reproducing
18+
the content of this license.
2319

24-
PubNub Real-time Cloud-Hosted Push API and Push Notification Client Frameworks
25-
Copyright (c) 2013 PubNub Inc.
26-
http://www.pubnub.com/
27-
http://www.pubnub.com/terms
20+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF
21+
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
23+
EVENT SHALL PUBNUB OR THE AUTHORS OR COPYRIGHT HOLDERS OF THE SOFTWARE BE
24+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
25+
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27+
28+
https://www.pubnub.com/
29+
https://www.pubnub.com/terms

src/Api/PubnubApi/Builder/UrlRequestBuilder.cs

+8-7
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,15 @@
66
using System.Globalization;
77
using System.Threading.Tasks;
88
using System.Threading;
9+
using PubnubApi.Security.Crypto.Common;
910
#if !NETSTANDARD10 && !NETSTANDARD11 && !NETSTANDARD12 && !WP81
1011
using System.Reflection;
1112
#endif
1213
#if !NET35 && !NET40
1314
using System.Collections.Concurrent;
1415
#endif
16+
using PubnubApi.Security.Crypto;
17+
using PubnubApi.Security.Crypto.Cryptors;
1518

1619
namespace PubnubApi
1720
{
@@ -2114,8 +2117,7 @@ private string GeneratePAMv2Signature(string queryStringToSign, string partialUr
21142117
string_to_sign.Append(partialUrl).Append('\n');
21152118
string_to_sign.Append(queryStringToSign);
21162119

2117-
PubnubCrypto pubnubCrypto = new PubnubCrypto((opType != PNOperationType.PNSignalOperation) ? pubnubConfig[pubnubInstanceId].CipherKey : "", pubnubConfig[pubnubInstanceId], this.pubnubLog, null);
2118-
signature = pubnubCrypto.PubnubAccessManagerSign(pubnubConfig[pubnubInstanceId].SecretKey, string_to_sign.ToString());
2120+
signature = Util.PubnubAccessManagerSign(pubnubConfig[pubnubInstanceId].SecretKey, string_to_sign.ToString());
21192121
if (this.pubnubLog != null && this.pubnubConfig != null)
21202122
{
21212123
LoggingMethod.WriteToLog(pubnubLog, "string_to_sign = " + string_to_sign, pubnubConfig[pubnubInstanceId].LogVerbosity);
@@ -2142,8 +2144,7 @@ private string GeneratePAMv3Signature(string method, string requestBody, string
21422144
string_to_sign.AppendFormat(CultureInfo.InvariantCulture, "{0}\n", queryStringToSign);
21432145
string_to_sign.Append(requestBody);
21442146

2145-
PubnubCrypto pubnubCrypto = new PubnubCrypto((opType != PNOperationType.PNSignalOperation) ? pubnubConfig[pubnubInstanceId].CipherKey : "", pubnubConfig[pubnubInstanceId], this.pubnubLog, null);
2146-
signature = pubnubCrypto.PubnubAccessManagerSign(pubnubConfig[pubnubInstanceId].SecretKey, string_to_sign.ToString());
2147+
signature = Util.PubnubAccessManagerSign(pubnubConfig[pubnubInstanceId].SecretKey, string_to_sign.ToString());
21472148
signature = string.Format(CultureInfo.InvariantCulture, "v2.{0}", signature.TrimEnd(new[] { '=' }));
21482149
if (this.pubnubLog != null && this.pubnubConfig != null)
21492150
{
@@ -2259,10 +2260,10 @@ private string JsonEncodePublishMsg(object originalMessage, PNOperationType opTy
22592260
{
22602261
string message = jsonLib.SerializeToJsonString(originalMessage);
22612262

2262-
if (pubnubConfig.ContainsKey(pubnubInstanceId) && pubnubConfig[pubnubInstanceId].CipherKey.Length > 0 && opType != PNOperationType.PNSignalOperation)
2263+
if (pubnubConfig.ContainsKey(pubnubInstanceId) && (pubnubConfig[pubnubInstanceId].CryptoModule != null || pubnubConfig[pubnubInstanceId].CipherKey.Length > 0) && opType != PNOperationType.PNSignalOperation)
22632264
{
2264-
PubnubCrypto aes = new PubnubCrypto(pubnubConfig[pubnubInstanceId].CipherKey, pubnubConfig[pubnubInstanceId], pubnubLog, null);
2265-
string encryptMessage = aes.Encrypt(message);
2265+
pubnubConfig[pubnubInstanceId].CryptoModule ??= new CryptoModule(new LegacyCryptor(pubnubConfig[pubnubInstanceId].CipherKey, pubnubConfig[pubnubInstanceId].UseRandomInitializationVector, pubnubLog), null);
2266+
string encryptMessage = pubnubConfig[pubnubInstanceId].CryptoModule.Encrypt(message);
22662267
message = jsonLib.SerializeToJsonString(encryptMessage);
22672268
}
22682269

src/Api/PubnubApi/EndPoint/Files/DownloadFileOperation.cs

+17-17
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
#if !NET35 && !NET40
1212
using System.Collections.Concurrent;
1313
#endif
14+
using PubnubApi.Security.Crypto;
15+
using PubnubApi.Security.Crypto.Cryptors;
1416

1517
namespace PubnubApi.EndPoint
1618
{
@@ -157,24 +159,23 @@ private void ProcessFileDownloadRequest(Dictionary<string, object> externalQuery
157159
if (item1Bytes != null)
158160
{
159161
byte[] outputBytes = null;
160-
string currentCipherKey = !string.IsNullOrEmpty(this.currentFileCipherKey) ? this.currentFileCipherKey : config.CipherKey;
161-
if (currentCipherKey.Length > 0)
162+
if (string.IsNullOrEmpty(this.currentFileCipherKey) && string.IsNullOrEmpty(config.CipherKey) && config.CryptoModule == null)
162163
{
164+
outputBytes = item1Bytes;
165+
}
166+
else
167+
{
168+
CryptoModule currentCryptoModule = !string.IsNullOrEmpty(this.currentFileCipherKey) ? new CryptoModule(new LegacyCryptor(this.currentFileCipherKey, true, pubnubLog), null) : (config.CryptoModule ??= new CryptoModule(new LegacyCryptor(config.CipherKey, true, pubnubLog), null));
163169
try
164170
{
165-
PubnubCrypto aes = new PubnubCrypto(currentCipherKey, config, pubnubLog, null);
166-
outputBytes = aes.Decrypt(item1Bytes, true);
171+
outputBytes = currentCryptoModule.Decrypt(item1Bytes);
167172
LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Stream length (after Decrypt)= {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), item1Bytes.Length), config.LogVerbosity);
168173
}
169174
catch (Exception ex)
170175
{
171176
System.Diagnostics.Debug.WriteLine(ex.ToString());
172177
}
173178
}
174-
else
175-
{
176-
outputBytes = item1Bytes;
177-
}
178179
PNDownloadFileResult result = new PNDownloadFileResult();
179180
result.FileBytes = outputBytes;
180181
result.FileName = currentFileName;
@@ -226,25 +227,24 @@ private async Task<PNResult<PNDownloadFileResult>> ProcessFileDownloadRequest(Di
226227
if (item1Bytes != null)
227228
{
228229
byte[] outputBytes = null;
229-
string currentCipherKey = !string.IsNullOrEmpty(this.currentFileCipherKey) ? this.currentFileCipherKey : config.CipherKey;
230-
if (currentCipherKey.Length > 0)
230+
if (string.IsNullOrEmpty(this.currentFileCipherKey) && string.IsNullOrEmpty(config.CipherKey) && config.CryptoModule == null)
231231
{
232+
outputBytes = item1Bytes;
233+
}
234+
else
235+
{
236+
CryptoModule currentCryptoModule = !string.IsNullOrEmpty(this.currentFileCipherKey) ? new CryptoModule(new LegacyCryptor(this.currentFileCipherKey, true, pubnubLog), null) : (config.CryptoModule ??= new CryptoModule(new LegacyCryptor(config.CipherKey, true, pubnubLog), null));
232237
try
233238
{
234-
PubnubCrypto aes = new PubnubCrypto(currentCipherKey, config, pubnubLog, null);
235-
outputBytes = aes.Decrypt(item1Bytes, true);
239+
outputBytes = currentCryptoModule.Decrypt(item1Bytes);
236240
LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Stream length (after Decrypt)= {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), item1Bytes.Length), config.LogVerbosity);
237241
}
238242
catch (Exception ex)
239243
{
240244
System.Diagnostics.Debug.WriteLine(ex.ToString());
241245
}
242246
}
243-
else
244-
{
245-
outputBytes = item1Bytes;
246-
}
247-
247+
248248
PNDownloadFileResult result = new PNDownloadFileResult();
249249
result.FileBytes = outputBytes;
250250
result.FileName = currentFileName;

src/Api/PubnubApi/EndPoint/Files/SendFileOperation.cs

+17-8
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
#if !NET35 && !NET40
1212
using System.Collections.Concurrent;
1313
#endif
14+
using PubnubApi.Security.Crypto;
15+
using PubnubApi.Security.Crypto.Cryptors;
1416

1517
namespace PubnubApi.EndPoint
1618
{
@@ -199,8 +201,12 @@ private void ProcessFileUpload(Dictionary<string, object> externalQueryParam, PN
199201

200202
string dataBoundary = String.Format(CultureInfo.InvariantCulture, "----------{0:N}", Guid.NewGuid());
201203
string contentType = "multipart/form-data; boundary=" + dataBoundary;
202-
string currentCipherKey = !string.IsNullOrEmpty(this.currentFileCipherKey) ? this.currentFileCipherKey : config.CipherKey;
203-
byte[] postData = GetMultipartFormData(sendFileByteArray,generateFileUploadUrlResult.FileName, generateFileUploadUrlResult.FileUploadRequest.FormFields, dataBoundary, currentCipherKey, config, pubnubLog);
204+
CryptoModule currentCryptoModule = null;
205+
if (!string.IsNullOrEmpty(this.currentFileCipherKey) || !string.IsNullOrEmpty(config.CipherKey) || config.CryptoModule != null)
206+
{
207+
currentCryptoModule = !string.IsNullOrEmpty(this.currentFileCipherKey) ? new CryptoModule(new LegacyCryptor(this.currentFileCipherKey, true, pubnubLog), null) : (config.CryptoModule ??= new CryptoModule(new LegacyCryptor(config.CipherKey, true, pubnubLog), null));
208+
}
209+
byte[] postData = GetMultipartFormData(sendFileByteArray,generateFileUploadUrlResult.FileName, generateFileUploadUrlResult.FileUploadRequest.FormFields, dataBoundary, currentCryptoModule, config, pubnubLog);
204210

205211
string json;
206212
UrlProcessRequest(new Uri(generateFileUploadUrlResult.FileUploadRequest.Url), requestState, false, postData, contentType).ContinueWith(r =>
@@ -300,8 +306,12 @@ private async Task<PNResult<PNFileUploadResult>> ProcessFileUpload(Dictionary<st
300306

301307
string dataBoundary = String.Format(CultureInfo.InvariantCulture, "----------{0:N}", Guid.NewGuid());
302308
string contentType = "multipart/form-data; boundary=" + dataBoundary;
303-
string currentCipherKey = !string.IsNullOrEmpty(this.currentFileCipherKey) ? this.currentFileCipherKey : config.CipherKey;
304-
byte[] postData = GetMultipartFormData(sendFileByteArray, generateFileUploadUrlResult.FileName, generateFileUploadUrlResult.FileUploadRequest.FormFields, dataBoundary, currentCipherKey, config, pubnubLog);
309+
CryptoModule currentCryptoModule = null;
310+
if (!string.IsNullOrEmpty(this.currentFileCipherKey) || !string.IsNullOrEmpty(config.CipherKey) || config.CryptoModule != null)
311+
{
312+
currentCryptoModule = !string.IsNullOrEmpty(this.currentFileCipherKey) ? new CryptoModule(new LegacyCryptor(this.currentFileCipherKey, true, pubnubLog), null) : (config.CryptoModule ??= new CryptoModule(new LegacyCryptor(config.CipherKey, true, pubnubLog), null));
313+
}
314+
byte[] postData = GetMultipartFormData(sendFileByteArray, generateFileUploadUrlResult.FileName, generateFileUploadUrlResult.FileUploadRequest.FormFields, dataBoundary, currentCryptoModule, config, pubnubLog);
305315

306316
Tuple<string, PNStatus> JsonAndStatusTuple = await UrlProcessRequest(new Uri(generateFileUploadUrlResult.FileUploadRequest.Url), requestState, false, postData, contentType).ConfigureAwait(false);
307317
ret.Status = JsonAndStatusTuple.Item2;
@@ -469,7 +479,7 @@ private static byte[] GetByteArrayFromFilePath(string filePath)
469479

470480
}
471481

472-
private static byte[] GetMultipartFormData(byte[] sendFileByteArray, string fileName, Dictionary<string, object> formFields, string dataBoundary, string currentCipherKey, PNConfiguration config, IPubnubLog pubnubLog)
482+
private static byte[] GetMultipartFormData(byte[] sendFileByteArray, string fileName, Dictionary<string, object> formFields, string dataBoundary, CryptoModule currentCryptoModule, PNConfiguration config, IPubnubLog pubnubLog)
473483
{
474484
byte[] ret = null;
475485
string fileContentType = "application/octet-stream";
@@ -500,12 +510,11 @@ private static byte[] GetMultipartFormData(byte[] sendFileByteArray, string file
500510
byte[] postHeaderData = Encoding.UTF8.GetBytes(header);
501511

502512
dataStream.Write(postHeaderData, 0, postHeaderData.Length);
503-
if (currentCipherKey.Length > 0)
513+
if (currentCryptoModule != null)
504514
{
505515
try
506516
{
507-
PubnubCrypto aes = new PubnubCrypto(currentCipherKey, config, pubnubLog, null);
508-
byte[] encryptBytes = aes.Encrypt(sendFileByteArray, true);
517+
byte[] encryptBytes = currentCryptoModule.Encrypt(sendFileByteArray);
509518
dataStream.Write(encryptBytes, 0, encryptBytes.Length);
510519
}
511520
catch (Exception ex)

0 commit comments

Comments
 (0)