diff --git a/src/Microsoft.PowerShell.Security/project.json b/src/Microsoft.PowerShell.Security/project.json
index 0f4a3ef2c86..d0de3cb8ed8 100644
--- a/src/Microsoft.PowerShell.Security/project.json
+++ b/src/Microsoft.PowerShell.Security/project.json
@@ -47,19 +47,13 @@
"define": [ "CORECLR" ],
"compile": {
"exclude": [
- "security/CertificateCommands.cs",
- "security/CmsCommands.cs",
"singleshell/installer/MshSecurityMshSnapin.cs",
- "gen/CertificateCommands.cs",
- "gen/CmsCommands.cs",
"gen/SecurityMshSnapinResources.cs"
]
},
"embed": {
"exclude": [
- "resources/CertificateCommands.resx",
- "resources/CmsCommands.resx",
"resources/SecurityMshSnapinResources.resx"
]
}
diff --git a/src/Microsoft.PowerShell.Security/security/CertificateCommands.cs b/src/Microsoft.PowerShell.Security/security/CertificateCommands.cs
index 345c38f272d..11c5c0ee88a 100644
--- a/src/Microsoft.PowerShell.Security/security/CertificateCommands.cs
+++ b/src/Microsoft.PowerShell.Security/security/CertificateCommands.cs
@@ -212,26 +212,20 @@ protected override void ProcessRecord()
private static X509Certificate2 GetCertFromPfxFile(string path)
{
- X509Certificate2 cert = new X509Certificate2();
-
- cert.Import(path);
-
+ X509Certificate2 cert = new X509Certificate2(path);
return cert;
}
private static X509Certificate2 GetCertFromPfxFile(string path, SecureString password)
{
- X509Certificate2 cert = new X509Certificate2();
-
//
// NTRAID#DevDiv Bugs-33007-2004/7/08-kumarp
// the following will not be required once X509Certificate2.Import()
// accepts a SecureString
//
- string clearTextPassword = SecurityUtils.GetStringFromSecureString(password);
-
- cert.Import(path, clearTextPassword, X509KeyStorageFlags.DefaultKeySet);
-
+ string clearTextPassword = Utils.GetStringFromSecureString(password);
+
+ var cert = new X509Certificate2(path, clearTextPassword, X509KeyStorageFlags.DefaultKeySet);
return cert;
}
}
diff --git a/src/Microsoft.PowerShell.Security/security/CmsCommands.cs b/src/Microsoft.PowerShell.Security/security/CmsCommands.cs
index a4bf918ad5b..40ca423458e 100644
--- a/src/Microsoft.PowerShell.Security/security/CmsCommands.cs
+++ b/src/Microsoft.PowerShell.Security/security/CmsCommands.cs
@@ -3,19 +3,14 @@
--********************************************************************/
using System;
-using System.IO;
using System.Management.Automation;
using System.Text;
-using System.Security;
-using System.Security.Cryptography;
using System.Globalization;
using System.Security.Cryptography.Pkcs;
using System.Security.Cryptography.X509Certificates;
using System.Diagnostics.CodeAnalysis;
using System.Collections.ObjectModel;
using System.Collections.Generic;
-using System.Management.Automation.Security;
-using System.Diagnostics.Eventing.Reader;
namespace Microsoft.PowerShell.Commands
{
@@ -279,7 +274,7 @@ protected override void ProcessRecord()
{
if (_contentBuffer.Length > 0)
{
- _contentBuffer.Append(Environment.NewLine);
+ _contentBuffer.Append(System.Environment.NewLine);
}
_contentBuffer.Append(Content);
@@ -456,7 +451,7 @@ protected override void ProcessRecord()
{
if (_contentBuffer.Length > 0)
{
- _contentBuffer.Append(Environment.NewLine);
+ _contentBuffer.Append(System.Environment.NewLine);
}
_contentBuffer.Append(Content);
diff --git a/src/Microsoft.PowerShell.Security/security/Utils.cs b/src/Microsoft.PowerShell.Security/security/Utils.cs
index 1bc0d25d5b3..f9e9c1842ff 100644
--- a/src/Microsoft.PowerShell.Security/security/Utils.cs
+++ b/src/Microsoft.PowerShell.Security/security/Utils.cs
@@ -5,21 +5,9 @@
using System;
using System.IO;
using System.Management.Automation;
-using Microsoft.PowerShell.Commands;
using System.Management.Automation.Host;
using System.Management.Automation.Internal;
using System.Security;
-using System.Security.Principal;
-using System.Security.AccessControl;
-using System.Security.Cryptography;
-using System.Security.Cryptography.X509Certificates;
-
-using System.Collections.Generic;
-using System.Collections.ObjectModel;
-using System.Runtime.InteropServices;
-using DWORD = System.UInt32;
-using BOOL = System.UInt32;
-using FILETIME = System.Runtime.InteropServices.ComTypes.FILETIME;
namespace Microsoft.PowerShell
{
@@ -47,44 +35,6 @@ internal static long GetFileSize(string filePath)
return size;
}
-#if false
- ///
- /// throw if file is smaller than 4 bytes in length
- ///
- ///
- /// path to file
- ///
- /// Does not return a value
- ///
- ///
- ///
- internal static void CheckIfFileSmallerThan4Bytes(string filePath)
- {
- if (GetFileSize(filePath) < 4)
- {
- string message =
- StringUtil.Format(
- UtilsStrings.FileSmallerThan4Bytes,
- new object[] { filePath }
- );
-
- throw PSTraceSource.NewArgumentException(message, "path");
- /*
- // 2004/10/22-JonN The above form of the constructor
- // no longer exists. This should probably be as below,
- // however I have not tested this. This method is not
- // used so I have removed it.
- throw PSTraceSource.NewArgumentException(
- "path",
- "Utils",
- "FileSmallerThan4Bytes",
- filePath
- );
- */
- }
- }
-#endif
-
///
/// present a prompt for a SecureString data
///
@@ -109,74 +59,6 @@ internal static SecureString PromptForSecureString(PSHostUserInterface hostUI,
return ss;
}
-#if !CORECLR
- ///
- /// get plain text string from a SecureString
- ///
- /// This function will not be required once all of the methods
- /// that we call accept a SecureString. The list below has
- /// classes/methods that will be changed to accept a SecureString
- /// after Whidbey beta1
- ///
- /// -- X509Certificate2.Import (String, String, X509KeyStorageFlags)
- /// (DCR #33007 in the DevDiv Schedule db)
- ///
- /// -- NetworkCredential(string, string);
- ///
- ///
- ///
- /// input data
- ///
- /// a string representing clear-text equivalent of ss
- ///
- ///
- ///
- [ArchitectureSensitive]
- internal static string GetStringFromSecureString(SecureString ss)
- {
- IntPtr p = Marshal.SecureStringToGlobalAllocUnicode(ss);
- string s = Marshal.PtrToStringUni(p);
-
- Marshal.ZeroFreeGlobalAllocUnicode(p);
-
- return s;
- }
-#endif
-
- /*
- ///
- /// display sec-desc of a file
- ///
- ///
- /// file security descriptor
- ///
- /// Does not return a value
- ///
- ///
- ///
- internal static void ShowFileSd(FileSecurity sd)
- {
- string userName = null;
- FileSystemRights rights = 0;
- AccessControlType aceType = 0;
-
- rules = sd.GetAccessRules(true, false, typeof(NTAccount));
-
- foreach (FileSystemAccessRule r in rules)
- {
- userName = r.IdentityReference.ToString();
- aceType = r.AccessControlType;
- rights = r.FileSystemRights;
-
- Console.WriteLine("{0} : {1} : {2}",
- userName,
- aceType.ToString(),
- rights.ToString());
- }
- }
- }
- */
-
///
///
///
diff --git a/src/Modules/Unix/Microsoft.PowerShell.Security/Microsoft.PowerShell.Security.psd1 b/src/Modules/Unix/Microsoft.PowerShell.Security/Microsoft.PowerShell.Security.psd1
index f86fa695fbf..45859c96afa 100644
--- a/src/Modules/Unix/Microsoft.PowerShell.Security/Microsoft.PowerShell.Security.psd1
+++ b/src/Modules/Unix/Microsoft.PowerShell.Security/Microsoft.PowerShell.Security.psd1
@@ -7,7 +7,7 @@ ModuleVersion="3.0.0.0"
PowerShellVersion="3.0"
AliasesToExport = @()
FunctionsToExport = @()
-CmdletsToExport="Get-Credential", "Get-ExecutionPolicy", "Set-ExecutionPolicy", "ConvertFrom-SecureString", "ConvertTo-SecureString"
+CmdletsToExport="Get-Credential", "Get-ExecutionPolicy", "Set-ExecutionPolicy", "ConvertFrom-SecureString", "ConvertTo-SecureString", "Get-PfxCertificate"
NestedModules="Microsoft.PowerShell.Security.dll"
HelpInfoURI = 'https://go.microsoft.com/fwlink/?linkid=390786'
}
diff --git a/src/Modules/Windows-Full/Microsoft.PowerShell.Security/Microsoft.PowerShell.Security.psd1 b/src/Modules/Windows-Core+Full/Microsoft.PowerShell.Security/Microsoft.PowerShell.Security.psd1
similarity index 100%
rename from src/Modules/Windows-Full/Microsoft.PowerShell.Security/Microsoft.PowerShell.Security.psd1
rename to src/Modules/Windows-Core+Full/Microsoft.PowerShell.Security/Microsoft.PowerShell.Security.psd1
diff --git a/src/Modules/Windows-Core/Microsoft.PowerShell.Security/Microsoft.PowerShell.Security.psd1 b/src/Modules/Windows-Core/Microsoft.PowerShell.Security/Microsoft.PowerShell.Security.psd1
deleted file mode 100644
index f47251e8321..00000000000
--- a/src/Modules/Windows-Core/Microsoft.PowerShell.Security/Microsoft.PowerShell.Security.psd1
+++ /dev/null
@@ -1,13 +0,0 @@
-@{
-GUID="A94C8C7E-9810-47C0-B8AF-65089C13A35A"
-Author="Microsoft Corporation"
-CompanyName="Microsoft Corporation"
-Copyright="© Microsoft Corporation. All rights reserved."
-ModuleVersion="3.0.0.0"
-PowerShellVersion="3.0"
-AliasesToExport = @()
-FunctionsToExport = @()
-CmdletsToExport="Get-Acl", "Set-Acl", "Get-Credential", "Get-ExecutionPolicy", "Set-ExecutionPolicy", "Get-AuthenticodeSignature", "Set-AuthenticodeSignature", "ConvertFrom-SecureString", "ConvertTo-SecureString", "New-FileCatalog" , "Test-FileCatalog"
-NestedModules="Microsoft.PowerShell.Security.dll"
-HelpInfoURI = 'https://go.microsoft.com/fwlink/?linkid=390786'
-}
diff --git a/src/System.Management.Automation/CoreCLR/CorePsStub.cs b/src/System.Management.Automation/CoreCLR/CorePsStub.cs
index 662356ccf40..b4bc1c57a23 100644
--- a/src/System.Management.Automation/CoreCLR/CorePsStub.cs
+++ b/src/System.Management.Automation/CoreCLR/CorePsStub.cs
@@ -793,31 +793,6 @@ public enum RollbackSeverity
#endregion PSTransaction
- #region CMS
-
- internal static class CmsUtils
- {
- internal static string BEGIN_CERTIFICATE_SIGIL = "-----BEGIN CERTIFICATE-----";
- internal static string END_CERTIFICATE_SIGIL = "-----END CERTIFICATE-----";
-
- internal static string Encrypt(byte[] contentBytes, CmsMessageRecipient[] recipients, SessionState sessionState, out ErrorRecord error)
- {
- throw new NotImplementedException("CmsUtils.Encrypt(...) is not implemented in CoreCLR powershell.");
- }
-
- internal static string GetAsciiArmor(byte[] bytes)
- {
- throw new NotImplementedException("CmsUtils.GetAsciiArmor(...) is not implemented in CoreCLR powershell.");
- }
-
- internal static byte[] RemoveAsciiArmor(string actualContent, string beginMarker, string endMarker, out int startIndex, out int endIndex)
- {
- throw new NotImplementedException("CmsUtils.RemoveAsciiArmor(...) is not implemented in CoreCLR powershell.");
- }
- }
-
- #endregion CMS
-
#region ApartmentState
internal enum ApartmentState
diff --git a/src/System.Management.Automation/project.json b/src/System.Management.Automation/project.json
index 904f2496f79..9af39fe58d5 100644
--- a/src/System.Management.Automation/project.json
+++ b/src/System.Management.Automation/project.json
@@ -183,6 +183,7 @@
"System.Reflection.Emit.Lightweight": "4.3.0",
"System.Security.AccessControl": "4.3.0",
"System.Security.Cryptography.Algorithms": "4.3.0",
+ "System.Security.Cryptography.Pkcs": "4.3.0",
"System.Security.Cryptography.X509Certificates": "4.3.0",
"System.Threading.Thread": "4.3.0",
"System.Threading.Tasks.Parallel": "4.3.0",
diff --git a/src/System.Management.Automation/security/SecuritySupport.cs b/src/System.Management.Automation/security/SecuritySupport.cs
index b1c72471921..fe6f53daab2 100644
--- a/src/System.Management.Automation/security/SecuritySupport.cs
+++ b/src/System.Management.Automation/security/SecuritySupport.cs
@@ -1012,17 +1012,11 @@ internal enum CertificatePurpose
namespace System.Management.Automation
{
-#if !CORECLR
-
using System.Security.Cryptography.Pkcs;
///
/// Utility class for CMS (Cryptographic Message Syntax) related operations
///
- ///
- /// The namespace 'System.Security.Cryptography.Pkcs' is not available in CoreCLR,
- /// so the Cryptographic Message Syntax (CMS) will not be supported on OneCore PS.
- ///
internal static class CmsUtils
{
internal static string Encrypt(byte[] contentBytes, CmsMessageRecipient[] recipients, SessionState sessionState, out ErrorRecord error)
@@ -1086,8 +1080,7 @@ internal static string GetAsciiArmor(byte[] bytes)
StringBuilder output = new StringBuilder();
output.AppendLine(BEGIN_CMS_SIGIL);
- string encodedString = Convert.ToBase64String(
- bytes, Base64FormattingOptions.InsertLineBreaks);
+ string encodedString = ClrFacade.ToBase64StringWithLineBreaks(bytes);
output.AppendLine(encodedString);
output.Append(END_CMS_SIGIL);
@@ -1131,8 +1124,6 @@ internal static byte[] RemoveAsciiArmor(string actualContent, string beginMarker
}
}
-#endif
-
///
/// Represents a message recipient for the Cms cmdlets.
///
@@ -1271,7 +1262,7 @@ private void ResolveFromBase64Encoding(ResolutionPurpose purpose, out ErrorRecor
return;
}
- List certificatesToProcess = new List(); ;
+ List certificatesToProcess = new List();
try
{
X509Certificate2 newCertificate = new X509Certificate2(messageBytes);
diff --git a/src/System.Management.Automation/utils/ClrFacade.cs b/src/System.Management.Automation/utils/ClrFacade.cs
index 4583f925f14..2c7a8f713aa 100644
--- a/src/System.Management.Automation/utils/ClrFacade.cs
+++ b/src/System.Management.Automation/utils/ClrFacade.cs
@@ -661,6 +661,36 @@ internal static void SetCurrentThreadUiCulture(CultureInfo uiCultureInfo)
#region Misc
+ ///
+ /// Facade for Convert.ToBase64String(bytes, Base64FormattingOptions.InsertLineBreaks)
+ /// Inserts line breaks after every 76 characters in the string representation.
+ ///
+ internal static string ToBase64StringWithLineBreaks(byte[] bytes)
+ {
+#if CORECLR
+ // Inserts line breaks after every 76 characters in the string representation.
+ string encodedRawString = Convert.ToBase64String(bytes);
+ if (encodedRawString.Length <= 76)
+ return encodedRawString;
+
+ StringBuilder builder = new StringBuilder(encodedRawString.Length);
+ int index = 0, remainingLen = encodedRawString.Length;
+ while (remainingLen > 76)
+ {
+ builder.Append(encodedRawString, index, 76);
+ builder.Append(System.Environment.NewLine);
+
+ index += 76;
+ remainingLen -= 76;
+ }
+
+ builder.Append(encodedRawString, index, remainingLen);
+ return builder.ToString();
+#else
+ return Convert.ToBase64String(bytes, Base64FormattingOptions.InsertLineBreaks);
+#endif
+ }
+
///
/// Facade for RemotingServices.IsTransparentProxy(object)
///
diff --git a/test/powershell/Modules/Microsoft.PowerShell.Security/CmsMessage.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Security/CmsMessage.Tests.ps1
new file mode 100644
index 00000000000..1f500b2bb30
--- /dev/null
+++ b/test/powershell/Modules/Microsoft.PowerShell.Security/CmsMessage.Tests.ps1
@@ -0,0 +1,421 @@
+
+Function Create-TestCertificate
+{
+ $dataEnciphermentCert = "
+MIIKYAIBAzCCCiAGCSqGSIb3DQEHAaCCChEEggoNMIIKCTCCBgoGCSqGSIb3DQEHAaCCBfsEggX3
+MIIF8zCCBe8GCyqGSIb3DQEMCgECoIIE/jCCBPowHAYKKoZIhvcNAQwBAzAOBAgPOFDMBkCffQIC
+B9AEggTYjY55RrmAhdj1grENxXjiPrVNdS++pb5UOn3M7O78BR0U1i2h5zvjkPjOwdLoOCbq5pgg
+F0PKaMjHVu8EoZxSqsib17ptR5Rx5N23hseuJUzS8fTAHiBet9payNOJlPfkpuqMfQEmCAo9gAPz
+w4RiyZNOA3NhxkfGl9yU4O9GSEr2koWKCUoCNelkIXVbkV728L7zSiWRSqRb7V4QJAtwtgPLTbl/
+zo2SFhdNAGPeXbcOsKCv9trhuxPZ0FH4fukbXkHs0I3b5mYgMUI5Mds7UwT3wCtz+Ev9pLbmYN8X
+NfH0tAK8ZGnQS1GcI4xCMEM8T9Tx3uwWY4arvRM3GTLwyt8JZEVZNTuYL9A9+RyeiO5d5xEKG8H4
+snOCoTriT45tdl8hzMBCdc3jWxWiydmNRw47irifv5BX7BK/6FLAxkMRwACAxNO63ezG/OxuDDEz
+ml+KzeZNvr4u4mTBcgZ49vMSyfRt/my+5+iLnSMGp4Rt0uix8489wctkxGlgyXGk23pA4Cj4hq/6
+txopcl2gHn+DAFrHIgLg4JR8lcuOzBw8nFOrhK7iR9aMK21apxwImIaDCKJ1grOfbuElq4pkMpov
+SltJe00WB94o69LibOg5LqpTrHW2/DY951sIgElF83FdUBhoZHasfCme/RxgliQf3QHedmENXSjr
+8R8PAWX4wC0ZZVC0qcq5XP0PkwtuDKmfqq69R32nmBzpRrfypm9S+PfsYZeCeuROh6YKQ0ZBMnLb
+8Y9povpXh0lYwVLuPanvAFiCT4vI7oRd1Mg1Zr9ZooMFAVomall1UnQQ29fvsoADjEDcPymVT80o
+kTkw3NXnTX6fGZ94Eh0KZcuMgjTqIO3OKpH0lcaSBxlES4V0sO/mwP4ULy8l3dcnn440Nei33VDo
+B7n2jhjJl/HvtltfEEEw1DW9AWDvkJDp878sD6VoyQZehvvxBNT0FwMr20TbVKeAGxf9n+xJ9Alo
+VUS3qE7XnpxAAAR5L2OG+tMd4dyDSge1qrkVNZ3/uUzKKCZei2P7ICR9cX1FRsmcINdNfydIA2cA
+Pmeq+UkRdqsJxt1NSK5bLvMM4EHRQZMMbXVKxxJ+kQDrzfQtERFPyd3Hdm2F4T/JXUQ+PrTQnRqY
+LruTAiZfxygZuFrxJnNTRydRdbEaTAtMjFCMRFZ2wctJsgCb3yN9tt0JDYxIvm0MSehXiF+sCrl4
+yZvvUzJqrgppHRTBR4Sao+MZ/rJ30vVU19Q3oBi9ikTqDY+4SrHsp5Y4llnsbrz0Web+h2jLvyJz
+LgKuqs87qHhToVMLuULy/HLqY3m661EMwNqh5D76gSFI+TP2/rzT5mVOGglahFoc848o4cshtPWE
+9MjAkDfsMbIfeKH3uh3D+eBIxYmZ5Cq2aHzqdQ0pU/nDNX7BDjC3E80VcQnXx4U6tRsQHsGtbcld
+MFTp0yHJ2KLkz+inH3WPy/lYuVZ0QJe+LqvGt+bt1DgQmLBMD9WLFML3d0TtkuY3RhD5Y0wr2zt9
+tT6WVTn8Hob1cJns4N7tDEr8Q3TdIar0I5Bzj3qoesJt+4lxwnVdUA1bNJ2zxXIkDfX/MTB464FI
+2g9uhUs3lIOEiCjeJCwBebgZa1HlfhyCRu0E7fnNnKLaGWRs8LVy7MZIfe1kJoDVgTGB3TATBgkq
+hkiG9w0BCRUxBgQEAQAAADBdBgkrBgEEAYI3EQExUB5OAE0AaQBjAHIAbwBzAG8AZgB0ACAAUwB0
+AHIAbwBuAGcAIABDAHIAeQBwAHQAbwBnAHIAYQBwAGgAaQBjACAAUAByAG8AdgBpAGQAZQByMGcG
+CSqGSIb3DQEJFDFaHlgAQwBlAHIAdABSAGUAcQAtAGEAYgA5AGUAZgA3AGYAOAAtAGUAYwA2AGEA
+LQA0ADUAMwA4AC0AOQA4AGQAOAAtADAAYQA4AGUAYwA4ADUAOQBkADkAMgAxMIID9wYJKoZIhvcN
+AQcGoIID6DCCA+QCAQAwggPdBgkqhkiG9w0BBwEwHAYKKoZIhvcNAQwBBjAOBAiYL6rZmAGN9QIC
+B9CAggOw8eaNgIqx26SlOBKKQZ5O7NDZQHbytHTWn4ifNhVFUkbuaj22/VnYOFB9//8BLY6t0Dvw
+X6wqXSMnbr1jOuUYaFdJzOBZBsYQfFTfoJ4iOb2jwwIpZSgTHeqgXbvnI7MIxauu6F4UseWVxt3u
+ZhHjEZQjKWeC5mNCb6wX0IOQk96n1RJnJ3v1D4Q5YrVekOVq70VhRNtLOZMkrJV7vDMNlUYXD69D
+PbcyPajVvETq0W98YNKB89oNwFWuKoMLNPWmSwIfn10oSEtybNEEr2IVgCBt2w2eb+nIDuA3c/Rc
+qKPXwVGMzoUyAiGwTcueCdMRmiuQAuKCUyi9P/JqeIbgHtg15nAoGtw+l4MsFXfdMJjTCDd0WYff
+l9ipaNnw8erCPquD0+wXeMnNivXaFzu2+CGwCSwbDl2M49HAQdtpKhNj5jKJBEP1GRQIk173gbEZ
+n69IXUCsf0GDZiZVNbAQHBOuRoEHpBhendFgTJFAU2LDHlmV6OA0LYHaSn7CP/vOXOhWXJ1yGL2p
+SeUepciwQV7sOHqDExWY82fd1kHSHcgCAkWLSSdIPlWhyeqjC1agSP6b74VK8uLRPkin5F9wGIPi
+ewe/LsW3PTtDkDnj3DiSioKlQRUUxVxzi5qPBs+7vJEhbuO7UhtsMCWeUygDbw6n8BKan4w9iLhx
+7/z6zVvQmLnK4HZChTPFuThRy1NctupoX7nE+CDgyhcmryaTDXohkviMWl4Od+8uGh8Quv2bHk6Y
+UnFqNB/hSqYMkTuMLH4F9sVzoQEsYu96CDwbQaggbLMnPtmHKsPtzdnWQnys+oGT4uD8vl9xFdEW
+AZdestrxbDK0La0AgGszUE+6B/GtOs2pv0fMXXYV2h+dAlwfz7oLxzm9E+SFgzviL+6PuI9fDHNd
+pWeq/Rr5OpFb3rSotGTl84aIjk3hPd3uHujPQh8GO2EQ5k6p6ukk+a7gOUB+pH8fHihFl5L7pI0z
+yRp0FvbZo//hmACYMvINoy2EQxjYLh7QLeE4qEr8bkzJVgEURUvcUpyHFJT6PGzUMqGx/Wjh2jJc
+HfEDPMUDoTE/QRzLW7XrmQgJIRuHgPI/cqmOyvpEvuwdRhYyHEKktRO3tGjeflohDCyDW9bxOaJV
+ZP64KBordM28ZHCQbnSdU0I5us6qiFX2PiLlBzRMH2ftUNMYReioqZyR+Xv5wjaoydV3//BDMH8M
+1lh9GazUO8+OtzQEH0jiBi6ctlzFT8nNI2C+cOB9S3yMAjCEQa8wNzAfMAcGBSsOAwIaBBR96vF2
+OksttXT1kXf+aez9EzDlsgQU4ck78h0WTy01zHLwSKNWK4wFFQM=
+"
+
+ $dataEnciphermentCert = $dataEnciphermentCert -replace '\s',''
+ $certBytes = [Convert]::FromBase64String($dataEnciphermentCert)
+ $certLocation = Join-Path $TestDrive "ProtectedEventLogging.pfx"
+ [IO.File]::WriteAllBytes($certLocation, $certBytes)
+
+ return $certLocation
+}
+
+
+Describe "CmsMessage cmdlets and Get-PfxCertificate basic tests" -Tags "CI" {
+
+ BeforeAll {
+ $certLocation = Create-TestCertificate
+ $certLocation | Should Not BeNullOrEmpty | Out-Null
+ }
+
+ It "Verify Get-PfxCertificate -FilePath" {
+ $cert = Get-PfxCertificate -FilePath $certLocation
+ $cert.Subject | Should Be "CN=MyDataEnciphermentCert"
+ }
+
+ It "Verify Get-PfxCertificate -LiteralPath" {
+ $cert = Get-PfxCertificate -LiteralPath $certLocation
+ $cert.Subject | Should Be "CN=MyDataEnciphermentCert"
+ }
+
+ It "Verify Get-PfxCertificate positional argument" {
+ $cert = Get-PfxCertificate $certLocation
+ $cert.Subject | Should Be "CN=MyDataEnciphermentCert"
+ }
+
+ It "Verify CMS message recipient resolution by path" -Skip:(!$IsWindows) {
+ $errors = $null
+ $recipient = [System.Management.Automation.CmsMessageRecipient] $certLocation
+ $recipient.Resolve($ExecutionContext.SessionState, "Encryption", [ref] $errors)
+
+ $recipient.Certificates.Count | Should Be 1
+ $recipient.Certificates[0].Subject | Should Match 'CN=MyDataEnciphermentCert'
+ }
+
+ It "Verify CMS message recipient resolution by cert" -Skip:(!$IsWindows) {
+ $errors = $null
+ $cert = Get-PfxCertificate $certLocation
+ $recipient = [System.Management.Automation.CmsMessageRecipient] $cert
+ $recipient.Resolve($ExecutionContext.SessionState, "Encryption", [ref] $errors)
+
+ $recipient.Certificates.Count | Should Be 1
+ $recipient.Certificates[0].Subject | Should Match 'CN=MyDataEnciphermentCert'
+ }
+
+ It "Verify a CMS message can be protected / unprotected" -Skip:(!$IsWindows) {
+ $protected = "Hello World","How are you?" | Protect-CmsMessage -To $certLocation
+ $protected.IndexOf("-----BEGIN CMS-----") | Should Be 0
+
+ $message = $protected | Get-CmsMessage
+ $message.Recipients.Count | Should Be 1
+ $message.Recipients[0].IssuerName | Should Be "CN=MyDataEnciphermentCert"
+
+ $expected = "Hello World" + [System.Environment]::NewLine + "How are you?"
+ $decrypted = $message | Unprotect-CmsMessage -To $certLocation
+ $decrypted | Should Be $expected
+
+ $decrypted = $protected | Unprotect-CmsMessage -To $certLocation
+ $decrypted | Should Be $expected
+ }
+}
+
+
+Describe "CmsMessage cmdlets thorough tests" -Tags "Feature" {
+
+ BeforeAll {
+ if ($IsWindows)
+ {
+ $certLocation = Create-TestCertificate
+ $certLocation | Should Not BeNullOrEmpty | Out-Null
+
+ if ($IsCoreCLR)
+ {
+ # PKI module is not available for PowerShell Core, so we need to use Windows PowerShell to import the cert
+ $fullPowerShell = Join-Path "$env:SystemRoot" "System32\WindowsPowerShell\v1.0\powershell.exe"
+
+ try {
+ $modulePathCopy = $env:PSMODULEPATH
+ $env:PSMODULEPATH = $null
+
+ $importedCertPath = & $fullPowerShell -NoProfile -NonInteractive `
+ -Command "Import-PfxCertificate $certLocation -CertStoreLocation cert:\CurrentUser\My | % PSPath"
+ $importedCert = Get-ChildItem $importedCertPath
+ } finally {
+ $env:PSMODULEPATH = $modulePathCopy
+ }
+ }
+ else
+ {
+ $importedCert = Import-PfxCertificate $certLocation -CertStoreLocation cert:\CurrentUser\My
+ }
+ }
+ else
+ {
+ # Skip for non-Windows platforms
+ $defaultParamValues = $PSdefaultParameterValues.Clone()
+ $PSdefaultParameterValues = @{ "it:skip" = $true }
+ }
+ }
+
+ AfterAll {
+ if ($IsWindows)
+ {
+ if ($importedCert)
+ {
+ Remove-Item (Join-Path Cert:\CurrentUser\My $importedCert.Thumbprint) -Force -ErrorAction SilentlyContinue
+ }
+ }
+ else
+ {
+ $PSdefaultParameterValues = $defaultParamValues
+ }
+ }
+
+ It "Verify message recipient resolution by Base64Cert" {
+ $certContent = "
+ -----BEGIN CERTIFICATE-----
+ MIIDXTCCAkWgAwIBAgIQRTsRwsx0LZBHrx9z5Dag2zANBgkqhkiG9w0BAQUFADAh
+ MR8wHQYDVQQDDBZNeURhdGFFbmNpcGhlcm1lbnRDZXJ0MCAXDTE0MDcyNTIyMjkz
+ OVoYDzMwMTQwNzI1MjIzOTM5WjAhMR8wHQYDVQQDDBZNeURhdGFFbmNpcGhlcm1l
+ bnRDZXJ0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx3SuShUvnRqn
+ tYOIouJdP3wPZ5rtDi2KYPurpngGNZjM0EGDTrnhmEAI8DL4Kp6n/zz1mYVoX73+
+ 6uCpZX/13VDXg1neebJ261XpBX6FzxtclIQr8ywdUtrEgCnUAhgqgvO1Wwm4ogNR
+ tWGCGkmlnqyaoV1j/V4KSn4WvKqSUIOZm0umGCTtNAJ6VtdpYO+uxxnRAapPUCY+
+ qQ7DFzTUECIo1lMlBcuMiXj6NSFr4/D7ltkZ27jCdsZmzI7ZvRnDlfSYTPQnAO/E
+ 0uYn9uyKY/xfngWkUX/pe+j+10Lm1ypbASrj2Ezgf0KeZRXBwqKUOLhKheEmBJ18
+ rLV27qwHeQIDAQABo4GOMIGLMA4GA1UdDwEB/wQEAwIEMDAUBgNVHSUEDTALBgkr
+ BgEEAYI3UAEwRAYJKoZIhvcNAQkPBDcwNTAOBggqhkiG9w0DAgICAIAwDgYIKoZI
+ hvcNAwQCAgCAMAcGBSsOAwIHMAoGCCqGSIb3DQMHMB0GA1UdDgQWBBRIyIzwInLJ
+ 3B+FajVUFMACf1hrxjANBgkqhkiG9w0BAQUFAAOCAQEAfFt4rmUmWfCbbwi2mCrZ
+ Osq0lfVNUiZ+iLlEKga4VAI3sJZRtErnVM70eXUt7XpRaOdIfxjuXFpsgc37KyLi
+ ByCORLuRC0itZVs3aba48opfMDXivxBy0ngqCPPLQsyaN9K7WnpvYV1QxiudYwwU
+ 8U5rFmzlwNLvc3XiyoGWaVZluk2DIJawQ5QYAU9/NMBBCbPHjTG7k0l4cpcEC+Ex
+ od3RlO6/MOYuK2WB4VTxKsV80EdA3ljlu7Td8P4movnrbB4rG4wpCpk05eREkg/5
+ Y54Ilo9m5OSAWtdx4yfS779eebLgUs3P+dk6EKwovXMokVveZA8cenIp3QkqSpeT
+ cQ==
+ -----END CERTIFICATE-----
+ "
+
+ $errors = $null
+ $recipient = [System.Management.Automation.CmsMessageRecipient] $certContent
+ $recipient.Resolve($ExecutionContext.SessionState, "Encryption", [ref] $errors)
+
+ $recipient.Certificates.Count | Should Be 1
+ $recipient.Certificates[0].Subject | Should Match 'CN=MyDataEnciphermentCert'
+ }
+
+ It "Verify wildcarded recipient resolution by path [Decryption]" {
+ $errors = $null
+ $recipient = [System.Management.Automation.CmsMessageRecipient] ($certLocation + "*")
+ $recipient.Resolve($ExecutionContext.SessionState, "Decryption", [ref] $errors)
+
+ # Should have resolved single cert
+ $recipient.Certificates.Count | Should Be 1
+ }
+
+ It "Verify wildcarded recipient resolution by path [Encryption]" {
+ $errors = $null
+ $recipient = [System.Management.Automation.CmsMessageRecipient] ($certLocation + "*")
+ $recipient.Resolve($ExecutionContext.SessionState, "Encryption", [ref] $errors)
+
+ $recipient.Certificates.Count | Should Be 1
+ }
+
+ It "Verify resolution by directory" {
+ $protectedEventLoggingCertPath = Join-Path $TestDrive ProtectedEventLoggingDir
+ $null = New-Item -ItemType Directory $protectedEventLoggingCertPath -Force
+ Copy-Item $certLocation $protectedEventLoggingCertPath
+ Copy-Item $certLocation (Join-Path $protectedEventLoggingCertPath "SecondCert.pfx")
+ Copy-Item $certLocation (Join-Path $protectedEventLoggingCertPath "ThirdCert.pfx")
+
+ $errors = $null
+ $recipient = [System.Management.Automation.CmsMessageRecipient] $protectedEventLoggingCertPath
+ $recipient.Resolve($executionContext.SessionState, "Decryption", [ref] $errors)
+
+ $recipient.Certificates.Count | Should Be 1
+ }
+
+ It "Verify resolution by thumbprint" {
+ $errors = $null
+ $recipient = [System.Management.Automation.CmsMessageRecipient] $importedCert.Thumbprint
+ $recipient.Resolve($ExecutionContext.SessionState, "Decryption", [ref] $errors)
+
+ # "Should have certs from thumbprint in 'My' store"
+ $recipient.Certificates.Count | Should Be 1
+ $recipient.Certificates[0].Thumbprint | Should Be $importedCert.Thumbprint
+ }
+
+ It "Verify resolution by subject name" {
+ $errors = $null
+ $recipient = [System.Management.Automation.CmsMessageRecipient] $importedCert.Subject
+ $recipient.Resolve($ExecutionContext.SessionState, "Decryption", [ref] $errors)
+
+ $recipient.Certificates.Count | Should Be 1
+ $recipient.Certificates[0].Thumbprint | Should Be $importedCert.Thumbprint
+ }
+
+ It "Verify error when no cert found in encryption for encryption" {
+ $errors = $null
+ $recipient = [System.Management.Automation.CmsMessageRecipient] "SomeCertificateThatDoesNotExist*"
+ $recipient.Resolve($ExecutionContext.SessionState, "Encryption", [ref] $errors)
+
+ $errors.Count | Should Be 1
+ $errors[0].FullyQualifiedErrorId | Should Be "NoCertificateFound"
+ }
+
+ It "Verify error when encrypting to non-wildcarded identifier for decryption" {
+ $errors = $null
+ $recipient = [System.Management.Automation.CmsMessageRecipient] "SomeCertificateThatDoesNotExist"
+ $recipient.Resolve($ExecutionContext.SessionState, "Decryption", [ref] $errors)
+
+ $errors.Count | Should Be 1
+ $errors[0].FullyQualifiedErrorId | Should Be "NoCertificateFound"
+ }
+
+ It "Verify error when encrypting to wrong cert" {
+ $errors = $null
+ $goodCerts = @(Get-ChildItem Cert:\currentuser\My -DocumentEncryptionCert | ForEach-Object Thumbprint)
+ $badCert = Get-ChildItem Cert:\currentuser\My | ? { $_.Thumbprint -notin $goodCerts } | Select -First 1
+
+ $recipient = [System.Management.Automation.CmsMessageRecipient] $badCert.Thumbprint
+ $recipient.Resolve($ExecutionContext.SessionState, "Encryption", [ref] $errors)
+
+ $errors.Count | Should Be 1
+ $errors[0].FullyQualifiedErrorId | Should Be "CertificateCannotBeUsedForEncryption"
+ }
+
+ It "Verify no error when encrypting to wildcarded identifier for decryption" {
+ $errors = $null
+ $recipient = [System.Management.Automation.CmsMessageRecipient] "SomeCertificateThatDoesNotExist*"
+ $recipient.Resolve($ExecutionContext.SessionState, "Decryption", [ref] $errors)
+
+ $errors | Should Be $null
+ $recipient.Certificates.Count | Should Be 0
+ }
+
+ It "Verify Protect-CmsMessage emits recipient errors" {
+ try {
+ "Hello World" | Protect-CmsMessage -To "SomeThumbprintThatDoesNotExist" -ErrorAction Stop
+ throw "No Exception!"
+ } catch {
+ $_.FullyQualifiedErrorId | Should Be "NoCertificateFound,Microsoft.PowerShell.Commands.ProtectCmsMessageCommand"
+ }
+ }
+
+ It "Verify CmsMessage cmdlets works with paths" {
+ try {
+ $randomNum = Get-Random -Minimum 1000 -Maximum 9999
+ $tempPath = Join-Path $TestDrive "$randomNum-Path-Test-File"
+ $encryptedPath = $tempPath + ".encrypted.txt"
+ "Hello World","How are you?" | Set-Content $tempPath
+
+ Protect-CmsMessage -Path $tempPath -To $certLocation -OutFile $encryptedPath
+
+ $message = Get-CmsMessage -LiteralPath $encryptedPath
+ $message.Recipients.Count | Should Be 1
+ $message.Recipients[0].IssuerName | Should Be "CN=MyDataEnciphermentCert"
+
+ $expected = "Hello World" + [System.Environment]::NewLine + "How are you?" + [System.Environment]::NewLine
+ $decrypted = $message | Unprotect-CmsMessage -To $certLocation
+ $decrypted | Should Be $expected
+
+ $decrypted = Unprotect-CmsMessage -Path $encryptedPath -To $certLocation
+ $decrypted | Should Be $expected
+ } finally {
+ Remove-Item $tempPath, $encryptedPath -Force -ErrorAction SilentlyContinue
+ }
+ }
+
+ It "Verify Unprotect-CmsMessage works with local store" {
+ try {
+ $randomNum = Get-Random -Minimum 1000 -Maximum 9999
+ $tempPath = Join-Path $TestDrive "$randomNum-Path-Test-File"
+ "Hello World" | Protect-CmsMessage -To $certLocation -OutFile $tempPath
+
+ # Decrypt using $importedCert in the Cert store
+ $decrypted = Unprotect-CmsMessage -Path $tempPath
+ $decrypted | Should Be "Hello World"
+ } finally {
+ Remove-Item $tempPath -Force -ErrorAction SilentlyContinue
+ }
+ }
+
+ It "Verify Unprotect-CmsMessage emits recipient errors" {
+ try {
+ "" | Unprotect-CmsMessage -To "SomeThumbprintThatDoesNotExist" -IncludeContext -ErrorAction Stop
+ throw "No Exception!"
+ } catch {
+ $_.FullyQualifiedErrorId | Should Be "NoCertificateFound,Microsoft.PowerShell.Commands.UnprotectCmsMessageCommand"
+ }
+ }
+
+ It "Verify failure to extract Ascii armor generates an error [Unprotect-CmsMessage]" {
+ try {
+ "Hello World" | Unprotect-CmsMessage -ErrorAction Stop
+ throw "No Exception!"
+ } catch {
+ $_.FullyQualifiedErrorId | Should Be "InputContainedNoEncryptedContentIncludeContext,Microsoft.PowerShell.Commands.UnprotectCmsMessageCommand"
+ }
+ }
+
+ It "Verify failure to extract Ascii armor generates an error [Get-CmsMessage]" {
+ try {
+ "Hello World" | Get-CmsMessage -ErrorAction Stop
+ throw "No Exception!"
+ } catch {
+ $_.FullyQualifiedErrorId | Should Be "InputContainedNoEncryptedContent,Microsoft.PowerShell.Commands.GetCmsMessageCommand"
+ }
+ }
+
+ It "Verify 'Unprotect-CmsMessage -IncludeContext' with no encrypted input" {
+ # Should have round-tripped content
+ $result = "Hello World" | Unprotect-CmsMessage -IncludeContext
+ $result | Should Be "Hello World"
+ }
+
+ It "Verify Unprotect-CmsMessage lets you include context" {
+ $protected = "Hello World" | Protect-CmsMessage -To $certLocation
+ $adjustedProtected = "Pre content" + [System.Environment]::NewLine + $protected + [System.Environment]::NewLine + "Post content"
+
+ $decryptedNoContext = $adjustedProtected | Unprotect-CmsMessage -To $certLocation
+ $decryptedWithContext = $adjustedProtected | Unprotect-CmsMessage -To $certLocation -IncludeContext
+
+ $decryptedNoContext | Should Be "Hello World"
+
+ $expected = "Pre content" + [System.Environment]::NewLine + "Hello World" + [System.Environment]::NewLine + "Post content"
+ $decryptedWithContext | Should Be $expected
+ }
+
+ It "Verify Unprotect-CmsMessage treats event logs as a first class citizen" {
+ $protected = "Encrypted Message1","Encrypted Message2" | Protect-CmsMessage -To $certLocation
+ $virtualEventLog = Get-WinEvent Microsoft-Windows-PowerShell/Operational -MaxEvents 1
+ $savedId = $virtualEventLog.Id
+ $virtualEventLog.Message = $protected
+
+ $expected = "Encrypted Message1" + [System.Environment]::NewLine + "Encrypted Message2"
+ $decrypted = $virtualEventLog | Unprotect-CmsMessage -To $certLocation
+ $decrypted | Should Be $expected
+
+ $processed = $virtualEventLog | Unprotect-CmsMessage -To $certLocation -IncludeContext
+ $processed.Id | Should Be $savedId
+ $processed.Message | Should Be $expected
+ }
+
+ It "Verify -DocumentEncryptionCert parameter works" {
+ $foundCerts = Get-ChildItem Cert:\CurrentUser -Recurse -DocumentEncryptionCert
+
+ # Validate they all match the EKU
+ $correctMatching = $foundCerts | ? {
+ ($_.EnhancedKeyUsageList.Count -gt 0) -and
+ ($_.EnhancedKeyUsageList[0].ObjectId -eq '1.3.6.1.4.1.311.80.1')
+ }
+ # "All Document Encryption Cert should have had correct EKU"
+ @($foundCerts).Count | Should Be @($correctMatching).Count
+ }
+
+ It "Verify protect message using OutString" {
+ $protected = Get-Process -Id $pid | Protect-CmsMessage -To $certLocation
+ $decrypted = $protected | Unprotect-CmsMessage -To $certLocation
+ # Should have had PID in output
+ $decrypted | Should Match $pid
+ }
+}