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

util.go 3.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. package atto
  2. import (
  3. "crypto/rand"
  4. "fmt"
  5. "io/ioutil"
  6. "math/big"
  7. "net/http"
  8. "strings"
  9. "golang.org/x/crypto/blake2b"
  10. )
  11. // GenerateSeed generates a new random seed.
  12. func GenerateSeed() (string, error) {
  13. b := make([]byte, 32)
  14. _, err := rand.Read(b)
  15. return fmt.Sprintf("%X", b), err
  16. }
  17. // NewPrivateKey creates a private key from the given seed and index.
  18. func NewPrivateKey(seed string, index uint32) (*big.Int, error) {
  19. seedInt, ok := big.NewInt(0).SetString(seed, 16)
  20. if !ok {
  21. return nil, fmt.Errorf("could not parse seed")
  22. }
  23. seedBytes := bigIntToBytes(seedInt, 32)
  24. indexBytes := bigIntToBytes(big.NewInt(int64(index)), 4)
  25. in := append(seedBytes, indexBytes...)
  26. privateKeyBytes := blake2b.Sum256(in)
  27. return big.NewInt(0).SetBytes(privateKeyBytes[:]), nil
  28. }
  29. func base32Encode(in *big.Int) string {
  30. alphabet := []byte("13456789abcdefghijkmnopqrstuwxyz")
  31. bigZero := big.NewInt(0)
  32. bigRadix := big.NewInt(32)
  33. num := big.NewInt(0).SetBytes(in.Bytes())
  34. out := make([]byte, 0)
  35. mod := new(big.Int)
  36. for num.Cmp(bigZero) > 0 {
  37. num.DivMod(num, bigRadix, mod)
  38. out = append(out, alphabet[mod.Int64()])
  39. }
  40. for i := 0; i < len(out)/2; i++ {
  41. out[i], out[len(out)-1-i] = out[len(out)-1-i], out[i]
  42. }
  43. return string(out)
  44. }
  45. func base32Decode(in string) (*big.Int, error) {
  46. reverseAlphabet := map[rune]*big.Int{}
  47. reverseAlphabet['1'] = big.NewInt(0)
  48. reverseAlphabet['3'] = big.NewInt(1)
  49. reverseAlphabet['4'] = big.NewInt(2)
  50. reverseAlphabet['5'] = big.NewInt(3)
  51. reverseAlphabet['6'] = big.NewInt(4)
  52. reverseAlphabet['7'] = big.NewInt(5)
  53. reverseAlphabet['8'] = big.NewInt(6)
  54. reverseAlphabet['9'] = big.NewInt(7)
  55. reverseAlphabet['a'] = big.NewInt(8)
  56. reverseAlphabet['b'] = big.NewInt(9)
  57. reverseAlphabet['c'] = big.NewInt(10)
  58. reverseAlphabet['d'] = big.NewInt(11)
  59. reverseAlphabet['e'] = big.NewInt(12)
  60. reverseAlphabet['f'] = big.NewInt(13)
  61. reverseAlphabet['g'] = big.NewInt(14)
  62. reverseAlphabet['h'] = big.NewInt(15)
  63. reverseAlphabet['i'] = big.NewInt(16)
  64. reverseAlphabet['j'] = big.NewInt(17)
  65. reverseAlphabet['k'] = big.NewInt(18)
  66. reverseAlphabet['m'] = big.NewInt(19)
  67. reverseAlphabet['n'] = big.NewInt(20)
  68. reverseAlphabet['o'] = big.NewInt(21)
  69. reverseAlphabet['p'] = big.NewInt(22)
  70. reverseAlphabet['q'] = big.NewInt(23)
  71. reverseAlphabet['r'] = big.NewInt(24)
  72. reverseAlphabet['s'] = big.NewInt(25)
  73. reverseAlphabet['t'] = big.NewInt(26)
  74. reverseAlphabet['u'] = big.NewInt(27)
  75. reverseAlphabet['w'] = big.NewInt(28)
  76. reverseAlphabet['x'] = big.NewInt(29)
  77. reverseAlphabet['y'] = big.NewInt(30)
  78. reverseAlphabet['z'] = big.NewInt(31)
  79. out := big.NewInt(0)
  80. radix := big.NewInt(32)
  81. for _, r := range in {
  82. out.Mul(out, radix)
  83. val, ok := reverseAlphabet[r]
  84. if !ok {
  85. return out, fmt.Errorf("'%c' is no legal base32 character", r)
  86. }
  87. out.Add(out, val)
  88. }
  89. return out, nil
  90. }
  91. func bigIntToBytes(x *big.Int, n int) []byte {
  92. return x.FillBytes(make([]byte, n, n))
  93. }
  94. func revertBytes(in []byte) []byte {
  95. for i := 0; i < len(in)/2; i++ {
  96. in[i], in[len(in)-1-i] = in[len(in)-1-i], in[i]
  97. }
  98. return in
  99. }
  100. func doRPC(requestBody, node string) (responseBytes []byte, err error) {
  101. resp, err := http.Post(node, "application/json", strings.NewReader(requestBody))
  102. if err != nil {
  103. return
  104. }
  105. defer resp.Body.Close()
  106. if resp.StatusCode != 200 {
  107. err = fmt.Errorf("received unexpected HTTP return code %d", resp.StatusCode)
  108. return
  109. }
  110. return ioutil.ReadAll(resp.Body)
  111. }
  112. func getPublicKeyFromAddress(address string) (*big.Int, error) {
  113. if len(address) == 64 {
  114. return base32Decode(address[4:56])
  115. } else if len(address) == 65 {
  116. return base32Decode(address[5:57])
  117. }
  118. return nil, fmt.Errorf("could not parse address %s", address)
  119. }