【Git笔记】"error:0D0890A1:asn1 encoding routines:ASN1_verify:unknown message digest algorithm"的解决方法

       备注:本笔记所描述的问题的前提是机器上已安装成功git且通过配置ca证书支持以https方式获取远程仓库,如果使用git时碰到这篇文章描述的问题,那么按那篇文章给出的办法解决即可。

最近从github clone repo时,git clone命令报错如下(以vim代码补全插件youcompleteme为例):

$ git clone https://github.com/Valloric/YouCompleteMe.git
Cloning into 'YouCompleteMe'...
fatal: unable to access 'https://github.com/Valloric/YouCompleteMe.git/': error:0D0890A1:asn1 encoding routines:ASN1_verify:unknown message digest algorithm

由于git底层是用本机安装的curl去fetch远程repo的,所以我们可以打开curl调试选项查看具体的错误:

$ export GIT_CURL_VERBOSE=1
$ git clone https://github.com/Valloric/YouCompleteMe.git
Cloning into 'YouCompleteMe'...
* Couldn't find host github.com in the .netrc file, using defaults
* About to connect() to github.com port 443
*   Trying 192.30.252.129... * connected
* Connected to github.com (192.30.252.129) port 443
* successfully set certificate verify locations:
*   CAfile: /home/slvher/tools/https-ca/github-ca/ca-bundle.crt
  CApath: none
* error:0D0890A1:asn1 encoding routines:ASN1_verify:unknown message digest algorithm
* Closing connection #0
fatal: unable to access 'https://github.com/Valloric/YouCompleteMe.git/': error:0D0890A1:asn1 encoding routines:ASN1_verify:unknown message digest algorithm

从verbose输出可知,git已经借助curl成功连接上github.com,但以https方式clone remote repo时,由于本地配置的CAfile无法识别github提供的ssl认证算法,所以本次session失败退出。

从stackoverflow的这个帖子(Can not use “git pull” beacause of some error)得知,github在https的ssl认证中,采用的是sha256算法,而这个sha256算法是openssl从version
0.9.8o才引入的。

用下面的命令验证我机器(公司统一的开发环境)上openssl的版本,发现居然是0.9.7a,这个版本不支持github采用的sha256算法,真心蛋疼。。。

$ python -c 'import ssl; print ssl.OPENSSL_VERSION'
OpenSSL 0.9.7a Feb 19 2003

既然git clone报错的原因已清楚,解决思路就明确了,可以执行下面的步骤进行修复。

1. 更新机器上的openssl库至v0.9.8o或更高版本

       a. 从openssl官网下载合适的版本,例如我下载的是openssl-1.0.1j.tar.gz

b. 解压上步下载的压缩包,cd至解压目录

c. 在当前shell终端执行以下命令

$ export CFLAGS="-fPIC"
$ ./config shared --openssldir=/home/slvher/tools/openssl-1.0.1j/  ## 无root权限,故由openssldir指定自定义安装路径
$ make depend
$ make all
$ make install

openssl源码编译/安装成功后,可在openssldir指定的目录下看到下面的目录结构

$ ls
bin  certs  include  lib  man  misc  openssl.cnf  private

我们需要的共享库libssl.so文件在lib目录下。

备注1:更新版本时需注意曾在2014年4月爆发的针对openssl version 1.0.1的heartbleed漏洞,所以需要下载openssl ver 1.0.1g或更高版本。

备注2:这步安装openssl至非系统默认目录是由于我没有root权限,不能覆盖系统默认的openssl版本,而且冒然升级也可能影响到机器上其他用户。这也直接导致本文的解决方法还需要完成下面3个步骤。

2. 重新编译curl或替换curl依赖的openssl共享库

显然,相比于重新源码编译curl,直接替换curl依赖的libssl.so更方便,借助LD_PRELOAD即可实现目的:

$ export LD_PRELOAD=/home/slvher/tools/openssl-1.0.1j/lib/libssl.so:/home/slvher/tools/openssl-1.0.1j/lib/libcrypto.so
$ python -c 'import ssl; print ssl.OPENSSL_VERSION' ## 验证是否替换成功,我机器的输出为OpenSSL 1.0.1j 15 Oct 2014,可见成功替换

3. 验证git clone是否能成功执行

$ git clone https://github.com/Valloric/YouCompleteMe.git
Cloning into 'YouCompleteMe'...
remote: Counting objects: 29685, done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 29685 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (29685/29685), 28.81 MiB | 5.77 MiB/s, done.
Resolving deltas: 100% (9501/9501), done.
Checking connectivity... done.

至此,目的达成。世界真美妙 ^_^

4. 将替换openssl库的过程自动化

       第2步通过设置环境变量LD_PRELOAD实现了更新curl依赖的libssl.so共享库版本的目的。但这个替换动作只对当前终端的session有效,当该session窗口关闭或切换到其它窗口时,执行git clone还是会出错。

将这种替换操作自动化的一个方法是在~/.bash_profile中将LD_PRELOAD设置为新版libssl.so的路径并export该变量。但这种方式可能会影响当前用户下的所有模块。

