Python 杂记之 解决Win 7中安装与配置pyenv-win时因secure channel错误所引起的问题
作者: 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 | C:\Users\nobody>pyenv install 3.9.4 |
由于当前系统为德语版,错误提示信息为:
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 |
如下图所示。
在64位的Windows系统位于,
1 | HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Internet Settings\WinHttp |
64位系统
需要注意的是,如果注册表默认没有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 |
添加后的结果如下图所示:
第二步,在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 |
添加之后结果应如下图所示。
结果
当完成上述注册表的添加与修改后就可以尝试重新打开cmd,并使用命令pyenv install xxx
安装新的版本,我测试的结果如下:
1 | C:\Users\nobody>pyenv install 3.7.9 |
检查安装结果如下:
1 | C:\Users\nobody>pyenv versions |
相比pyenv在其他系统如Linux 和Mac OS中,pyenv versions
的结果少了一个system, 即表示系统预装,或者系统级别的Python版本,可以将系统安装的Python通过mklink /J
或者mklink /D
命令创建一个快捷方式,即link,将系统安装的Python映射到pyevn的相关子目录,如下图,
1 | C:\Users\nobody>mklink /J "C:\Users\nobody\.pyenv\pyenv-win\versions\system" "C:\Python27" |
然后在使用pyenv versions
检查已安装的版本,会得到如下结果:
1 | C:\Users\nobody>pyenv versions |
在使用pyenv global system
·将系统安装的python版本设置为全局默认版本,再次使用pyenv versions
检查已安装的版本,会得到如下结果:
1 | C:\Users\nobody>pyenv versions |
小结
以上即为本人在Windows 7系统中安装和配置pyenv时所遇问题和找到的解决方案。上述接近问题的办法并非自己原创,部分内容来自官方文档,自己总结了一下,假如了一些扩展性的知识,文章是想作为自己学习的日志,方便自己日后回顾。上述内容仅为一家之言,并非最优,若读者有别的思路也欢迎关注我的个人微信公众号,一起讨论学习。
补充内容
mklink命令/d和/j参数的区别总结如下:
差异1,当创建时
- /d 可以使用相对路径方式创建
- /j 必须绝对路径方式创建
此区别意义不大,建议所有的mklink目录均用绝对路径创建
差异2,当复制和剪切时
- 复制:/d /j 均生成源目录的内容副本,变为一般文件夹
- 剪切/移动:
- /d 生成的目录,移动到其他地方,仍旧保持链接。对源目录无影响,/d生成的目录消失
- /j 生成的目录,移动到其他地方,会产生一个新的副本文件夹,源文件夹内容全部移至新普通文件夹内,源文件夹清空,源文件夹仍旧存在,/j生成的目录也依旧存在
差异3,当使用软件打开时
- /d生成的目录,地址栏会跳到源目录位置。
- /J生成的目录,地址栏不会跳到源目录位置。
文章首发于 Jim Wang's blog , 转载文章请务必以超链接形式标明文章出处,作者信息及本版权声明。