Remove System.Linq dependency from System.Security.Cryptography.Encoding (dotnet...
authorStephen Toub <stoub@microsoft.com>
Mon, 7 Oct 2019 15:49:18 +0000 (11:49 -0400)
committerGitHub <noreply@github.com>
Mon, 7 Oct 2019 15:49:18 +0000 (11:49 -0400)
* Remove System.Linq dependency from System.Security.Cryptography.Encoding

* Address PR feedback

Commit migrated from https://github.com/dotnet/corefx/commit/2f40d22fddf3e08187a95454958bd42a37ef7ad0

src/libraries/System.Security.Cryptography.Encoding/src/Internal/Cryptography/OidLookup.OSX.cs
src/libraries/System.Security.Cryptography.Encoding/src/Internal/Cryptography/OidLookup.cs
src/libraries/System.Security.Cryptography.Encoding/src/System.Security.Cryptography.Encoding.csproj

index b7aa4c2..b56b1ca 100644 (file)
@@ -4,7 +4,7 @@
 
 using System;
 using System.Collections.Generic;
-using System.Linq;
+using System.Diagnostics;
 using System.Security.Cryptography;
 
 namespace Internal.Cryptography
@@ -44,6 +44,9 @@ namespace Internal.Cryptography
         // ---- PAL layer ends here ----
         // -----------------------------
 
+        /// <summary>Expected size of <see cref="s_extraFriendlyNameToOid"/>.</summary>
+        private const int ExtraFriendlyNameToOidCount = 8;
+
         // There are places inside the framework where Oid.FromFriendlyName is called
         // (to pass in an OID group restriction for Windows) and an exception is not tolerated.
         //
@@ -53,7 +56,7 @@ namespace Internal.Cryptography
         // and OpenSSL produce different answers.  Since the answers originally came from OpenSSL
         // on macOS, this preserves the OpenSSL names.
         private static readonly Dictionary<string, string> s_extraFriendlyNameToOid =
-            new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
+            new Dictionary<string, string>(ExtraFriendlyNameToOidCount, StringComparer.OrdinalIgnoreCase)
             {
                 { "pkcs7-data", "1.2.840.113549.1.7.1" },
                 { "contentType", "1.2.840.113549.1.9.3" },
@@ -66,6 +69,17 @@ namespace Internal.Cryptography
             };
 
         private static readonly Dictionary<string, string> s_extraOidToFriendlyName =
-            s_extraFriendlyNameToOid.ToDictionary(kvp => kvp.Value, kvp => kvp.Key);
+            InvertWithDefaultComparer(s_extraFriendlyNameToOid);
+
+#if DEBUG
+        static partial void ExtraStaticDebugValidation()
+        {
+            // Validate we hardcoded the right dictionary size
+            Debug.Assert(s_extraFriendlyNameToOid.Count == ExtraFriendlyNameToOidCount,
+                $"Expected {nameof(s_extraFriendlyNameToOid)}.{nameof(s_extraFriendlyNameToOid.Count)} == {ExtraFriendlyNameToOidCount}, got {s_extraFriendlyNameToOid.Count}");
+            Debug.Assert(s_extraOidToFriendlyName.Count == ExtraFriendlyNameToOidCount,
+                $"Expected {nameof(s_extraOidToFriendlyName)}.{nameof(s_extraOidToFriendlyName.Count)} == {ExtraFriendlyNameToOidCount}, got {s_extraOidToFriendlyName.Count}");
+        }
+#endif
     }
 }
index eeb0121..1bcc75a 100644 (file)
@@ -3,9 +3,9 @@
 // See the LICENSE file in the project root for more information.
 
 using System;
-using System.Linq;
 using System.Collections.Concurrent;
 using System.Collections.Generic;
+using System.Diagnostics;
 using System.Security.Cryptography;
 
 namespace Internal.Cryptography
@@ -93,6 +93,9 @@ namespace Internal.Cryptography
             return mappedOid;
         }
 
+        /// <summary>Expected size of <see cref="s_friendlyNameToOid"/>.</summary>
+        private const int FriendlyNameToOidCount = 103;
+
         // This table was originally built by extracting every szOID #define out of wincrypt.h,
         // and running them through new Oid(string) on Windows 10.  Then, take the list of everything
         // which produced a FriendlyName value, and run it through two other languages. If all 3 agree
@@ -108,7 +111,7 @@ namespace Internal.Cryptography
         // is to prevent issues wherein an identifier is different between CoreFX\Windows and CoreFX\Unix;
         // since any existing code would be using the Windows identifier, it is the de facto standard.
         private static readonly Dictionary<string, string> s_friendlyNameToOid =
-            new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
+            new Dictionary<string, string>(FriendlyNameToOidCount, StringComparer.OrdinalIgnoreCase)
             {
                 { "3des", "1.2.840.113549.3.7" },
                 { "aes128", "2.16.840.1.101.3.4.1.2" },
@@ -216,7 +219,7 @@ namespace Internal.Cryptography
             };
 
         private static readonly Dictionary<string, string> s_oidToFriendlyName =
-            s_friendlyNameToOid.ToDictionary(kvp => kvp.Value, kvp => kvp.Key);
+            InvertWithDefaultComparer(s_friendlyNameToOid);
 
         private static readonly Dictionary<string, string> s_compatOids =
             new Dictionary<string, string>
@@ -233,5 +236,30 @@ namespace Internal.Cryptography
                 { "1.3.14.3.2.4", "md4RSA" },
                 { "1.3.14.7.2.3.1", "md2RSA" },
             };
+
+        private static Dictionary<string, string> InvertWithDefaultComparer(Dictionary<string, string> source)
+        {
+            var result = new Dictionary<string, string>(source.Count);
+            foreach (KeyValuePair<string, string> item in source)
+            {
+                result.Add(item.Value, item.Key);
+            }
+            return result;
+        }
+
+#if DEBUG
+        static OidLookup()
+        {
+            // Validate we hardcoded the right dictionary size
+            Debug.Assert(s_friendlyNameToOid.Count == FriendlyNameToOidCount,
+                $"Expected {nameof(s_friendlyNameToOid)}.{nameof(s_friendlyNameToOid.Count)} == {FriendlyNameToOidCount}, got {s_friendlyNameToOid.Count}");
+            Debug.Assert(s_oidToFriendlyName.Count == FriendlyNameToOidCount,
+                $"Expected {nameof(s_oidToFriendlyName)}.{nameof(s_oidToFriendlyName.Count)} == {FriendlyNameToOidCount}, got {s_oidToFriendlyName.Count}");
+
+            ExtraStaticDebugValidation();
+        }
+
+        static partial void ExtraStaticDebugValidation();
+#endif
     }
 }
index 251837a..b0cdb20 100644 (file)
     <Reference Include="System.Collections" />
     <Reference Include="System.Collections.Concurrent" />
     <Reference Include="System.Diagnostics.Debug" />
-    <Reference Include="System.Linq" />
     <Reference Include="System.Memory" />
     <Reference Include="System.Resources.ResourceManager" />
     <Reference Include="System.Runtime" />