Windows 系统 TLS 密码套件操作

[TOCM]

一、前言


Windows 10 及 Windows Server 2016 操作系统可以使用 PowerShell 命令获得系统支持的 TLS 密码套件列表,并且禁用或启用相应的密码套件。其他版本 Windows 系统密码套件,微软没有给出 PowerShell 操作命令,但在微软给出了,使用 C++ 调用函数,和使用 Microsoft 管理控制台,操作密码套件。

二、获取密码套件列表


使用命令GET-TlsCipherSuite获取计算机的 TLS 密码套件列表。

语法:
  1. Get-TlsCipherSuite [[-Name] <String>] [<CommonParameters>]
参数:
  • [[-Name] <String>] 非必选参数。值为字符串类型,无默认值。指定要获取的 TLS 密码套件的名称。可指定部分名称,支持模糊匹配,不支持通配符匹配。
  • [<CommonParameters>] 非必选参数。固定参数:-Verbose-Debug-ErrorAction-ErrorVariable-OutBuffer-OutVariable
示例 1:获取所有密码套件

此命令获取计算机的所有 TLS 密码套件。

  1. PS C:\> Get-TlsCipherSuite
示例 2:获取与字符串匹配的密码套件

此命令获取名称包含字符串 DES 的所有密码套件。

  1. PS C:\> Get-TlsCipherSuite -Name "DES"

三、启用密码套件


使用命令Enable-TlsCipherSuite启用 TLS 密码套件。

语法:
  1. Enable-TlsCipherSuite [-Name] <String> [[-Position] <UInt32>] [<CommonParameters>]
参数:
  • [-Name] <String> 必选参数。指定要启用的 TLS 密码套件的名称。
  • [[-Position] <UInt32>] 非必选参数。指定在 TLS 密码套件的有序列表中插入密码套件的位置。如果不指定位置,则默认插入列表末尾。指定值 0 或 CRYPT_PRIORITY_TOP 以将插入列表顶部。指定值 42949672950xFFFFFFFFCRYPT_PRIORITY_BOTTOM 以在列表末尾插入。
  • [<CommonParameters>] 非必选参数。固定参数:-Verbose-Debug-ErrorAction-ErrorVariable-OutBuffer-OutVariable
示例 1:启用密码套件

此命令启用名为TLS_DHE_DSS_WITH_AES_256_CBC_SHA的密码套件。此命令将密码套件 TLS 密码套件列表添加为最低优先级。

  1. PS C:\> Enable-TlsCipherSuite -Name "TLS_DHE_DSS_WITH_AES_256_CBC_SHA"
示例 2:启用密码套件作为最低优先级

此命令启用名为TLS_DHE_DSS_WITH_AES_256_CBC_SHA的密码套件。此命令将密码套件 TLS 密码套件列表添加为最低优先级。与第一个示例不同,此命令显式指定位置编号4294967295,它是CRYPT_PRIORITY_BOTTOM的值。

  1. PS C:\> Enable-TlsCipherSuite -Name "TLS_DHE_DSS_WITH_AES_256_CBC_SHA" -Position 4294967295
示例 3:启用密码套件作为最高优先级

此命令启用名为TLS_DHE_DSS_WITH_AES_256_CBC_SHA的密码套件。此命令将密码套件添加到位置 0 的 TLS 密码套件列表,这是最高优先级。

  1. PS C:\> Enable-TlsCipherSuite -Name "TLS_DHE_DSS_WITH_AES_256_CBC_SHA" -Position 0

四、禁用密码套件


使用命令Disable-TlsCipherSuite禁用 TLS 密码套件。

语法:
  1. Disable-TlsCipherSuite [-Name] <String> [ <CommonParameters>]
参数:
  • [-Name] <String> 必选参数。指定要禁用的 TLS 密码套件的名称。
  • [<CommonParameters>] 非必选参数。固定参数:-Verbose-Debug-ErrorAction-ErrorVariable-OutBuffer-OutVariable
示例 1:禁用密码套件

此命令禁用名为TLS_RSA_WITH_3DES_EDE_CBC_SHA的密码套件。该命令从 TLS 协议密码套件列表中删除密码套件。

  1. PS C:\> Disable-TlsCipherSuite -Name "TLS_RSA_WITH_3DES_EDE_CBC_SHA"
