作者: Jim Wang 公众号: 巴博萨船长

摘要:如何解决pyenv的Windows版本pyenv-win在Windows 7中安装配置pyenv-win时,遇到的:: [ERROR] :: An error occurred in the support of the secure channel,为什么会存在secure protocol 安全协议的问题?如何在Window 7系统中开启TLS 1.0和 TSL 2.0两个协议,什么是SChannel ?如何设置pyenv版本列表中的system选项?mlink命令中的/f与/d的区别是什么?

Abstract: How to solve the problem of pyenv-win when installing and configuring pyenv-win in Windows 7:: [ERROR] :: An error occurred in the support of the secure channel, why there is a secure protocol problem? ? How to enable TLS 1.0 and TSL 2.0 in Window 7 system, what is SChannel? How to set the system option in the pyenv version list? What is the difference between /f and /d in the mlink command?

作者: Jim Wang 公众号: 巴博萨船长

所遇问题

在Windows 系统中在尝试安装配置pyenv-win时,在使用pyenv install命令安装其他Python版本的时候,有可能碰见如下问题。或者只有我不幸遇见了这个问题,这篇文章可以帮助你解决这个问题。

1
2
3
4
5
6
C:\Users\nobody>pyenv install 3.9.4
:: [Info] :: Mirror: https://www.python.org/ftp/python
:: [Downloading] :: 3.9.4 ...
:: [Downloading] :: From https://www.python.org/ftp/python/3.9.4/python-3.9.4-amd64-webinstall.exe
:: [Downloading] :: To C:\Users\nobody\.pyenv\pyenv-win\install_cache\python-3.9.4-amd64-webinstall.exe
:: [ERROR] :: Im Support des sicheren Channels ist ein Fehler aufgetreten

由于当前系统为德语版,错误提示信息为:

1
:: [ERROR] :: Im Support des sicheren Channels ist ein Fehler aufgetreten

该错误问题的英文翻译为:

1
:: [ERROR] :: An error occurred in the support of the secure channel

问题原因

该问题出现原因的关键字为,secure protocol 即安全协议,具体为当前系统为对传输层(Transport Layer Security )TLS 1.0 和TLS 2.0 这两个协议提供支持。一些应用和服务在开发是,被设计成,为了实现安全套接字连接,会选择使用WinHTTP,使用WinHTTP时,会选择使用WINHTTP_OPTION_SECURE_PROTOCOLS这个标识符,可改标识符的定义不包含对TLS 1.0 和TLS 2.0 协议的使用。Windows 7 允许通过设置一个名为DefaultSecureProtocol 的注册表键的值,来控制WINHTTP_OPTION_SECURE_PROTOCOLS这个标识符的定义,即定义当程序WINHTTP_OPTION_SECURE_PROTOCOLS时,Windows系统应该为其开启那些协议(或Windows 系统应视为该标识符支持的协议应为什么),具体参见Update to enable TLS 1.1 and TLS 1.2 as default secure protocols in WinHTTP in Windows这篇官方文章。

在Windows系统中,DefaultSecureProtocol 合法值和其对应含义如下表所示。

合法值 值的含义
0x00000008 默认开启SSL 2.0
0x00000020 默认开启SSL 3.0
0x00000080 默认开启 TLS 1.0
0x00000200 默认开启 TLS 1.1
0x00000800 默认开启 TLS 1.2

举例来说,如果我们想为WINHTTP_OPTION_SECURE_PROTOCOLS这个标识同时开启TLS 1.1 和 TLS1.2的支持,那么我们需要将0x00000200 与0x00000800相加,其结果应为0x00000a00。我们将DefaultSecureProtocol 的值设置为0x00000a00,就可以同时开始TLS 1.1 和 TLS1.2这两个协议。

解决方法

第一步,检查注册表,如有必要添加DefaultSecureProtocol键并设置响应的值。

DefaultSecureProtocol 这个注册表的键,在32位的Windows系统位于,

1
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings\WinHttp

如下图所示。

image-20210619142132677

在64位的Windows系统位于,

1
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Internet Settings\WinHttp

64位系统

image-20210619142014086

需要注意的是,如果注册表默认没有DefaultSecureProtocol 这个键,在64位Window系统中,要在以上两处添加这个键,并设置相应的合法值,值的类型为DWORD。

也可以使用Windows官方提供的快速工具Easy Fix 来实现上述键值的自动添加。下载链接:https://download.microsoft.com/download/0/6/5/0658B1A7-6D2E-474F-BC2C-D69E5B9E9A68/MicrosoftEasyFix51044.msi。

该工具除了在WinHttp这个键下(在64位系统中,注册表的上述两处位置),添加DefaultSecureProtocol 这个键和默认值0x00000a00。还会将在下列两处位置添加一个名为SecureProtocol的新键和默认值0x00000a00,以开启IE浏览器对TLS 1.1 和 TLS 1.2两个协议的支持。两处位置如下:

