You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

filehash.go 2.3 kB

10 months ago
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. package cdssdk
  2. import (
  3. "crypto/sha256"
  4. "encoding/hex"
  5. "fmt"
  6. "strings"
  7. )
  8. // 文件的哈希值,格式:[前缀: 4个字符][哈希值: 64个字符]
  9. // 前缀用于区分哈希值的类型:
  10. //
  11. // - "Full":完整文件的哈希值
  12. //
  13. // - "Comp":将文件拆分成多个分片,每一个分片计算Hash之后再合并的哈希值
  14. //
  15. // 哈希值:SHA256哈希值,全大写的16进制字符串格式
  16. type FileHash string
  17. const (
  18. FullHashPrefix = "Full"
  19. CompositeHashPrefix = "Comp"
  20. EmptyHash = FileHash("Full0000000000000000000000000000000000000000000000000000000000000000")
  21. )
  22. func (h *FileHash) GetPrefix() string {
  23. return string((*h)[:4])
  24. }
  25. func (h *FileHash) GetHash() string {
  26. return string((*h)[4:])
  27. }
  28. // 由调用者保证Hash值有效
  29. func (h *FileHash) GetHashBytes() []byte {
  30. bytes, _ := hex.DecodeString(h.GetHash())
  31. return bytes
  32. }
  33. func (h *FileHash) GetHashPrefix(len int) string {
  34. return string((*h)[4 : 4+len])
  35. }
  36. func (h *FileHash) IsFullHash() bool {
  37. return (*h)[:4] == FullHashPrefix
  38. }
  39. func (h *FileHash) IsCompositeHash() bool {
  40. return (*h)[:4] == CompositeHashPrefix
  41. }
  42. func ParseHash(hashStr string) (FileHash, error) {
  43. if len(hashStr) != 4+64 {
  44. return "", fmt.Errorf("hash string length should be 4+64, but got %d", len(hashStr))
  45. }
  46. prefix := hashStr[:4]
  47. hash := hashStr[4:]
  48. if prefix != FullHashPrefix && prefix != CompositeHashPrefix {
  49. return "", fmt.Errorf("invalid hash prefix: %s", prefix)
  50. }
  51. if len(hash) != 64 {
  52. return "", fmt.Errorf("invalid hash length: %d", len(hash))
  53. }
  54. for _, c := range hash {
  55. if (c < '0' || c > '9') && (c < 'A' || c > 'F') {
  56. return "", fmt.Errorf("invalid hash character: %c", c)
  57. }
  58. }
  59. return FileHash(hashStr), nil
  60. }
  61. func NewFullHash(hash []byte) FileHash {
  62. return FileHash(FullHashPrefix + strings.ToUpper(hex.EncodeToString(hash)))
  63. }
  64. func NewFullHashFromString(hashStr string) FileHash {
  65. return FileHash(FullHashPrefix + strings.ToUpper(hashStr))
  66. }
  67. func CalculateCompositeHash(segmentHashes [][]byte) FileHash {
  68. data := make([]byte, len(segmentHashes)*32)
  69. for i, segmentHash := range segmentHashes {
  70. copy(data[i*32:], segmentHash)
  71. }
  72. hash := sha256.Sum256(data)
  73. return FileHash(CompositeHashPrefix + strings.ToUpper(hex.EncodeToString(hash[:])))
  74. }