注意

如果禁用某个密码套件后,当你再次获取密码套件列表时Get-TlsCipherSuite,将不会出现在列表里,已禁用的密码套件也没有命令可以查询,你只能去查看微软文档,查看当前系统支持的密码套件列表,获取密码套件名称后,再次启用Enable-TlsCipherSuite -Name "密码套件全名"。微软文档链接:Cipher Suites in TLS/SSL (Schannel SSP)

五、其他版本 Windows 系统密码套件


在 Windows 10 和 Windows Server 2016 之前的版本系统中,微软没有给出 PowerShell 操作命令,但在微软文档中给出了,使用 C++ 调用函数,操作密码套件;如果感觉 C++ 麻烦也可以使用 Microsoft 管理控制台中的“组策略对象”管理单元配置 SSL Cipher Suite 订单组策略设置来修改密码套件列表。以上这些,都在微软文档中有提到,微软文档链接:Prioritizing Schannel Cipher Suites

另外,在 Stack Overflow 上有人问如何使用 C# 调用 Schannel 函数,操作密码套件。将微软文档中提到的,用 C++ 获取密码套件列表的代码,改成使用 C# 代码获取密码套件列表,并且成功了。Stack Overflow 链接:How to Call Schannel Functions from .Net/C#

C# 代码如下:

  1. using System;
  2. using System.Text;
  3. using System.Runtime.InteropServices;
  4. namespace ConsoleApplication1
  5. {
  6. class Program
  7. {
  8. [DllImport("Bcrypt.dll", CharSet = CharSet.Unicode)]
  9. static extern uint BCryptEnumContextFunctions(uint dwTable, string pszContext, uint dwInterface, ref uint pcbBuffer, ref IntPtr ppBuffer);
  10. [DllImport("Bcrypt.dll")]
  11. static extern void BCryptFreeBuffer(IntPtr pvBuffer);
  12. [DllImport("Bcrypt.dll", CharSet = CharSet.Unicode)]
  13. static extern uint BCryptAddContextFunction(uint dwTable, string pszContext, uint dwInterface, string pszFunction, uint dwPosition);
  14. [DllImport("Bcrypt.dll", CharSet = CharSet.Unicode)]
  15. static extern uint BCryptRemoveContextFunction(uint dwTable, string pszContext, uint dwInterface, string pszFunction);
  16. [StructLayout(LayoutKind.Sequential)]
  17. public struct CRYPT_CONTEXT_FUNCTIONS
  18. {
  19. public uint cFunctions;
  20. public IntPtr rgpszFunctions;
  21. }
  22. const uint CRYPT_LOCAL = 0x00000001;
  23. const uint NCRYPT_SCHANNEL_INTERFACE = 0x00010002;
  24. const uint CRYPT_PRIORITY_TOP = 0x00000000;
  25. const uint CRYPT_PRIORITY_BOTTOM = 0xFFFFFFFF;
  26. public static void DoStuff()
  27. {
  28. uint cbBuffer = 0;
  29. IntPtr ppBuffer = IntPtr.Zero;
  30. uint Status = BCryptEnumContextFunctions(
  31. CRYPT_LOCAL,
  32. "SSL",
  33. NCRYPT_SCHANNEL_INTERFACE,
  34. ref cbBuffer,
  35. ref ppBuffer);
  36. if (Status == 0)
  37. {
  38. CRYPT_CONTEXT_FUNCTIONS functions = (CRYPT_CONTEXT_FUNCTIONS)Marshal.PtrToStructure(ppBuffer, typeof(CRYPT_CONTEXT_FUNCTIONS));
  39. Console.WriteLine(functions.cFunctions);
  40. IntPtr pStr = functions.rgpszFunctions;
  41. for (int i = 0; i < functions.cFunctions; i++)
  42. {
  43. Console.WriteLine(Marshal.PtrToStringUni(Marshal.ReadIntPtr(pStr)));
  44. pStr += IntPtr.Size;
  45. }
  46. BCryptFreeBuffer(ppBuffer);
  47. }
  48. }
  49. static void Main(string[] args)
  50. {
  51. DoStuff();
  52. Console.ReadLine();
  53. }
  54. }
  55. }

六、参考文献


(完)