diff --git a/api/auth/client.go b/api/auth/client.go index 1832281..03b39df 100644 --- a/api/auth/client.go +++ b/api/auth/client.go @@ -2,8 +2,14 @@ package auth import ( "bytes" + "encoding/base64" + "encoding/json" + "strconv" + "strings" - "github.com/fumiama/tienyik/internal/hcli" + "github.com/fumiama/tienyik" + "github.com/fumiama/tienyik/hcli" + "github.com/fumiama/tienyik/internal/horm" "github.com/fumiama/tienyik/internal/hson" "github.com/fumiama/tienyik/internal/textio" ) @@ -19,11 +25,126 @@ type ResponseNegotiationEncKey struct { EncKey string `json:"encKey"` } +type ResponseNegotiationEncKeyData struct { + EValue string `json:"evalue"` + EID string `json:"eid"` +} + +func (r *ResponseNegotiationEncKey) Unwrap(tyr *tienyik.RSA) (*ResponseNegotiationEncKeyData, error) { + v, err := base64.StdEncoding.DecodeString(r.EncKey) + if err != nil { + return nil, err + } + aesk, err := tyr.Decrypt(v) + if err != nil { + return nil, err + } + + v, err = base64.StdEncoding.DecodeString(r.EncData) + if err != nil { + return nil, err + } + v, err = tienyik.NewAES(aesk).Decrypt(v) + if err != nil { + return nil, err + } + + var rsp ResponseNegotiationEncKeyData + err = json.Unmarshal(v, &rsp) + if err != nil { + return nil, err + } + return &rsp, nil +} + func NegotiationEncKey(r *RequestNegotiationEncKey) (*ResponseNegotiationEncKey, error) { - resp, err := hcli.Post(textio.API(), bytes.NewReader(hson.Marshal(nil, r))) + resp, err := hcli.NoClient.Post( + textio.API(), textio.ContenTypeJSON, + bytes.NewReader(hson.Marshal(nil, r)), + ) if err != nil { return nil, err } defer resp.Body.Close() return hson.Unmarshal[*ResponseNegotiationEncKey](nil, resp.Body) } + +type ResponseGenChallengeData struct { + EffectiveSeconds int `json:"effectiveSeconds"` + ChallengeID string `json:"challengeId"` + ChallengeCode string `json:"challengeCode"` +} + +func GenChallengeData(tya *tienyik.AES, cli *hcli.Client) (*ResponseGenChallengeData, error) { + resp, err := cli.Post( + textio.API(), textio.ContenTypeJSON, + strings.NewReader("{}"), + ) + if err != nil { + return nil, err + } + defer resp.Body.Close() + return hson.Unmarshal[*ResponseGenChallengeData](tya, resp.Body) +} + +type RequestLogin struct { + UserAccount string `form:"userAccount"` + Password string `form:"password"` + SHA256Password string `form:"sha256Password"` + ChallengeID string `form:"challengeId"` + DeviceCode string `form:"deviceCode"` + DeviceName string `form:"deviceName"` + DeviceType string `form:"deviceType"` + DeviceModel string `form:"deviceModel"` + AppVersion string `form:"appVersion"` + SysVersion string `form:"sysVersion"` + ClientVersion string `form:"clientVersion"` +} + +type ResponseLogin struct { + Timestamp int64 `json:"timestamp"` + UserID int64 `json:"userId"` + UserEid string `json:"userEid"` + UserName string `json:"userName"` + UserAccount string `json:"userAccount"` + Email *string `json:"email"` + Mobilephone string `json:"mobilephone"` + TenantID int64 `json:"tenantId"` + SecretKey string `json:"secretKey"` + DeviceType string `json:"deviceType"` + TenantName string `json:"tenantName"` + BondedDevice bool `json:"bondedDevice"` + RealNameStatus int64 `json:"realNameStatus"` + HasPassword int64 `json:"hasPassword"` + PID *string `json:"pid"` + NeedSmsValidate bool `json:"needSmsValidate"` + NeedUpdatePassword bool `json:"needUpdatePassword"` + ForceUpdateInitialPwd bool `json:"forceUpdateInitialPwd"` + AdminUser bool `json:"adminUser"` + LoginNotify *string `json:"loginNotify"` + CommonLoginReqHeader string `json:"commonLoginReqHeader"` + RecordSn bool `json:"recordSn"` + Token *string `json:"token"` + TwoFaValidateType *string `json:"twoFaValidateType"` + Random *string `json:"random"` + NeedBindVirtualMfa *bool `json:"needBindVirtualMfa"` + Tryout *string `json:"tryout"` + CtqEncID *string `json:"ctqEncId"` +} + +func (r *ResponseLogin) SetClient(cli *hcli.Client) { + cli.Tenantid = strconv.FormatInt(r.TenantID, 10) + cli.Usereid = r.UserEid +} + +func Login(tya *tienyik.AES, cli *hcli.Client, r *RequestLogin) (*ResponseLogin, error) { + resp, err := cli.Post( + textio.API(), textio.ContenTypeForm, + bytes.NewReader(horm.Marshal(tya, r)), + ) + if err != nil { + return nil, err + } + defer resp.Body.Close() + return hson.Unmarshal[*ResponseLogin](tya, resp.Body) +} diff --git a/api/auth/client/qrCode.go b/api/auth/client/qrCode.go new file mode 100644 index 0000000..f3fa093 --- /dev/null +++ b/api/auth/client/qrCode.go @@ -0,0 +1,50 @@ +package client + +import ( + "net/url" + + "github.com/fumiama/tienyik" + "github.com/fumiama/tienyik/hcli" + "github.com/fumiama/tienyik/internal/hson" + "github.com/fumiama/tienyik/internal/textio" +) + +type ResponseGenData struct { + QrCodeId string `json:"qrCodeId"` + QrCodeEndpoint *string `json:"qrCodeEndpoint"` + ServerHost string `json:"serverHost"` +} + +func GenData(tya *tienyik.AES, cli *hcli.Client) (*ResponseGenData, error) { + resp, err := cli.Post(textio.API(), textio.ContenTypeForm, nil) + if err != nil { + return nil, err + } + defer resp.Body.Close() + return hson.Unmarshal[*ResponseGenData](tya, resp.Body) +} + +type ResponseGetStatusData struct { + CodeId string `json:"codeId"` + CodeStatus string `json:"codeStatus"` + LoginToken *string `json:"loginToken"` + ClientCustomData *string `json:"clientCustomData"` + SupplementData *string `json:"supplementData"` +} + +func GetStatus(tya *tienyik.AES, cli *hcli.Client, qrCodeId string) (*ResponseGetStatusData, error) { + u, err := url.Parse(textio.API()) + if err != nil { + return nil, err + } + q := u.Query() + q.Set("qrCodeId", qrCodeId) + u.RawQuery = tya.EUrlParams(q) + + resp, err := cli.Get(u.String()) + if err != nil { + return nil, err + } + defer resp.Body.Close() + return hson.Unmarshal[*ResponseGetStatusData](tya, resp.Body) +} diff --git a/api/auth/client/qrCode_test.go b/api/auth/client/qrCode_test.go new file mode 100644 index 0000000..9762575 --- /dev/null +++ b/api/auth/client/qrCode_test.go @@ -0,0 +1,18 @@ +package client + +import ( + "testing" + + "github.com/fumiama/tienyik/hcli" +) + +func TestGenData(t *testing.T) { + r, err := GenData(nil, hcli.NewClient()) + if err != nil { + t.Fatal(err) + } + t.Log(r) + if r.QrCodeId == "" { + t.Fail() + } +} diff --git a/api/auth/client_test.go b/api/auth/client_test.go index c121f12..c67c443 100644 --- a/api/auth/client_test.go +++ b/api/auth/client_test.go @@ -3,7 +3,6 @@ package auth import ( "crypto/rand" "crypto/rsa" - "encoding/base64" "testing" "github.com/fumiama/tienyik" @@ -32,23 +31,8 @@ func TestNegotiationEncKey(t *testing.T) { t.Logf("EncData: %s", r.EncData) t.Logf("EncKey: %s", r.EncKey) - v, err := base64.StdEncoding.DecodeString(r.EncKey) + _, err = r.Unwrap(tyr) if err != nil { t.Fatal(err) } - aesk, err := tyr.Decrypt(v) - if err != nil { - t.Fatal(err) - } - t.Log(string(aesk)) - - v, err = base64.StdEncoding.DecodeString(r.EncData) - if err != nil { - t.Fatal(err) - } - v, err = tienyik.NewAES([]byte(aesk)).Decrypt(v) - if err != nil { - t.Fatal(err) - } - t.Log(string(v)) } diff --git a/api/cdserv/client.go b/api/cdserv/client.go new file mode 100644 index 0000000..b29dbc5 --- /dev/null +++ b/api/cdserv/client.go @@ -0,0 +1,32 @@ +package cdserv + +import ( + "github.com/fumiama/tienyik/hcli" + "github.com/fumiama/tienyik/internal/hson" + "github.com/fumiama/tienyik/internal/textio" +) + +type GlobalSwitches struct { + BodyMsgEType []string `json:"bodyMsgEType"` + PasswordRulesEnable bool `json:"passwordRulesEnable"` +} + +type ResponseGetServData struct { + GlobalSwitches GlobalSwitches `json:"globalSwitches"` + ServerNodeId string `json:"serverNodeId"` + Timestamp int64 `json:"timestamp"` + NetAccessType int `json:"netAccessType"` +} + +func (r *ResponseGetServData) SetClient(cli *hcli.Client) { + cli.Servernode = r.ServerNodeId +} + +func GetServData() (*ResponseGetServData, error) { + resp, err := hcli.NoClient.Get(textio.API()) + if err != nil { + return nil, err + } + defer resp.Body.Close() + return hson.Unmarshal[*ResponseGetServData](nil, resp.Body) +} diff --git a/api/cdserv/client_test.go b/api/cdserv/client_test.go new file mode 100644 index 0000000..5ea7da1 --- /dev/null +++ b/api/cdserv/client_test.go @@ -0,0 +1,14 @@ +package cdserv + +import "testing" + +func TestGetServData(t *testing.T) { + r, err := GetServData() + if err != nil { + t.Fatal(err) + } + t.Log(r) + if len(r.GlobalSwitches.BodyMsgEType) == 0 { + t.Fail() + } +} diff --git a/cfg.go b/cfg.go new file mode 100644 index 0000000..26f2aa6 --- /dev/null +++ b/cfg.go @@ -0,0 +1,31 @@ +package tienyik + +import ( + "crypto/rand" + "encoding/base64" + "io" + "strings" +) + +const Version = "103010001" + +const ( + DeviceTypePC = "25" + DeviceTypeMAC = "45" + DeviceTypeWEB = "60" +) + +const ( + AppModelTOC = "1" + AppModelTOB = "2" + AppModelPHONE = "3" +) + +func NewDeviceCode() string { + sb := &strings.Builder{} + sb.WriteString("web_") + enc := base64.NewEncoder(base64.RawURLEncoding, sb) + io.CopyN(enc, rand.Reader, (32/6+1)*8) + enc.Close() + return sb.String()[:4+32] +} diff --git a/go.mod b/go.mod index 2a95693..614567a 100644 --- a/go.mod +++ b/go.mod @@ -5,10 +5,11 @@ go 1.24.4 require ( github.com/fumiama/go-base16384 v1.7.1 github.com/sirupsen/logrus v1.9.3 + golang.org/x/net v0.28.0 ) require ( - golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect - golang.org/x/text v0.3.7 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect + github.com/stretchr/testify v1.8.0 // indirect + golang.org/x/sys v0.23.0 // indirect + golang.org/x/text v0.17.0 // indirect ) diff --git a/go.sum b/go.sum index 2ee0a67..af8ec3d 100644 --- a/go.sum +++ b/go.sum @@ -8,13 +8,19 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ= +github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= +golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM= +golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= +golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/internal/hcli/api.go b/hcli/api.go similarity index 100% rename from internal/hcli/api.go rename to hcli/api.go diff --git a/hcli/cli.go b/hcli/cli.go new file mode 100644 index 0000000..6eb17b7 --- /dev/null +++ b/hcli/cli.go @@ -0,0 +1,80 @@ +package hcli + +import ( + "net/http" + "reflect" + "strconv" + "sync/atomic" + "time" + + base14 "github.com/fumiama/go-base16384" + "github.com/fumiama/tienyik" + "golang.org/x/net/http2" +) + +var NoClient = (*Client)(nil) + +// DefaultClient is the default HTTP2 client. +var DefaultClient = http.Client{ + Transport: &http2.Transport{}, +} + +type Client struct { + rcnt uintptr + Appmodel string + Devicecode string + Devicetype string + Servernode string + Tenantid string + Usereid string + Version string +} + +func NewClient() *Client { + return &Client{ + Appmodel: tienyik.AppModelTOB, + Devicecode: tienyik.NewDeviceCode(), + Devicetype: tienyik.DeviceTypeWEB, + Version: tienyik.Version, + } +} + +func (c *Client) setHeaders(req *http.Request) { + if c == nil { + return + } + + v := reflect.ValueOf(c).Elem() + t := v.Type() + + for i := 0; i < v.NumField(); i++ { + field := t.Field(i) + if !field.IsExported() { + continue + } + + fieldValue := v.Field(i) + + if fieldValue.Kind() == reflect.String { + req.Header.Set( + base14.DecodeString("廝呲舀㴄")+field.Name, + fieldValue.String(), + ) + } + } + + if c.Appmodel != "" { + ts := time.Now().UnixMilli() + timestamp := strconv.FormatInt(ts, 10) + requestid := strconv.FormatUint( + uint64(atomic.AddUintptr(&c.rcnt, 1))+uint64(ts), 10, + ) + + req.Header.Set(base14.DecodeString("廝呲草獱歙攷徥爀㴆"), requestid) + req.Header.Set(base14.DecodeString("廝呲荑睭杜蕆厵縀㴆"), timestamp) + } + + if c.Servernode != "" { + //TODO: gensign + } +} diff --git a/internal/hcli/http.go b/hcli/http.go similarity index 50% rename from internal/hcli/http.go rename to hcli/http.go index fd6c236..d968e4d 100644 --- a/internal/hcli/http.go +++ b/hcli/http.go @@ -7,10 +7,12 @@ import ( base14 "github.com/fumiama/go-base16384" ) -func setCommonHeaders(req *http.Request) { +func setCommonHeaders(req *http.Request, contentType string) { req.Header.Set("Accept", "application/json") req.Header.Set("Pragma", "no-cache") - req.Header.Set("Content-Type", "application/json") + if contentType != "" { + req.Header.Set("Content-Type", contentType) + } req.Header.Set("Origin", base14.DecodeString("栝啇俌蠯姜吲融艹歛烦宸㴅")) req.Header.Set("Referer", base14.DecodeString("栝啇俌蠯姜吲融艹歛烦宸紀㴆")) req.Header.Set( @@ -19,47 +21,52 @@ func setCommonHeaders(req *http.Request) { ) } -func Get(path string) (resp *http.Response, err error) { +func (cli *Client) Get(path string) (resp *http.Response, err error) { req, err := http.NewRequest(http.MethodGet, ep(path), nil) if err != nil { return nil, err } - setCommonHeaders(req) - return http.DefaultClient.Do(req) + setCommonHeaders(req, "") + cli.setHeaders(req) + return DefaultClient.Do(req) } -func Post(path string, body io.Reader) (resp *http.Response, err error) { +func (cli *Client) Post(path string, contentType string, body io.Reader) (resp *http.Response, err error) { req, err := http.NewRequest(http.MethodPost, ep(path), body) if err != nil { return nil, err } - setCommonHeaders(req) - return http.DefaultClient.Do(req) + setCommonHeaders(req, contentType) + cli.setHeaders(req) + return DefaultClient.Do(req) } -func Put(path string, body io.Reader) (resp *http.Response, err error) { +func (cli *Client) Put(path string, contentType string, body io.Reader) (resp *http.Response, err error) { req, err := http.NewRequest(http.MethodPut, ep(path), body) if err != nil { return nil, err } - setCommonHeaders(req) - return http.DefaultClient.Do(req) + setCommonHeaders(req, contentType) + cli.setHeaders(req) + return DefaultClient.Do(req) } -func Delete(path string) (resp *http.Response, err error) { +func (cli *Client) Delete(path string) (resp *http.Response, err error) { req, err := http.NewRequest(http.MethodDelete, ep(path), nil) if err != nil { return nil, err } - setCommonHeaders(req) - return http.DefaultClient.Do(req) + setCommonHeaders(req, "") + cli.setHeaders(req) + return DefaultClient.Do(req) } -func Patch(path string, body io.Reader) (resp *http.Response, err error) { +func (cli *Client) Patch(path string, contentType string, body io.Reader) (resp *http.Response, err error) { req, err := http.NewRequest(http.MethodPatch, ep(path), body) if err != nil { return nil, err } - setCommonHeaders(req) - return http.DefaultClient.Do(req) + setCommonHeaders(req, contentType) + cli.setHeaders(req) + return DefaultClient.Do(req) } diff --git a/http.go b/http.go new file mode 100644 index 0000000..dd34d0d --- /dev/null +++ b/http.go @@ -0,0 +1,40 @@ +package tienyik + +import ( + "errors" + "net/url" + + "github.com/fumiama/tienyik/internal/textio" +) + +func (tya *AES) EUrlParams(params url.Values) string { + if tya == nil { + return params.Encode() + } + return url.Values{ + textio.FuncName(1, true): {textio.BytesToString(tya.Encrypt( + textio.StringToBytes(params.Encode()), + ))}, + }.Encode() +} + +func (tya *AES) ParseQuery(eparams string) (url.Values, error) { + if tya == nil { + return url.ParseQuery(eparams) + } + q, err := url.ParseQuery(eparams) + if err != nil { + return nil, err + } + if len(q) != 1 { + return nil, errors.New("len(q) must be 1") + } + for _, v := range q { + dec, err := tya.Decrypt(textio.StringToBytes(v[0])) + if err != nil { + return nil, err + } + return url.ParseQuery(textio.BytesToString(dec)) + } + panic("unexpected") +} diff --git a/internal/textio/api_test.go b/http_test.go similarity index 89% rename from internal/textio/api_test.go rename to http_test.go index c2ff540..fbb924d 100644 --- a/internal/textio/api_test.go +++ b/http_test.go @@ -1,11 +1,9 @@ -package textio +package tienyik import ( "encoding/binary" "net/url" "testing" - - "github.com/fumiama/tienyik" ) func TestEUrlParams(t *testing.T) { @@ -21,11 +19,12 @@ func TestEUrlParams(t *testing.T) { binary.BigEndian.PutUint32(key[i*4:(i+1)*4], k) } t.Log(string(key[:])) // wxdispbis8txuueo26ffs2veqs18sism - tya := tienyik.NewAES(key[:]) - params := EUrlParams(&tya, url.Values{ + tya := NewAES(key[:]) + params := tya.EUrlParams(url.Values{ "moduleCode": {"DESKTOP_MSGCENTER"}, }) - q, err := ParseQuery(&tya, params) + t.Log(params) + q, err := tya.ParseQuery(params) if err != nil { t.Fatal(err) } @@ -48,7 +47,7 @@ func TestEUrlParamsMultiple(t *testing.T) { for i, k := range rawkey { binary.BigEndian.PutUint32(key[i*4:(i+1)*4], k) } - tya := tienyik.NewAES(key[:]) + tya := NewAES(key[:]) testCases := []struct { name string @@ -103,8 +102,8 @@ func TestEUrlParamsMultiple(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - params := EUrlParams(&tya, tc.params) - q, err := ParseQuery(&tya, params) + params := tya.EUrlParams(tc.params) + q, err := tya.ParseQuery(params) if err != nil { t.Fatal(err) } diff --git a/internal/horm/req.go b/internal/horm/req.go new file mode 100644 index 0000000..dc5c01f --- /dev/null +++ b/internal/horm/req.go @@ -0,0 +1,35 @@ +package horm + +import ( + "net/url" + "reflect" + + "github.com/fumiama/tienyik" + "github.com/fumiama/tienyik/internal/textio" +) + +func Marshal(tya *tienyik.AES, x any) []byte { + q := url.Values{} + v := reflect.ValueOf(x).Elem() + t := v.Type() + + for i := 0; i < v.NumField(); i++ { + field := v.Field(i) + fieldType := t.Field(i) + + formTag := fieldType.Tag.Get("form") + if formTag == "" || formTag == "-" { + continue + } + + if field.Kind() == reflect.String { + q.Set(formTag, field.String()) + } + } + + s := q.Encode() + if tya != nil { + return tya.Encrypt(textio.StringToBytes(s)) + } + return textio.StringToBytes(s) +} diff --git a/internal/hson/req.go b/internal/hson/req.go index 9600cdd..40a25bf 100644 --- a/internal/hson/req.go +++ b/internal/hson/req.go @@ -2,12 +2,18 @@ package hson import ( "bytes" + "encoding/base64" "encoding/json" "github.com/fumiama/tienyik" "github.com/fumiama/tienyik/internal/log" + "github.com/fumiama/tienyik/internal/op" ) +type reqbody struct { + EData string `json:"edata"` +} + func Marshal(tya *tienyik.AES, v any) []byte { w := bytes.NewBuffer(make([]byte, 0, 1024)) err := json.NewEncoder(w).Encode(v) @@ -16,7 +22,9 @@ func Marshal(tya *tienyik.AES, v any) []byte { } log.Debugln("Marshal JSON:", w.String()) if tya != nil { - return tya.Encrypt(w.Bytes()) + return tya.Encrypt(op.Must(json.Marshal(&reqbody{ + EData: base64.StdEncoding.EncodeToString(w.Bytes()), + }))) } return w.Bytes() } diff --git a/internal/textio/api.go b/internal/textio/api.go index a7cb72b..57eca99 100644 --- a/internal/textio/api.go +++ b/internal/textio/api.go @@ -1,12 +1,8 @@ package textio import ( - "errors" - "net/url" "runtime" "strings" - - "github.com/fumiama/tienyik" ) func API() string { @@ -42,29 +38,3 @@ func API() string { sb.WriteString(p[1:]) return sb.String() } - -func EUrlParams(tya *tienyik.AES, params url.Values) string { - return url.Values{ - FuncName(1, true): {BytesToString(tya.Encrypt( - StringToBytes(params.Encode()), - ))}, - }.Encode() -} - -func ParseQuery(tya *tienyik.AES, eparams string) (url.Values, error) { - q, err := url.ParseQuery(eparams) - if err != nil { - return nil, err - } - if len(q) != 1 { - return nil, errors.New("len(q) must be 1") - } - for _, v := range q { - dec, err := tya.Decrypt(StringToBytes(v[0])) - if err != nil { - return nil, err - } - return url.ParseQuery(BytesToString(dec)) - } - panic("unexpected") -} diff --git a/internal/textio/http.go b/internal/textio/http.go new file mode 100644 index 0000000..351d2b2 --- /dev/null +++ b/internal/textio/http.go @@ -0,0 +1,6 @@ +package textio + +const ( + ContenTypeForm = "application/x-www-form-urlencoded" + ContenTypeJSON = "application/json" +) diff --git a/sha256.go b/sha256.go new file mode 100644 index 0000000..833c0bf --- /dev/null +++ b/sha256.go @@ -0,0 +1,25 @@ +package tienyik + +import ( + "crypto/sha256" + "encoding/hex" +) + +func ChallengePassword(pwd string, chlg string) string { + h := sha256.New() + h.Write([]byte(pwd)) + h.Write([]byte(chlg)) + var sum [sha256.Size]byte + return hex.EncodeToString(h.Sum(sum[:0])) +} + +func ChallengeSHA256Password(pwd string, chlg string) string { + h := sha256.New() + h.Write([]byte(pwd)) + var sum [sha256.Size]byte + s := hex.EncodeToString(h.Sum(sum[:0])) + h.Reset() + h.Write([]byte(s)) + h.Write([]byte(chlg)) + return hex.EncodeToString(h.Sum(sum[:0])) +}