Simple tool to calc Golang module checksum of go.mod and module directory.
This README also describes how Golang go.sum calc hash from file conent.
Maybe this is the missing official doc for how Golang go.sum calc hash from file conent
- Github: https://github.com/gin-gonic/gin
- Example Version: v1.4.0
- CheckSum: https://sum.golang.org/lookup/github.com/gin-gonic/[email protected]
git clone https://github.com/gin-gonic/gin.git
git checkout v1.4.0go get -u github.com/vikyd/go-checksumgo-checksum relOrAbsPathOfGinDir/go.modwill print like:
file: /Users/viky/tmp/gin/go.mod
{
"Hash": "b1946b355a09fedc3865073bbeb5214de686542bbeaea9e1bf83cb3a08f66b99",
"HashBase64": "sZRrNVoJ/tw4ZQc7vrUhTeaGVCu+rqnhv4PLOgj2a5k=",
"HashSynthesized": "396d84667dc33bc2e7f6820a3af33ef8b04efb950f1c92431fbdbfabfdeb65d3",
"HashSynthesizedBase64": "OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM=",
"GoCheckSum": "h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM="
}
The output hash "GoCheckSum": "h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM="
is the same as
the online checksum: github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM=
(from here)
go-checksum relOrAbsPathOfGinDir github.com/gin-gonic/[email protected]- 1st param: module directory
- no need to remove .git, will ignore
- 2nd param: module prefix with version
- necessary for dir checksum
will print like:
directory: /Users/viky/tmp/gin
{
"HashSynthesized": "ded3280827ccee9a6ab11d29b73ff08b58a6a4da53efff7042d319f25af59824",
"HashSynthesizedBase64": "3tMoCCfM7ppqsR0ptz/wi1impNpT7/9wQtMZ8lr1mCQ=",
"GoCheckSum": "h1:3tMoCCfM7ppqsR0ptz/wi1impNpT7/9wQtMZ8lr1mCQ="
}
The output hash "GoCheckSum": "h1:3tMoCCfM7ppqsR0ptz/wi1impNpT7/9wQtMZ8lr1mCQ="
is the same as
the online checksum: github.com/gin-gonic/gin v1.4.0 h1:3tMoCCfM7ppqsR0ptz/wi1impNpT7/9wQtMZ8lr1mCQ=
(from here)
Steps:
- tell me the path of
go.mod - read content from
go.mod, as variablecontent - calc SHA256 hash from
content, as variablehash - mix some string with
hash, as variablemixedHash-
hash go.mod\n - if
hashis:CDa7N - then
mixedHashis: -
CDa7N go.mod\n - yeah, that's a strange string
-
- calc SHA256 hash from
mixedHash, as variablehashSynthesized - calc Base64 from
hashSynthesized, as variablehashSynthesizedBase64 - finally, in
go.sum, the string is:h1:hashSynthesizedBase64, as variableGoCheckSum- if
hashSynthesizedis:CCfM7 - then
GoCheckSumis:h1:CCfM7 h1: The hash begins with an algorithm prefix of the form "h:". The only defined algorithm prefix is "h1:", which uses SHA-256.h: hash
- if
Steps:
- tell me the path of
module's dirandmodule's prefix(also named import path)module's prefixis used to calc hash, as part of the content string
- clean the dir path, to remove duplicate path seperator etc.
- loop each file in
module's dir- only consider file, not dir
- find the relative path of the file (relative to
module's dir) - join file relative path with
module's prefix, as variablefileImportPath - example:
- one file in gin project:
gin.go - its module's dir:
/dir01/dir02/gin - its absolute path:
/dir01/dir02/gin/gin.go - its relative path:
gin.go - final string
fileImportPath:github.com/gin-gonic/[email protected]/gin.go
- one file in gin project:
- after the loop, we got a list
fileImportPathof all files, as variablefiles- except files in
.git
- except files in
- sort
filesas string in increasion order - then begin hash steps
- loop sorted
files- read content from a file of
files, as variablecontent - calc SHA256 hash from
content, as variablehash - mix some string with
hash, as variablemixedHash-
hash fileImportPath\n - if
hashis:CDa7N - if
fileImportPathis:github.com/gin-gonic/[email protected]/gin.go - then
mixedHashis: -
CDa7N github.com/gin-gonic/[email protected]/gin.go\n - yeah, that's a strange string
-
- read content from a file of
- after this loop, we can get a single long string joined by all files'
mixedHash, as variablemixedHashAll- example:
-
CDa7N github.com/gin-gonic/[email protected]/gin.go\nEFb8M github.com/gin-gonic/[email protected]/context.go\n ...
- calc SHA256 hash from
mixedHashAll, as variablehashSynthesized - calc Base64 from
hashSynthesized, as variablehashSynthesizedBase64 - finally, in
go.sum, the string is:h1:hashSynthesizedBase64, as variableGoCheckSum- if
hashSynthesizedis:CCfM7 - then
GoCheckSumis:h1:CCfM7 h1: The hash begins with an algorithm prefix of the form "h:". The only defined algorithm prefix is "h1:", which uses SHA-256.h: hash
- if
Golang source code about how to calc hash for modules: https://github.com/golang/mod/blob/release-branch.go1.15/sumdb/dirhash/hash.go