1
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings
1
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings

添加后的结果如下图所示:

image-20210619150914631

第二步,在Windows 7上开启SChannel组件级别的TLS 1.0和TLS 1.2两个协议的支持

SChannel也被称为Secure Channel 23,是一个windows子系统,当windows应用程序想要做任何与TLS相关的事情时,比如与远程服务器建立一个加密会话,或接受来自客户端的TLS连接,就会使用Schannel,从体系来看,SChannel实现了Security Support Provider Interface (SSPI)接口,是微软提供的SSP包之一。SSP包还包括CredSSP、Negotiate、NTLM、Kerberos和Digest24等等。

SChannel使用示例:

HTTPS连接

由IE,Edge,powershell的InvokeWebRequest发起的 由IIS web server收到的

RDP连接

客户端的mstsc.exe 服务器上的终端服务(svchost.exe中的termsrv.dll)

微软官方文档TLS-SSL设置一文提到,若要在Windows 7系统上协商和启用TLS 1.0和TLS 2.0的版本就需要在相应的子项中创建DisabledByDefault的子健,并将该键的值设置为设置0。

对于TLS 1.0,注册表位置:

1
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.1\Client

对于TLS 1.2,注册表位置:

1
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Client

添加之后结果应如下图所示。

image-20210619141719216

结果

当完成上述注册表的添加与修改后就可以尝试重新打开cmd,并使用命令pyenv install xxx 安装新的版本,我测试的结果如下:

1
2
3
4
5
6
7
C:\Users\nobody>pyenv install 3.7.9
:: [Info] :: Mirror: https://www.python.org/ftp/python
:: [Downloading] :: 3.7.9 ...
:: [Downloading] :: From https://www.python.org/ftp/python/3.7.9/python-3.7.9-amd64-webinstall.exe
:: [Downloading] :: To C:\Users\nobody\.pyenv\pyenv-win\install_cache\python-3.7.9-amd64-webinstall.exe
:: [Installing] :: 3.7.9 ...
:: [Info] :: completed! 3.7.9

检查安装结果如下:

1
2
C:\Users\nobody>pyenv versions
3.7.9

相比pyenv在其他系统如Linux 和Mac OS中,pyenv versions的结果少了一个system, 即表示系统预装,或者系统级别的Python版本,可以将系统安装的Python通过mklink /J或者mklink /D 命令创建一个快捷方式,即link,将系统安装的Python映射到pyevn的相关子目录,如下图,

1
2
C:\Users\nobody>mklink /J "C:\Users\nobody\.pyenv\pyenv-win\versions\system" "C:\Python27"
Connection created for C:\Users\nobody\.pyenv\pyenv-win\versions\system <<===>> C:\Python27

然后在使用pyenv versions检查已安装的版本,会得到如下结果:

1
2
3
C:\Users\nobody>pyenv versions
3.7.9
system

在使用pyenv global system·将系统安装的python版本设置为全局默认版本,再次使用pyenv versions检查已安装的版本,会得到如下结果:

1
2
3
C:\Users\nobody>pyenv versions
3.7.9
* system (set by C:\Users\nobody\.pyenv\pyenv-win\version)

小结

以上即为本人在Windows 7系统中安装和配置pyenv时所遇问题和找到的解决方案。上述接近问题的办法并非自己原创,部分内容来自官方文档,自己总结了一下,假如了一些扩展性的知识,文章是想作为自己学习的日志,方便自己日后回顾。上述内容仅为一家之言,并非最优,若读者有别的思路也欢迎关注我的个人微信公众号,一起讨论学习。

补充内容

mklink命令/d和/j参数的区别总结如下:

差异1,当创建时

  • /d 可以使用相对路径方式创建
  • /j 必须绝对路径方式创建

此区别意义不大,建议所有的mklink目录均用绝对路径创建

差异2,当复制和剪切时

  • 复制:/d /j 均生成源目录的内容副本,变为一般文件夹
  • 剪切/移动:
    • /d 生成的目录,移动到其他地方,仍旧保持链接。对源目录无影响,/d生成的目录消失
    • /j 生成的目录,移动到其他地方,会产生一个新的副本文件夹,源文件夹内容全部移至新普通文件夹内,源文件夹清空,源文件夹仍旧存在,/j生成的目录也依旧存在

差异3,当使用软件打开时

  • /d生成的目录,地址栏会跳到源目录位置。
  • /J生成的目录,地址栏不会跳到源目录位置。

版权声明:
文章首发于 Jim Wang's blog , 转载文章请务必以超链接形式标明文章出处,作者信息及本版权声明。