signer.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. package core
  2. import (
  3. "crypto/ecdsa"
  4. "encoding/base64"
  5. "fmt"
  6. "github.com/btcsuite/btcd/btcutil/hdkeychain"
  7. "github.com/btcsuite/btcd/chaincfg"
  8. "github.com/demdxx/gocast"
  9. "github.com/ethereum/go-ethereum/accounts"
  10. "github.com/ethereum/go-ethereum/common"
  11. "github.com/ethereum/go-ethereum/common/hexutil"
  12. "github.com/ethereum/go-ethereum/crypto"
  13. "github.com/tyler-smith/go-bip39"
  14. "go_server/model/system"
  15. "strings"
  16. "time"
  17. )
  18. type Sign struct {
  19. SysName string `mapstructure:"sys-name" json:"sys-name" yaml:"sys-name"` // 本系统名
  20. SysSignPrefix string `mapstructure:"sys-sign-prefix" json:"sys-sign-prefix" yaml:"sys-sign-prefix"`
  21. SysAddress string `mapstructure:"sys-address" json:"sys-address" yaml:"sys-address"` // 本系统地址
  22. SysKey string `mapstructure:"sys-key" json:"sys-key" yaml:"sys-key"` // 本系统密钥 -- 使用本系统密码本加密
  23. Internals []*InternalSys `mapstructure:"internals" json:"internals" yaml:"internals"`
  24. }
  25. type InternalSys struct {
  26. SysName string `mapstructure:"sys-name" json:"sys-name" yaml:"sys-name"`
  27. SysUrl string `mapstructure:"sys-url" json:"sys-url" yaml:"sys-url"` // 系统地址
  28. SignPrefix string `mapstructure:"sign-prefix" json:"sign-prefix" yaml:"sign-prefix"` // 签名前缀
  29. SignExpSec int64 `mapstructure:"sign-exp-sec" json:"sign-exp-sec" yaml:"sign-exp-sec"` // 签名超时-S
  30. SysAddress string `mapstructure:"sys-address" json:"sys-address" yaml:"sys-address"` // 管理系统地址
  31. }
  32. var signConfer *Sign
  33. func signConf() *Sign {
  34. if signConfer == nil {
  35. // 初始化
  36. rows := make([]*system.SysSignConfig, 0)
  37. err := MainDb().
  38. Model(&system.SysSignConfig{}).
  39. Where("1 = 1").
  40. Find(&rows).Error
  41. if err != nil {
  42. panic(err)
  43. }
  44. signConfer = new(Sign)
  45. for _, row := range rows {
  46. if row.IsSystemSign {
  47. signConfer.SysSignPrefix = row.SignName
  48. signConfer.SysKey = row.SignPriKey
  49. signConfer.SysAddress = row.SignAddress
  50. signConfer.SysName = row.SignName
  51. continue
  52. }
  53. if signConfer.Internals == nil {
  54. signConfer.Internals = make([]*InternalSys, 0)
  55. }
  56. signConfer.Internals = append(signConfer.Internals, &InternalSys{
  57. SysName: row.SignName,
  58. SysAddress: row.SignAddress,
  59. SysUrl: row.SysUrl,
  60. SignPrefix: row.SignName,
  61. SignExpSec: row.SignExpSec,
  62. })
  63. }
  64. }
  65. return signConfer
  66. }
  67. // 构建本系统签名信息
  68. func BuildSignMessage() (string, error) {
  69. sysPrivateKey, err := Base64Decode(signConf().SysKey)
  70. if err != nil {
  71. return "", err
  72. }
  73. msg := fmt.Sprintf("%s%d", signConf().SysSignPrefix, time.Now().Unix())
  74. sign, err := signMessage(msg, sysPrivateKey)
  75. if err != nil {
  76. return "", err
  77. }
  78. return fmt.Sprintf("%s%s", msg, sign), nil
  79. }
  80. type Signer struct {
  81. SignPrefix string `mapstructure:"sign-prefix" json:"sign-prefix" yaml:"sign-prefix"` // 签名前缀
  82. SignExpSec int64 `mapstructure:"sign-exp-sec" json:"sign-exp-sec" yaml:"sign-exp-sec"` // 签名超时-S
  83. SysAddress string `mapstructure:"sys-address" json:"sys-address" yaml:"sys-address"` // 管理系统地址
  84. }
  85. // 通过系统名获取外部系统签名器 用于签名验证
  86. var signerMap = make(map[string]*Signer)
  87. func SignerBySysName(sysName string) (*Signer, error) {
  88. v, ok := signerMap[sysName]
  89. if ok {
  90. return v, nil
  91. }
  92. for _, item := range signConf().Internals {
  93. if item.SysName == sysName {
  94. signerMap[sysName] = &Signer{
  95. SignPrefix: item.SignPrefix,
  96. SignExpSec: item.SignExpSec,
  97. SysAddress: item.SysAddress,
  98. }
  99. return signerMap[sysName], nil
  100. }
  101. }
  102. return nil, fmt.Errorf("sys name not found")
  103. }
  104. // 本系统地址 -- 暴露给其他系统使用
  105. func SysAddress() (string, error) {
  106. sysPrivateKey, err := Base64Decode(signConf().SysKey)
  107. if err != nil {
  108. return "", err
  109. }
  110. return ethPriKey2HexAddress(sysPrivateKey)
  111. }
  112. func SysSignPrefix() string {
  113. return signConf().SysSignPrefix
  114. }
  115. const (
  116. base64Table = "7PQX12RVW3YZaDEFGbcdeIJjkKLMNO56fghiABCHlSTUmnopqrxyz04stuvw89+/"
  117. )
  118. var coder = base64.NewEncoding(base64Table)
  119. func Base64Encode(src string) string { //编码
  120. return coder.EncodeToString([]byte(src))
  121. }
  122. func Base64Decode(src string) (string, error) { //解码
  123. bts, err := coder.DecodeString(src)
  124. if err != nil {
  125. return "", err
  126. }
  127. return fmt.Sprintf("%s", bts), nil
  128. }
  129. func signMessage(message, hexPri string) (string, error) {
  130. priKey, err := priHexKeyToECDSA(hexPri)
  131. if err != nil {
  132. return "", err
  133. }
  134. return signMessageWithEcdsa(message, priKey)
  135. }
  136. // signMessageWithEcdsa 使用私钥签名消息
  137. func signMessageWithEcdsa(message string, privateKey *ecdsa.PrivateKey) (string, error) {
  138. // 计算消息的Keccak256哈希
  139. hash := crypto.Keccak256Hash([]byte(message))
  140. // 签名
  141. signature, err := crypto.Sign(hash.Bytes(), privateKey)
  142. if err != nil {
  143. return "", err
  144. }
  145. // 添加恢复ID(以太坊要求)
  146. signature[64] += 27
  147. return hexutil.Encode(signature), nil
  148. }
  149. func (s *Signer) VerifySignature(message string) error {
  150. msg, signature, ok := s.checkMessage(message)
  151. if !ok {
  152. return fmt.Errorf("非法签名")
  153. }
  154. return verifySignature(msg, signature, common.HexToAddress(s.SysAddress))
  155. }
  156. // 消息格式
  157. // 1 去除消息头部信息
  158. // 2 获取前10位数字
  159. // 3 对比时间 不得相差3秒
  160. func (s *Signer) checkMessage(message string) (string, string, bool) {
  161. if !strings.HasPrefix(message, s.SignPrefix) {
  162. fmt.Println(fmt.Sprintf("签名未包含前缀:%s", s.SignPrefix))
  163. return "", "", false
  164. }
  165. removePrefix := strings.TrimPrefix(message, s.SignPrefix)
  166. timestamp := removePrefix[:10]
  167. notUnixTime := time.Now().Unix()
  168. if notUnixTime > gocast.ToInt64(timestamp)+s.SignExpSec || gocast.ToInt64(timestamp) > notUnixTime {
  169. return "", "", false
  170. }
  171. signature := removePrefix[10:]
  172. return s.SignPrefix + removePrefix[:10], signature, true
  173. }
  174. // verifySignature 验证签名
  175. func verifySignature(message, signature string, address common.Address) error {
  176. // 解码签名
  177. sig, err := hexutil.Decode(signature)
  178. if err != nil {
  179. return err
  180. }
  181. // 恢复ID必须为27或28
  182. if sig[64] != 27 && sig[64] != 28 {
  183. return fmt.Errorf("无效的恢复ID")
  184. }
  185. // 调整恢复ID为0或1(以太坊库要求)
  186. sig[64] -= 27
  187. // 计算消息哈希
  188. hash := crypto.Keccak256Hash([]byte(message))
  189. // 从签名恢复公钥
  190. publicKey, err := crypto.SigToPub(hash.Bytes(), sig)
  191. if err != nil {
  192. return err
  193. }
  194. // 从公钥生成地址
  195. recoveredAddr := crypto.PubkeyToAddress(*publicKey)
  196. // 验证地址是否匹配
  197. if recoveredAddr != address {
  198. return fmt.Errorf("签名验证失败: 地址不匹配")
  199. }
  200. return nil
  201. }
  202. // 生成助记词 使用标准:BIP39(i -128 /256)
  203. // 生成“128的熵”
  204. //1. 生成一个长度为 128 ~ 256 位的随机序列(后面称为熵);
  205. //- 熵的取值长度需要为 32 的整数倍的值。所以取值可能为:【128, 160, 192, 224, 256】。
  206. //2. 获取熵的校验和;
  207. //- 取熵哈希后的前 n 位作为校验和(n = 熵长度/32)。
  208. //- 校验和的理论值为【4,5,6,7,8】。
  209. //3. 生成新的序列;
  210. //- 新的序列方式为 = 熵 + 校验和
  211. //- 新序列的长度理论值可能为:【128+4,160+5,192+6,224+7,256+8】即【132,165,198,231,264】
  212. //4. 获得 m 个 11 位二进制数。
  213. //- 将新生成的序列,按照 11 位进行平分。
  214. //- m 的理论可能值为:【12,15,18,21,24】
  215. //- 为什么是 11 位?助记词库总共有 2048 个单词,2^11 正好是 2048。所以用 11 位二进制数刚好可以将所有的助记词定位。
  216. //5. 获得 m 个助记词;
  217. //- 根据第四步得到的 m 个 11位二进制数,去助记词表定位每一个助记词。
  218. //- 得到助记词个数的理论值为:【12,15,18,21,24】
  219. // 波场使用的熵长度为256 128生成12位单词助记词
  220. func GenerateMnemonicWords(i int) string {
  221. entropy, err := bip39.NewEntropy(i)
  222. if err != nil {
  223. return ""
  224. }
  225. mnemonic, _ := bip39.NewMnemonic(entropy)
  226. return mnemonic
  227. }
  228. func MnemonicToEthInfo(mnemonic string) (ethHexAddress string, subPriKey string, err error) {
  229. // 验证助记词有效性
  230. if !bip39.IsMnemonicValid(mnemonic) {
  231. return "", "", fmt.Errorf("invalid mnemonic phrase")
  232. }
  233. // 生成种子
  234. seed := bip39.NewSeed(mnemonic, "") // 第二个参数是密码,可以为空
  235. // 创建主密钥
  236. master, err := hdkeychain.NewMaster(seed, &chaincfg.MainNetParams)
  237. if err != nil {
  238. return "", "", fmt.Errorf("failed to create master key: %v", err)
  239. }
  240. // 解析派生路径
  241. dp, err := accounts.ParseDerivationPath("m/44'/60'/0'/0/0")
  242. if err != nil {
  243. return "", "", fmt.Errorf("failed to parse derivation path: %v", err)
  244. }
  245. // 派生密钥
  246. for _, n := range dp {
  247. var child *hdkeychain.ExtendedKey
  248. if master.IsAffectedByIssue172() {
  249. child, err = master.Derive(n)
  250. } else {
  251. child, err = master.DeriveNonStandard(n)
  252. }
  253. if err != nil {
  254. return "", "", fmt.Errorf("failed to derive key: %v", err)
  255. }
  256. master = child
  257. }
  258. // 获取ECDSA私钥
  259. privateKey, err := master.ECPrivKey()
  260. if err != nil {
  261. return "", "", fmt.Errorf("failed to get EC private key: %v", err)
  262. }
  263. privateKeyECDSA := privateKey.ToECDSA()
  264. publicKey := privateKeyECDSA.Public().(*ecdsa.PublicKey)
  265. // 生成地址
  266. addr := crypto.PubkeyToAddress(*publicKey)
  267. ethHexAddress = addr.Hex()
  268. // 编码私钥
  269. privateKeyBytes := crypto.FromECDSA(privateKeyECDSA)
  270. subPriKey = hexutil.Encode(privateKeyBytes)
  271. return ethHexAddress, subPriKey, nil
  272. }
  273. func GenerateSysInfo() (string, string, error) {
  274. mn := GenerateMnemonicWords(128)
  275. addr, pri, err := MnemonicToEthInfo(mn)
  276. if err != nil {
  277. return "", "", err
  278. }
  279. pri = Base64Encode(pri)
  280. return addr, pri, nil
  281. }
  282. func EthAddressCheck(addr string) bool {
  283. return common.IsHexAddress(addr)
  284. }
  285. func priHexKeyToECDSA(hexPriKey string) (*ecdsa.PrivateKey, error) {
  286. return crypto.HexToECDSA(strings.TrimPrefix(hexPriKey, "0x"))
  287. }
  288. func ethPriKey2HexAddress(priKeyHash string) (string, error) {
  289. priKey, err := priHexKeyToECDSA(priKeyHash)
  290. if err != nil {
  291. return "", err
  292. }
  293. pubKey := priKey.Public().(*ecdsa.PublicKey)
  294. addr := crypto.PubkeyToAddress(*pubKey)
  295. return addr.Hex(), nil
  296. }
  297. func EthPriKey2HexAddress(priKeyHash string) (string, error) {
  298. return ethPriKey2HexAddress(priKeyHash)
  299. }