这里我借助bash的alias命令对git clone的动作做改写:

1) 打开~/.bashrc文件

2) 给git命令设置alias

alias git='export LD_PRELOAD=/home/slvher/tools/openssl-1.0.1j/lib/libssl.so:/home/slvher/tools/openssl-1.0.1j/lib/libcrypto.so; git'

3) 保存退出

4) 在其他终端窗口执行source ~/.bashrc

5) 在该窗口验证git clone是否正常,可以验证,alias设置是成功的

至此,终于大功告成。

【参考资料】

1. stackoverflow: Can not use “git pull” beacause of some error

2. OpenSSL Doc: Compilation and Installation

3. wikipedia: Heartbleed

========================= EOF =========================

时间: 2024-12-19 14:47:22

【Git笔记】"error:0D0890A1:asn1 encoding routines:ASN1_verify:unknown message digest algorithm"的解决方法的相关文章

Mysql添加用户错误:ERROR 1364 (HY000): Field 'ssl_cipher' doesn't have a default value解决方法

添加用户 insert into mysql.user(Host,User,Password) values("localhost","test",password("1234")); 报以下的错误 ERROR 1364 (HY000): Field 'ssl_cipher' doesn't have a default value错误 mysql5.1以上版本,我是在5.6版本上操作的. 错语原因: mysql用户表的中某些字段不能为空,没有默

error opening trace file: No such file or directory (2)错误解决方法

在练习项目的时候报错    error opening trace file: No such file or directory (2)字面意思是找不到文件,实际上也就是找不到文件,查了其他人的解决方法后还是没解决.突然想到新版本的创建布局文件的时候都有两个一个是文件名命名的xml布局文件另一个是,如上图示,当不与java代码交互的时候布局文件写入fragment_main.xml显示没问题,当涉及到与java代码交互时必须放到activity_main.xml中,否则就会抱错,然后程序意外停

[mysql]ERROR 1364 (HY000): Field 'ssl_cipher' doesn't have a default value 解决方法

在MySQL数据库中的mysql.user表中使用insert语句添加新用户时,可能会出现以下错误: ERROR 1364 (HY000): Field 'ssl_cipher' doesn't have a default value 原因是在my.ini配置文件中有这样一条语句 sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES 指定了严格模式,为了安全,严格模式禁止通过insert 这种形式直接修改mysql库中的user表进行添加新用户

NDK编译c包含C++头文件 error: unknown type name 'class' 的解决方法

在进行native开发的时候,难免会遇到C文件包含C++头文件而调用C++函数,若没做什么处理,直接include进行编译的话,会遇到以下错误: error: unknown type name 'class' error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token 那么怎么解决呢? 首先,找下报错的原,从C以及C++特性不难发现:C文件include了带有C++关键字的头文件,如class等,因此,包含C

git提交过程中遇到的 index.lock 问题导致无法提交的解决方法

在提交代码的过程中,可能会遇到下面的问题: fatal: Unable to create 'C:/programLists/zzw-q1/.git/index.lock': File exists. If no other git process is currently running, this probably means a git process crashed in this repository earlier. Make sure no other git process is

syntax error near unexpected token(关于跨平台非法字符(^M)的解决方法)

别人写了一个shell拿过来在linux试用,执行报错如下: 仔细查找了还是没找到错误,一直都是报syntax error near unexpected token `{ 网上搜索了一下,找到了端倪,现在简单整理如下: 现在可以判断给我脚本的这位仁兄很有可能是在windows平台上编写的.使用vim -b命令查看文件内容如下: 每一行多了一个^M有木有? 那么接下来就要搞清楚这个^M是什么东东? long long long ago .....  老式的电传打字机使用两个字符来另起新行.一个字

ERROR: JDWP Unable to get JNI 1.2 environment的错误解决方法

在用java编程的时候,在debug模式下偶尔会出现下面的错误,jdk1.6.0-rc1: ERROR: JDWP Unable to get JNI 1.2 environment, jvm->GetEnv() return code = -2JDWP exit error AGENT_ERROR_NO_JNI_ENV(183): [http://www.cnblogs.com/../src/share/back/util.c:820] 解决方法: 在程序最后,main()函数中添加: Sys

error: two or more data types in declaration specifiers原因及解决方法

编译时报错: [plain] view plaincopyprint? error: <strong>two or more data types in declaration specifiers</strong> error: two or more data types in declaration specifiers 原因可能有两个: 1. 少了一个分号";",比如定义一个结构体时,在最后忘了加分号. 解决方法:加上分号即可. 2. 重复定义,比如:a

error: bad top line in state file /var/lib/logrotate.status 解决方法

发现日志切割并没有按计划执行,后来手动强制执行时,发现如下报错: [[email protected] logrotate.d]# logrotate -f httpd error: bad top line in state file /var/lib/logrotate.status [[email protected] logrotate.d]# 解决访求: 删除/var/lib/logrotate.status 这个文件即可解决. 解决后,最好再运行一下logrotate -f /etc