在Git中,每个commit ID的信息(如cc127537978af35e2f502da7e8d22e340ed810e5)就是一个SHA-1 Hash值,它是对那个commit是Git仓库中内容和头信息(Header)的一个校验和(checksum)。Linux kernel开创者和Git的开发者——Linus说,Git使用了SHA-1并非是为了安全性,而是为了数据的完整性;它可以保证,在很多年后,你重新checkout某个commit时,一定是它多年前的当时的状态,完全一摸一样,完全值得信任。
在Git中,根据commit的SHA-1值(40个十六进制数字)进行了简单的划分目录,以前2位数字作为目录名,其下面是剩余38位数字组成的一个文件名,以我的一个backup.git代码仓库为例,演示如下。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
[root@jay-linux objects]# pwd /home/repo/backup.git/objects [root@jay-linux objects]# ls 00 0b 17 20 29 32 3b 45 4d 57 5f 68 74 7e 88 93 9c a4 ad b7 c2 ce da e6 ef f9 pack 01 0c 19 21 2a 33 3c 46 4e 58 61 6a 75 7f 89 94 9d a5 ae b9 c3 d0 db e7 f0 fa 02 0d 1a 22 2b 34 3f 47 4f 59 62 6d 76 82 8a 96 9e a6 af ba c4 d1 dc e8 f3 fb 03 0e 1b 24 2c 35 40 48 50 5a 63 6e 78 83 8b 97 9f a8 b0 bc c5 d2 dd e9 f4 fc 04 0f 1c 25 2d 37 41 49 52 5b 64 6f 79 84 8d 98 a0 a9 b1 bd c8 d5 df ea f5 fd 06 13 1d 26 2e 38 42 4a 54 5c 65 71 7b 85 8e 99 a1 aa b2 be ca d7 e1 eb f6 fe 07 14 1e 27 30 39 43 4b 55 5d 66 72 7c 86 91 9a a2 ab b4 c0 cb d8 e3 ec f7 ff 0a 15 1f 28 31 3a 44 4c 56 5e 67 73 7d 87 92 9b a3 ac b5 c1 cc d9 e4 ee f8 info [root@jay-linux objects]# cd cc [root@jay-linux cc]# ls drwxrwxr-x 2 repo repo 4096 Jun 19 11:10 . drwxr-xr-x 211 repo repo 4096 Jun 19 11:10 .. -r--r--r-- 1 repo repo 695 Jun 19 11:10 127537978af35e2f502da7e8d22e340ed810e5 [root@jay-linux cc]# str=127537978af35e2f502da7e8d22e340ed810e5 [root@jay-linux cc]# echo "${#str} is the length of $str" 38 is the length of 127537978af35e2f502da7e8d22e340ed810e5 |
SHA-1是一种加密哈希函数(cryptographic hash function),另外两种SHA(secure hash algorithm)算法是SHA-0和SHA-2。SHA-1将文件中的内容通过其hash算法生成一个160bit的报文摘要,即40个十六进制数字(每个十六进制数字占4位)。它几乎可以保证,如果两个文件的SHA-1值是相同的,那么它们确是完全相同的内容(类似于生活中的指纹识别);不过也不是绝对的安全可靠,最新资料显示,理论上对其进行哈希碰撞(hash collision,不同的两块数据有相同的hash值)的攻击可以在2^51(2的51次方)左右的次数内实现。(BTW,国内也有对密码攻击研究深入的学者,我就看到wikipedia上经常提到山东大学的王小云[Wang Xiaoyun]教授,有兴趣研究密码破译攻击的,可以google其论文来读读。)由于SHA-1不是足够的安全,现在美国的很多政府部门都开始不采用SHA-1而采用SHA-2(256/224/512/384等多种长度的输出报文摘要,目前还没有发现其hash碰撞的存在)。SHA-1主要有两种用途,一个是加密,一个是数据完整性校验。
另外,哈希函数是一种将大的变长的数据集映射到一个固定长度的较小数据集的算法。A hash function is any algorithm or subroutine that maps large data sets of variable length, called keys, to smaller data sets of a fixed length. 哈希函数的返回值,被称为哈希值、哈希编码、哈希和、校验和或者就叫做哈希(hash values, hash codes, hash sums, checksums or simply hashes.)常见的Hash算法还有我们很熟悉的MD5(可以用md5sum工具计算),MD5是128bit的报文摘要(密文)。
在加密(如SHA-1算法)中,源数据一点儿的差异将会得到完全不同的加密后的密码(如SHA-1值),这种现象叫做“雪崩效应”(Avalanche effect)。
在Linux中的“coreutils”软件包中就包含了SHA相关的工具,进行一些简单的演示如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
[root@jay-linux jay]# ls /usr/bin/sha* /usr/bin/sha1hmac /usr/bin/sha224sum /usr/bin/sha256sum /usr/bin/sha384sum /usr/bin/sha512sum /usr/bin/shasum /usr/bin/sha1sum /usr/bin/sha256hmac /usr/bin/sha384hmac /usr/bin/sha512hmac /usr/bin/sharesec [root@jay-linux jay]# rpm -qf /usr/bin/sha1sum coreutils-8.4-19.el6.x86_64 [root@jay-linux jay]# rpm -qf /usr/bin/sha512sum coreutils-8.4-19.el6.x86_64 [root@jay-linux jay]# sha1sum - hello, world. 9de0915f4c007cc4f15f1b7b87a1010c60816ee5 - [root@jay-linux jay]# sha1sum - Hello, world. 01ba98b3c90126f14577d5b1fdb1ffe9d3364469 - [root@jay-linux jay]# echo "hello, world." | sha1sum 9de0915f4c007cc4f15f1b7b87a1010c60816ee5 - [root@jay-linux jay]# echo "Hello, world." | sha1sum 01ba98b3c90126f14577d5b1fdb1ffe9d3364469 - |
本来是简单了解一下Git中commit(SHA-1值),忽然思维发散,多理解了一些加密、哈希相关的东西,简记为此文吧。
欲了解更多,请参考如下网页: