hdwal.go 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. package hd
  2. import (
  3. "crypto/rand"
  4. "crypto/sha256"
  5. "encoding/binary"
  6. "fmt"
  7. "io"
  8. "math"
  9. "strconv"
  10. "time"
  11. "github.com/shirou/gopsutil/cpu"
  12. "github.com/shirou/gopsutil/mem"
  13. "github.com/shirou/gopsutil/net"
  14. "github.com/tyler-smith/go-bip39"
  15. )
  16. type MnemonicType int
  17. const (
  18. Mnemonic12 MnemonicType = iota
  19. Mnemonic24
  20. )
  21. func (m MnemonicType) String() string {
  22. switch m {
  23. case Mnemonic12:
  24. return "12 mnemonics"
  25. case Mnemonic24:
  26. return "24 mnemonics"
  27. }
  28. panic("Unexpected MnemonicType")
  29. }
  30. func entropy(mt MnemonicType) ([]byte, error) {
  31. randomBytes := make([]byte, 0)
  32. cpuPercent, _ := cpu.Percent(time.Second, false)
  33. memory, _ := mem.VirtualMemory()
  34. ioCounters, _ := net.IOCounters(true)
  35. netWork := strconv.Itoa(int(ioCounters[0].BytesSent + ioCounters[0].BytesRecv))
  36. cRandBytes := make([]byte, 32)
  37. if _, err := io.ReadFull(rand.Reader, cRandBytes); err != nil {
  38. return []byte{}, err
  39. }
  40. randomBytes = append(randomBytes, cRandBytes...)
  41. randomBytes = append(randomBytes, float64ToByte(cpuPercent[0])...)
  42. randomBytes = append(randomBytes, float64ToByte(memory.UsedPercent)...)
  43. randomBytes = append(randomBytes, []byte(netWork)...)
  44. random := sha256.Sum256(randomBytes)
  45. switch mt {
  46. case Mnemonic12:
  47. return random[:16], nil
  48. case Mnemonic24:
  49. return random[:32], nil
  50. default:
  51. return nil, fmt.Errorf("MnemonicType err: %d", mt)
  52. }
  53. }
  54. func NewMnemonic(mt MnemonicType) (string, error) {
  55. entropyBytes, err := entropy(mt)
  56. if err != nil {
  57. return "", err
  58. }
  59. mnemonic, err := bip39.NewMnemonic(entropyBytes)
  60. if err != nil {
  61. return "", err
  62. }
  63. return mnemonic, nil
  64. }
  65. func CheckMnemonic(mnemonic string) bool {
  66. return bip39.IsMnemonicValid(mnemonic)
  67. }
  68. func GenerateSeedFromMnemonic(mnemonic, password string) ([]byte, error) {
  69. seedBytes, err := bip39.NewSeedWithErrorChecking(mnemonic, password)
  70. if err != nil {
  71. return []byte{}, err
  72. }
  73. return seedBytes, nil
  74. }
  75. func GetExtendSeedFromPath(path string, seed []byte) ([]byte, error) {
  76. extendedKey, err := NewMaster(seed)
  77. if err != nil {
  78. return nil, err
  79. }
  80. derivationPath, err := ParseDerivationPath(path)
  81. if err != nil {
  82. return nil, err
  83. }
  84. for _, index := range derivationPath {
  85. childExtendedKey, err := extendedKey.Child(index)
  86. if err != nil {
  87. return nil, err
  88. }
  89. extendedKey = childExtendedKey
  90. }
  91. return extendedKey.key, nil
  92. }
  93. func float64ToByte(float float64) []byte {
  94. bits := math.Float64bits(float)
  95. bytes := make([]byte, 8)
  96. binary.LittleEndian.PutUint64(bytes, bits)
  97. return bytes
  98. }