Skip to content

Commit 0eaed65

Browse files
authored
Make SDK V4 preview version trimmable (#69)
1 parent 311c09f commit 0eaed65

File tree

6 files changed

+153
-62
lines changed

6 files changed

+153
-62
lines changed
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"Projects": [
3+
{
4+
"Name": "Amazon.Extensions.S3.Encryption",
5+
"Type": "Patch",
6+
"ChangelogMessages": [
7+
"Mark the assembly trimmable",
8+
"Enable Source Link"
9+
]
10+
}
11+
]
12+
}

src/Amazon.Extensions.S3.Encryption.csproj

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,17 @@
1919
<AssemblyOriginatorKeyFile>..\public.snk</AssemblyOriginatorKeyFile>
2020
<PackageReadmeFile>README.md</PackageReadmeFile>
2121
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
22+
23+
<EmbedUntrackedSources>true</EmbedUntrackedSources>
24+
<PublishRepositoryUrl>true</PublishRepositoryUrl>
25+
<IncludeSymbols>true</IncludeSymbols>
26+
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
27+
</PropertyGroup>
28+
29+
<PropertyGroup Condition="'$(TargetFramework)' == 'net8.0'">
30+
<IsTrimmable>true</IsTrimmable>
2231
</PropertyGroup>
23-
32+
2433
<PropertyGroup Condition="'$(TargetFramework)' == 'net472'">
2534
<AssemblyVersion>3.0.0</AssemblyVersion>
2635
</PropertyGroup>
@@ -36,6 +45,7 @@
3645
<PackageReference Include="AWSSDK.S3" Version="4.0.0-preview.4" />
3746
<PackageReference Include="AWSSDK.KeyManagementService" Version="4.0.0-preview.4" />
3847
<PackageReference Include="BouncyCastle.Cryptography" Version="2.4.0" />
48+
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="8.0.0" PrivateAssets="All" />
3949
</ItemGroup>
4050

4151
<!-- TODO: The dependency on Microsoft.Bcl.AsyncInterfaces should be removed once the issue causing it to be needed in the .NET SDK is fixed -->

src/EncryptionUtils.cs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,9 @@
1919
using Amazon.S3.Model;
2020
using Amazon.Runtime.Internal.Util;
2121
using Amazon.Runtime;
22-
using ThirdParty.Json.LitJson;
2322
using System.Collections.Generic;
2423
using System.Globalization;
2524
using Amazon.KeyManagementService;
26-
using Amazon.Runtime.SharedInterfaces;
2725
using Amazon.Extensions.S3.Encryption.Util;
2826
using Amazon.KeyManagementService.Model;
2927

