diff --git a/main/POIFS/Crypt/EncryptionInfo.cs b/main/POIFS/Crypt/EncryptionInfo.cs index 3b243594d..f3007db1f 100644 --- a/main/POIFS/Crypt/EncryptionInfo.cs +++ b/main/POIFS/Crypt/EncryptionInfo.cs @@ -22,7 +22,8 @@ limitations under the License. namespace NPOI.POIFS.Crypt { using System; - using System.Reflection; + using System.Diagnostics.CodeAnalysis; + using System.Net.Security; public class EncryptionInfo { @@ -292,23 +293,47 @@ EncryptionMode encryptionMode _encryptor = eib.GetEncryptor(); } + // REMOVE-REFLECTION: Remove reflections here will prevent NPOI from creating custom encryptors. + // Is it OK? Remove reflection-related code for now. + // It might be better to move Agile classes definition into this library. Now it's defined in NPOI.OOXML.Core. +#if NET6_0_OR_GREATER + [DynamicDependency(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.Interfaces + | DynamicallyAccessedMemberTypes.PublicMethods, EncryptionMode.BuilderNameAgile, "NPOI.OOXML")] +#endif protected static IEncryptionInfoBuilder GetBuilder(EncryptionMode encryptionMode) { - Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); - Type t = null; - foreach (Assembly assembly in assemblies) + switch (encryptionMode.Builder) { - t = assembly.GetType(encryptionMode.Builder); - if (t != null) + case EncryptionMode.BuilderNameBinaryRC4: + return new BinaryRC4.BinaryRC4EncryptionInfoBuilder(); + case EncryptionMode.BuilderNameCryptoAPI: + return new CryptoAPI.CryptoAPIEncryptionInfoBuilder(); + case EncryptionMode.BuilderNameStandard: + return new Standard.StandardEncryptionInfoBuilder(); + case EncryptionMode.BuilderNameAgile: + IEncryptionInfoBuilder instance = CreateAgileInstanceFallback(); + if (instance is not null) + return instance; break; } - if (t == null) + + throw new EncryptedDocumentException("Not found type " + encryptionMode.Builder); + } + + private static Type AgileEncryptionInfo; + private static IEncryptionInfoBuilder CreateAgileInstanceFallback() + { + if (AgileEncryptionInfo is null) { - throw new EncryptedDocumentException("Not found type " + encryptionMode.Builder); + foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) + if ((AgileEncryptionInfo = assembly.GetType(EncryptionMode.BuilderNameAgile)) != null) + break; } - IEncryptionInfoBuilder eib = null; - eib = (IEncryptionInfoBuilder)t.Assembly.CreateInstance(encryptionMode.Builder); - return eib; + + if (AgileEncryptionInfo is null) + return null; + + return (IEncryptionInfoBuilder)Activator.CreateInstance(AgileEncryptionInfo); } private int _versionMajor; diff --git a/main/POIFS/Crypt/EncryptionMode.cs b/main/POIFS/Crypt/EncryptionMode.cs index a5f0e28e4..5976b8ec6 100644 --- a/main/POIFS/Crypt/EncryptionMode.cs +++ b/main/POIFS/Crypt/EncryptionMode.cs @@ -27,14 +27,19 @@ namespace NPOI.POIFS.Crypt */ public class EncryptionMode { + public const string BuilderNameBinaryRC4 = "NPOI.POIFS.Crypt.BinaryRC4.BinaryRC4EncryptionInfoBuilder"; + public const string BuilderNameCryptoAPI = "NPOI.POIFS.Crypt.CryptoAPI.CryptoAPIEncryptionInfoBuilder"; + public const string BuilderNameStandard = "NPOI.POIFS.Crypt.Standard.StandardEncryptionInfoBuilder"; + public const string BuilderNameAgile = "NPOI.POIFS.Crypt.Agile.AgileEncryptionInfoBuilder"; + /* @see 2.3.6 Office Binary Document RC4 Encryption */ - public static readonly EncryptionMode BinaryRC4 = new EncryptionMode("NPOI.POIFS.Crypt.BinaryRC4.BinaryRC4EncryptionInfoBuilder", 1, 1, 0x0); + public static readonly EncryptionMode BinaryRC4 = new EncryptionMode(BuilderNameBinaryRC4, 1, 1, 0x0); /* @see 2.3.5 Office Binary Document RC4 CryptoAPI Encryption */ - public static readonly EncryptionMode CryptoAPI = new EncryptionMode("NPOI.POIFS.Crypt.CryptoAPI.CryptoAPIEncryptionInfoBuilder", 4, 2, 0x04); + public static readonly EncryptionMode CryptoAPI = new EncryptionMode(BuilderNameCryptoAPI, 4, 2, 0x04); /* @see 2.3.4.5 \EncryptionInfo Stream (Standard Encryption) */ - public static readonly EncryptionMode Standard = new EncryptionMode("NPOI.POIFS.Crypt.Standard.StandardEncryptionInfoBuilder", 4, 2, 0x24); + public static readonly EncryptionMode Standard = new EncryptionMode(BuilderNameStandard, 4, 2, 0x24); /* @see 2.3.4.10 \EncryptionInfo Stream (Agile Encryption) */ - public static readonly EncryptionMode Agile = new EncryptionMode("NPOI.POIFS.Crypt.Agile.AgileEncryptionInfoBuilder", 4, 4, 0x40); + public static readonly EncryptionMode Agile = new EncryptionMode(BuilderNameAgile, 4, 4, 0x40); public string Builder { get; private set; }