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