github.com/Mrs4s/MiraiGo@v0.0.0-20240226124653-54bdd873e3fe/client/internal/oicq/ecdh.go (about) 1 package oicq 2 3 import ( 4 "crypto/ecdh" 5 "crypto/md5" 6 "crypto/rand" 7 "encoding/hex" 8 "encoding/json" 9 "net/http" 10 "strconv" 11 ) 12 13 // session is ecdh session in oicq. 14 type session struct { 15 SvrPublicKeyVer uint16 16 PublicKey []byte 17 ShareKey []byte 18 } 19 20 const serverPublicKey = "04EBCA94D733E399B2DB96EACDD3F69A8BB0F74224E2B44E3357812211D2E62EFBC91BB553098E25E33A799ADC7F76FEB208DA7C6522CDB0719A305180CC54A82E" 21 22 func newSession() *session { 23 e := &session{ 24 SvrPublicKeyVer: 1, 25 } 26 key, _ := hex.DecodeString(serverPublicKey) 27 e.init(key) 28 return e 29 } 30 31 type pubKeyResp struct { 32 Meta struct { 33 PubKeyVer uint16 `json:"KeyVer"` 34 PubKey string `json:"PubKey"` 35 } `json:"PubKeyMeta"` 36 } 37 38 // fetchPubKey 从服务器获取PubKey 39 func (e *session) fetchPubKey(uin int64) { 40 resp, err := http.Get("https://keyrotate.qq.com/rotate_key?cipher_suite_ver=305&uin=" + strconv.FormatInt(uin, 10)) 41 if err != nil { 42 return 43 } 44 defer func() { _ = resp.Body.Close() }() 45 pubKey := pubKeyResp{} 46 err = json.NewDecoder(resp.Body).Decode(&pubKey) 47 if err != nil { 48 return 49 } 50 e.SvrPublicKeyVer = pubKey.Meta.PubKeyVer 51 key, _ := hex.DecodeString(pubKey.Meta.PubKey) 52 e.init(key) // todo check key sign 53 } 54 55 func (e *session) init(svrPubKey []byte) { 56 p256 := ecdh.P256() 57 local, _ := p256.GenerateKey(rand.Reader) 58 remote, _ := p256.NewPublicKey(svrPubKey) 59 share, _ := local.ECDH(remote) 60 61 hash := md5.New() 62 hash.Write(share[:16]) 63 e.ShareKey = hash.Sum(nil) 64 e.PublicKey = local.PublicKey().Bytes() 65 }