@@ -459,13 +457,13 @@ internal static EncryptionInstructions BuildInstructionsUsingInstructionFile(Get
459457
{
460458
using (TextReader textReader = new StreamReader(response.ResponseStream))
461459
{
462-
JsonData jsonData = JsonMapper.ToObject(textReader);
460+
var keyValuePairs = JsonUtils.ToDictionary(textReader.ReadToEnd());
463461

464-
var base64EncodedEncryptedEnvelopeKey = jsonData["EncryptedEnvelopeKey"];
462+
var base64EncodedEncryptedEnvelopeKey = keyValuePairs["EncryptedEnvelopeKey"];
465463
byte[] encryptedEnvelopeKey = Convert.FromBase64String((string)base64EncodedEncryptedEnvelopeKey);
466464
byte[] decryptedEnvelopeKey = decryptNonKmsEnvelopeKey(encryptedEnvelopeKey, materials);
467465

468-
var base64EncodedIV = jsonData["IV"];
466+
var base64EncodedIV = keyValuePairs["IV"];
469467
byte[] IV = Convert.FromBase64String((string)base64EncodedIV);
470468

471469
return new EncryptionInstructions(materials.MaterialsDescription, decryptedEnvelopeKey, IV);
@@ -532,7 +530,7 @@ internal static void UpdateMetadataWithEncryptionInstructions(AmazonWebServiceRe
532530
}
533531

534532
metadata.Add(XAmzIV, base64EncodedIV);
535-
metadata.Add(XAmzMatDesc, JsonMapper.ToJson(instructions.MaterialsDescription));
533+
metadata.Add(XAmzMatDesc, JsonUtils.ToJson(instructions.MaterialsDescription));
536534
}
537535
}
538536

@@ -544,11 +542,13 @@ internal static PutObjectRequest CreateInstructionFileRequest(AmazonWebServiceRe
544542
byte[] IVToStoreInInstructionFile = instructions.InitializationVector;
545543
string base64EncodedIV = Convert.ToBase64String(IVToStoreInInstructionFile);
546544

547-
JsonData jsonData = new JsonData();
548-
jsonData["EncryptedEnvelopeKey"] = base64EncodedEnvelopeKey;
549-
jsonData["IV"] = base64EncodedIV;
545+
var keyValuePairs = new Dictionary<string, string>
546+
{
547+
{"EncryptedEnvelopeKey", base64EncodedEnvelopeKey },
548+
{"IV", base64EncodedIV }
549+
};
550550

551-
var contentBody = jsonData.ToJson();
551+
var contentBody = JsonUtils.ToJson(keyValuePairs);
552552

553553
var putObjectRequest = request as PutObjectRequest;
554554
if (putObjectRequest != null)

src/EncryptionUtilsV2.cs

Lines changed: 31 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
using Amazon.KeyManagementService.Model;
2626
using Amazon.Runtime;
2727
using Amazon.S3.Model;
28-
using ThirdParty.Json.LitJson;
2928

3029
namespace Amazon.Extensions.S3.Encryption
3130
{
@@ -276,7 +275,7 @@ internal static void UpdateMetadataWithEncryptionInstructionsV2(AmazonWebService
276275
metadata.Add(XAmzKeyV2, base64EncodedEnvelopeKey);
277276
metadata.Add(XAmzCekAlg, instructions.CekAlgorithm);
278277
metadata.Add(XAmzIV, base64EncodedIv);
279-
metadata.Add(XAmzMatDesc, JsonMapper.ToJson(instructions.MaterialsDescription));
278+
metadata.Add(XAmzMatDesc, JsonUtils.ToJson(instructions.MaterialsDescription));
280279
}
281280
}
282281

@@ -288,17 +287,17 @@ internal static PutObjectRequest CreateInstructionFileRequestV2(AmazonWebService
288287
var ivToStoreInInstructionFile = instructions.InitializationVector;
289288
var base64EncodedIv = Convert.ToBase64String(ivToStoreInInstructionFile);
290289

291-
var jsonData = new JsonData
290+
var keyValuePairs = new Dictionary<string, string>()
292291
{
293-
[XAmzTagLen] = DefaultTagBitsLength.ToString(),
294-
[XAmzKeyV2] = base64EncodedEnvelopeKey,
295-
[XAmzCekAlg] = instructions.CekAlgorithm,
296-
[XAmzWrapAlg] = instructions.WrapAlgorithm,
297-
[XAmzIV] = base64EncodedIv,
298-
[XAmzMatDesc] = JsonMapper.ToJson(instructions.MaterialsDescription)
292+
{XAmzTagLen, DefaultTagBitsLength.ToString()},
293+
{XAmzKeyV2, base64EncodedEnvelopeKey},
294+
{XAmzCekAlg, instructions.CekAlgorithm},
295+
{XAmzWrapAlg, instructions.WrapAlgorithm},
296+
{XAmzIV, base64EncodedIv},
297+
{XAmzMatDesc, JsonUtils.ToJson(instructions.MaterialsDescription)},
299298
};
300299

301-
var contentBody = jsonData.ToJson();
300+
var contentBody = JsonUtils.ToJson(keyValuePairs);
302301

303302
var putObjectRequest = request as PutObjectRequest;
304303
if (putObjectRequest != null)
@@ -451,7 +450,7 @@ internal static Dictionary<string, string> GetMaterialDescriptionFromMetaData(Me
451450
return new Dictionary<string, string>();
452451
}
453452

454-
var materialDescription = JsonMapper.ToObject<Dictionary<string, string>>(materialDescriptionJsonString);
453+
var materialDescription = JsonUtils.ToDictionary(materialDescriptionJsonString);
455454
return materialDescription;
456455
}
457456

@@ -492,45 +491,45 @@ internal static EncryptionInstructions BuildInstructionsUsingInstructionFileV2(G
492491
{
493492
using (TextReader textReader = new StreamReader(response.ResponseStream))
494493
{
495-
var jsonData = JsonMapper.ToObject(textReader);
494+
var keyValuePair = JsonUtils.ToDictionary(textReader.ReadToEnd());
496495

497-
if (jsonData[XAmzKeyV2] != null)
496+
if (keyValuePair.ContainsKey(XAmzKeyV2))
498497
{
499498
// The envelope contains data in V2 format
500-
var encryptedEnvelopeKey = Base64DecodedDataValue(jsonData, XAmzKeyV2);
499+
var encryptedEnvelopeKey = Base64DecodedDataValue(keyValuePair, XAmzKeyV2);
501500
var decryptedEnvelopeKey = DecryptNonKmsEnvelopeKeyV2(encryptedEnvelopeKey, materials);
502501

503-
var initializationVector = Base64DecodedDataValue(jsonData, XAmzIV);
504-
var materialDescription = JsonMapper.ToObject<Dictionary<string, string>>((string)jsonData[XAmzMatDesc]);
502+
var initializationVector = Base64DecodedDataValue(keyValuePair, XAmzIV);
503+
var materialDescription = JsonUtils.ToDictionary((string)keyValuePair[XAmzMatDesc]);
505504

506-
var cekAlgorithm = StringValue(jsonData, XAmzCekAlg);
507-
var wrapAlgorithm = StringValue(jsonData, XAmzWrapAlg);
505+
var cekAlgorithm = StringValue(keyValuePair, XAmzCekAlg);
506+
var wrapAlgorithm = StringValue(keyValuePair, XAmzWrapAlg);
508507

509508
var instructions = new EncryptionInstructions(materialDescription, decryptedEnvelopeKey, null,
510509
initializationVector, wrapAlgorithm, cekAlgorithm);
511510

512511
return instructions;
513512
}
514-
else if (jsonData[XAmzKey] != null)
513+
else if (keyValuePair.ContainsKey(XAmzKey))
515514
{
516515
// The envelope contains data in V1 format
517-
var encryptedEnvelopeKey = Base64DecodedDataValue(jsonData, XAmzKey);
516+
var encryptedEnvelopeKey = Base64DecodedDataValue(keyValuePair, XAmzKey);
518517
var decryptedEnvelopeKey = DecryptNonKMSEnvelopeKey(encryptedEnvelopeKey, materials);
519518

520-
var initializationVector = Base64DecodedDataValue(jsonData, XAmzIV);
521-
var materialDescription = JsonMapper.ToObject<Dictionary<string, string>>((string)jsonData[XAmzMatDesc]);
519+
var initializationVector = Base64DecodedDataValue(keyValuePair, XAmzIV);
520+
var materialDescription = JsonUtils.ToDictionary((string)keyValuePair[XAmzMatDesc]);
522521

523522
var instructions = new EncryptionInstructions(materialDescription, decryptedEnvelopeKey, null, initializationVector);
524523

525524
return instructions;
526525
}
527-
else if (jsonData[EncryptedEnvelopeKey] != null)
526+
else if (keyValuePair.ContainsKey(EncryptedEnvelopeKey))
528527
{
529528
// The envelope contains data in older format
530-
var encryptedEnvelopeKey = Base64DecodedDataValue(jsonData, EncryptedEnvelopeKey);
529+
var encryptedEnvelopeKey = Base64DecodedDataValue(keyValuePair, EncryptedEnvelopeKey);
531530
var decryptedEnvelopeKey = DecryptNonKMSEnvelopeKey(encryptedEnvelopeKey, materials);
532531

533-
var initializationVector = Base64DecodedDataValue(jsonData, IV);
532+
var initializationVector = Base64DecodedDataValue(keyValuePair, IV);
534533

535534
return new EncryptionInstructions(materials.MaterialsDescription, decryptedEnvelopeKey, initializationVector);
536535
}
@@ -541,24 +540,24 @@ internal static EncryptionInstructions BuildInstructionsUsingInstructionFileV2(G
541540
}
542541
}
543542

544-
private static byte[] Base64DecodedDataValue(JsonData jsonData, string key)
543+
private static byte[] Base64DecodedDataValue(Dictionary<string, string> keyValuePairs, string key)
545544
{
546-
var base64EncodedValue = jsonData[key];
547-
if (base64EncodedValue == null)
545+
if (!keyValuePairs.TryGetValue(key, out var base64EncodedValue))
548546
{
549547
throw new ArgumentNullException(nameof(key));
550548
}
549+
551550
return Convert.FromBase64String((string)base64EncodedValue);
552551
}
553552

554-
private static string StringValue(JsonData jsonData, string key)
553+
private static string StringValue(Dictionary<string, string> keyValuePairs, string key)
555554
{
556-
var stringValue = jsonData[key];
557-
if (stringValue == null)
555+
if (!keyValuePairs.TryGetValue(key, out var stringValue))
558556
{
559557
throw new ArgumentNullException(nameof(key));
560558
}
561-
return (string)stringValue;
559+
560+
return stringValue;
562561
}
563562
}
564563
}

src/Internal/SetupDecryptionHandlerV1.cs

Lines changed: 6 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,12 @@
1313
* permissions and limitations under the License.
1414
*/
1515

16-
using System;
1716
using System.Collections.Generic;
18-
using Amazon.Runtime;
19-
using Amazon.S3.Model;
2017
using System.IO;
18+
using Amazon.S3;
19+
using Amazon.S3.Model;
2120
using Amazon.KeyManagementService.Model;
2221
using Amazon.Runtime.Internal.Util;
23-
using Amazon.S3;
24-
using ThirdParty.Json.LitJson;
2522
using Amazon.Extensions.S3.Encryption.Util;
2623

2724
namespace Amazon.Extensions.S3.Encryption.Internal
@@ -55,27 +52,17 @@ private static string GetKmsKeyIdFromMetadata(MetadataCollection metadata)
5552
}
5653
else
5754
{
58-
JsonData materialDescriptionJsonData;
55+
Dictionary<string,string> materialDescriptionJsonData;
5956
try
6057
{
61-
materialDescriptionJsonData = JsonMapper.ToObject(materialDescriptionJsonString);
58+
materialDescriptionJsonData = JsonUtils.ToDictionary(materialDescriptionJsonString);
6259
}
63-
catch (JsonException e)
60+
catch (InvalidDataException e)
6461
{
6562
throw new InvalidDataException($"{KMSKeyIDMetadataMessage} The key '{EncryptionUtils.XAmzMatDesc}' does not contain valid JSON.", e);
6663
}
6764

68-
JsonData kmsKeyIDJsonData;
69-
try
70-
{
71-
kmsKeyIDJsonData = materialDescriptionJsonData[EncryptionUtils.KMSCmkIDKey];
72-
}
73-
catch (JsonException e)
74-
{
75-
throw new InvalidDataException($"{KMSKeyIDMetadataMessage} The key '{EncryptionUtils.KMSCmkIDKey}' is does not contain valid JSON.", e);
76-
}
77-
78-
if (kmsKeyIDJsonData == null)
65+
if (!materialDescriptionJsonData.TryGetValue(EncryptionUtils.KMSCmkIDKey, out var kmsKeyIDJsonData))
7966
{
8067
throw new InvalidDataException($"{KMSKeyIDMetadataMessage} The key '{kmsKeyIDJsonData}' is missing from the material description.");
8168
}

src/Util/JsonUtils.cs

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://aws.amazon.com/apache2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
using System;
16+
using System.Collections.Generic;
17+
using System.IO;
18+
using System.Text;
19+
using System.Text.Json;
20+
21+
namespace Amazon.Extensions.S3.Encryption.Util
22+
{
23+
internal static class JsonUtils
24+
{
25+
26+
internal static string ToJson(Dictionary<string, string> keyValuePairs)
27+
{
28+
var stream = new MemoryStream();
29+
using (var writer = new Utf8JsonWriter(stream))
30+
{
31+
writer.WriteStartObject();
32+
foreach (var kvp in keyValuePairs)
33+
{
34+
writer.WriteString(kvp.Key, kvp.Value);
35+
}
36+
writer.WriteEndObject();
37+
}
38+
39+
stream.Position = 0;
40+
return new StreamReader(stream).ReadToEnd();
41+
}
42+
43+
internal static Dictionary<string,string> ToDictionary(string json)
44+
{
45+
var dictionary = new Dictionary<string,string>();
46+
byte[] bytes = Encoding.UTF8.GetBytes(json);
47+
var reader = new Utf8JsonReader(new ReadOnlySpan<byte>(bytes));
48+
49+
reader.Read();
50+
if (reader.TokenType != JsonTokenType.StartObject)
51+
throw new InvalidDataException("Key value pair JSON must start with an object.");
52+
53+
// Read to the first property
54+
reader.Read();
55+
56+
while(reader.TokenType != JsonTokenType.EndObject)
57+
{
58+
if (reader.TokenType != JsonTokenType.PropertyName)
59+
throw new InvalidDataException("Key value pair JSON missing property name.");
60+
61+
var key = reader.GetString();
62+
63+
reader.Read();
64+
if (reader.TokenType != JsonTokenType.String)
65+
throw new InvalidDataException("Key value pair JSON must only have string values.");
66+
67+
var value = reader.GetString();
68+
69+
// To make the existence checks easier in this library don't include null values.
70+
// That way rest of the library just needs to do ContainsKey check.
71+
if (value != null)
72+
{
73+
dictionary[key] = value;
74+
}
75+
76+
// Move to the next property or end of object
77+
reader.Read();
78+
}
79+
80+
return dictionary;
81+
}
82+
}
83+
}

0 commit comments

Comments
 (0)