首页 > 其他分享 >【转载】go.sum中特殊hash如何计算

【转载】go.sum中特殊hash如何计算

时间:2023-02-13 14:35:45浏览次数:58  
标签:文件 hash sum 计算 go mod

Golang为了依赖的安全考虑,在go.mod的基础上引入了go.sum,go.sum文件的作用主要是记录项目依赖的hash值,防止被人修改。

在分析具体项目的go.sum文件后可以发现go.sum中不仅记录了go.mod等的hash值,也记录了整个模块的hash值,这是为什么呢?

这样作的目的主要是在下载整个模块内部的时候可找到子依赖,使得可以并行下载多个依赖。

起初我以为go.sum中记录的hash值是通过sha256直接计算再进行base64编码后的结果,但是在实际操作验证时得到的base64值和go.sum中记录的总是对不上,因此通过查看go的源码(/usr/local/go/src/cmd/go/下面对/usr/local/go/src/cmd/vendor/golang.org/x/mod/sumdb/dirhash包下有引用依赖,这里也是实现go.sum的底层算法核心)发现Golang对文件的hash和整个项目的hash计算并不是简单的sha256计算和base64编码。

案例分析

cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
# 上面的大致意思是
<module> <version>/go.mod h1:<sha256hash+base64>
# 第一段是模块依赖路径
# 第二段是版本信息/具体文件
# 第三段是针对该文件内容计算的sha256哈希值再进行bash64编码的值
# 其中h1代表的意思就是sha256+base64
复制代码

特殊hash计算

go.mod的特殊hash计算

# 输入:go.mod的文件路径
# 步骤:
# 1.打开go.mod文件读取文件内容进行sha256哈希计算,得到sha256hash
# 2.构建新的字符串 base64in = "sha256hash  go.mod\n" ,中间用两个空格分隔,最后必须有一个环行符
# 3.将base64in作为输入给base64进行编码得到base64encode
# 4.字符串拼接得到go.sum中一样的结果 h1:base64encode
复制代码

go.mod的hash计算可以通过shell模拟得出结果,但是对于整个模块的hash计算就无能为力了,下面通过shell命令模拟上述过程

$ sha256sum go.mod 
5a93925e1efdeecd8b5755d089fdba6dfb3c04eb85447e8dec8b31cdb44203ab  go.mod    #sha256hash
$ vim base64in.txt  
5a93925e1efdeecd8b5755d089fdba6dfb3c04eb85447e8dec8b31cdb44203ab  go.mod   # base64in字符串,注意下面的环行符不能少,不然和Golang中的结果对不上

$ sha256sum base64in.txt  | xxd -r -ps | base64
+DbmgtsW3Ksw3QccfHlswRDLj07woKf4ku0C0xYA7u0=  #base64encode
# 最终的结果经过字符串拼接即可得到 h1:+DbmgtsW3Ksw3QccfHlswRDLj07woKf4ku0C0xYA7u0= 
#在写入go.sum时需要同时写上<module> <version>/go.mod h1:+DbmgtsW3Ksw3QccfHlswRDLj07woKf4ku0C0xYA7u0= 
复制代码

整个模块的特殊hash计算

对整个模块进行hash计算时不是直接对打包好的zip包求hash,而是对解压后的文件进行遍历hash计算后再进行一次总的hash计算,这样作的目的是避免因为zip算法进行打包时由于字节的差异导致对整个zip包的hash结果不一致

# 输入:模块所在目录和模块在的导入路径(在源码中使用时的那个导入路径)
# 步骤:
# 1. 遍历模块中所有文件
# 只考虑文件,不考虑目录
# 忽略.git目录内的所有文件
# 拼接每个文件相对路径与导入路径到一起
# 例如:导入路径 "github.com/spf13/cobra",该包中command.go文件经过拼接后为:github.com/spf13/cobra/command.go
# 将遍历的结果存储在一个列表中方便后面计算hash
# 2. 对上一步得到的列表进行排序 (排序主是保证hash结果一致)
# 3.然后进行遍历hash,其计算过程是在排序后的列表中读取一个文件进行sha256 hash 将"ha256hash github.com/spf13/cobra/command.go\n"字符串拼接在后一个文件hash结果前面,以此类推最后得到一个所有文件hash结果的字符串
# 4.对上面的长字符串再进行sha256 hash计算得到结果sha256hash进行base64编码得到base64encode
# 5.在写入go.sum时类似如下:
github.com/spf13/cobra v1.1.3 h1:xghbfqPkxzxP3C/f3n5DdpAbdKLj4ZE4BWQI362l53M=
github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo=
# 第一行是对整个包的hash结果
# 第二行是对go.mod的hash结果
复制代码

上面的过程都可以在Golang源码中找到,在github找到了一位大神也对这种特殊的hash进行了复现:hub.fastgit.org/vikyd/go-ch…

标签:文件,hash,sum,计算,go,mod
From: https://www.cnblogs.com/acodedreamer/p/17116208.html

相关文章

  • Calling C++ Code From Go With SWIG
    http://zacg.github.io/blog/2013/06/06/calling-c-plus-plus-code-from-go-with-swig/ RecentlywhileworkingonaGobasedprojectIneededtousesomefunctio......
  • redis数据结构介绍和redis命令操作string&hash
    redis的数据结构:*redis存储的是:key,value格式的数据,其中key都是字符串,value有5种不同的数据结构*value的数据结构:(1)字符串类型string(2......
  • 【问题讨论】关于golang调用so的问题的讨论
    runtime:dlopen/dlsymwithoutCGo#18296 Open  iamacarpetopenedthisissueDec13,2016·12comments  Open  ......
  • go连接kafka
    Part1前言本文主要介绍如何通过go语言连接kafka。这里采用的是sarama库。​​https://github.com/Shopify/sarama​​Part2库的安装goget-ugithub.com/Shopify/saramago......
  • JAVA - - - HashMap常见问题解答
    HashMap与ConcurrentHashMap的异同都是key-value形式的存储数据;HashMap是线程不安全的,ConcurrentHashMap是JUC下的线程安全的;HashMap底层数据结构是数组+......
  • golang 切片 slice
    1.基本介绍切片是数组的一个引用,因此切片是引用类型。切片的使用与数组类似,遍历,访问切片元素等都一样。切片是长度是可以变化的,因此切片可以看做是一个动态数组。slice内......
  • MixGo CE及外接模块管脚简单介绍
    之前用习惯了Arduino系列的板卡,也习惯了上面的管脚使用方法,换成MixGo系列的板卡,都是TypeC接口,这个管脚应该怎么看呢?MixGo系列的外接模块管脚又是怎么看,程序里面应该怎么......
  • 10 Django中间件
    Django中间件中间件介绍django中间件类似于是django的保安,请求来的时候需要先经过中间件才能到达django后端,响应走的时候也需要经过中间件才能到达web服务网关接口dja......
  • 06 Django与Ajax
    Django与Ajax什么是JSONJSON是轻量级的文本数据交换格式,JSON使用JavaScript语法来描述数据对象,但是JSON仍然独立于语言和平台。JSON解析器和JSON库支持许多不......
  • 01 Django简介
    前戏Wsgiref模块封装了socket代码请求来的时候将http数据格式拆封成一个大字典响应走的时候将数据打包成符合http协议要求的数据格式#模块封装了socket代码并将请求......