From 089232e469a6bed32c688c53d66d23432c02d3ca Mon Sep 17 00:00:00 2001 From: EchoJamie <79831689+EchoJamie@users.noreply.github.com> Date: Sun, 21 Jul 2024 07:05:49 +0800 Subject: [PATCH] =?UTF-8?q?GH-33=20github=20token=20=E5=AE=89=E5=85=A8?= =?UTF-8?q?=E6=80=A7=E9=97=AE=E9=A2=98=EF=BC=8C=E6=9C=AC=E5=9C=B0=E4=BC=9A?= =?UTF-8?q?=E6=9A=B4=E9=9C=B2=20(#219)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * :sparkles: 增加AES加密方法 * :sparkles: github token 安全性问题 * :bug: key length require 16,24,32 * :pencil2: 取消注释行 --- cmd/checkout.go | 4 +-- cmd/clone.go | 4 +-- cmd/delete.go | 2 +- cmd/pr.go | 4 +-- cmd/sync.go | 2 +- cmd/upgrade.go | 2 +- common/common.go | 81 +++++++++++++++++++++++++++++++++++++++++++++++- 7 files changed, 89 insertions(+), 10 deletions(-) diff --git a/cmd/checkout.go b/cmd/checkout.go index a08a48b..5f8b5e8 100644 --- a/cmd/checkout.go +++ b/cmd/checkout.go @@ -126,7 +126,7 @@ func getGithubBranch(branchNum string, account string) string { client := &http.Client{} req, err := http.NewRequest("GET", "https://api.github.com/repos/"+account+"/"+viper.GetString("current-project.name")+"/branches/"+branchNum, nil) - req.Header = common.GitHubHeader(viper.GetString("user.token")) + req.Header = common.GitHubHeader(common.GetToken()) resp, err := client.Do(req) if err != nil { fmt.Println("请求失败:", err) @@ -243,7 +243,7 @@ func getGithubIssueBranch(issueNumber string) string { client := &http.Client{} req, err := http.NewRequest("GET", "https://api.github.com/repos/isxcode/"+viper.GetString("current-project.name")+"/issues/"+issueNumber, nil) - req.Header = common.GitHubHeader(viper.GetString("user.token")) + req.Header = common.GitHubHeader(common.GetToken()) resp, err := client.Do(req) if err != nil { fmt.Println("请求失败:", err) diff --git a/cmd/clone.go b/cmd/clone.go index 9c35550..462a835 100644 --- a/cmd/clone.go +++ b/cmd/clone.go @@ -32,7 +32,7 @@ var cloneCmd = &cobra.Command{ func cloneCmdMain() { // 判断用户是否登录 - isLogin := common.CheckUserAccount(viper.GetString("user.token")) + isLogin := common.CheckUserAccount(common.GetToken()) if !isLogin { fmt.Println("请先登录") os.Exit(1) @@ -106,7 +106,7 @@ func inputProjectPath() { func cloneCode(isxcodeRepository string, path string, name string, isMain bool) { // 替换下载链接 - isxcodeRepository = strings.Replace(isxcodeRepository, "https://", "https://"+viper.GetString("user.token")+"@", -1) + isxcodeRepository = strings.Replace(isxcodeRepository, "https://", "https://"+common.GetToken()+"@", -1) // 下载主项目代码 executeCommand := "git clone -b main " + isxcodeRepository diff --git a/cmd/delete.go b/cmd/delete.go index 4682df1..7821b80 100644 --- a/cmd/delete.go +++ b/cmd/delete.go @@ -111,7 +111,7 @@ func getGithubIssueStatus(issueNumber string) string { client := &http.Client{} req, err := http.NewRequest("GET", "https://api.github.com/repos/isxcode/"+viper.GetString("current-project.name")+"/issues/"+issueNumber, nil) - req.Header = common.GitHubHeader(viper.GetString("user.token")) + req.Header = common.GitHubHeader(common.GetToken()) resp, err := client.Do(req) if err != nil { fmt.Println("请求失败:", err) diff --git a/cmd/pr.go b/cmd/pr.go index 1e0a418..fa4b4c0 100644 --- a/cmd/pr.go +++ b/cmd/pr.go @@ -97,7 +97,7 @@ func createPr(titleName string, branchName string, name string) { } req, err := http.NewRequest("POST", "https://api.github.com/repos/isxcode/"+name+"/pulls", bytes.NewBuffer(payload)) - req.Header = common.GitHubHeader(viper.GetString("user.token")) + req.Header = common.GitHubHeader(common.GetToken()) resp, err := client.Do(req) if err != nil { fmt.Println("请求失败:", err) @@ -134,7 +134,7 @@ func getGithubIssueTitle(issueNumber string) string { client := &http.Client{} req, err := http.NewRequest("GET", "https://api.github.com/repos/isxcode/"+viper.GetString("current-project.name")+"/issues/"+issueNumber, nil) - req.Header = common.GitHubHeader(viper.GetString("user.token")) + req.Header = common.GitHubHeader(common.GetToken()) resp, err := client.Do(req) if err != nil { fmt.Println("请求失败:", err) diff --git a/cmd/sync.go b/cmd/sync.go index 01f096b..d808d8e 100644 --- a/cmd/sync.go +++ b/cmd/sync.go @@ -61,7 +61,7 @@ func SyncBranch(projectName, branchName string) { userName := viper.GetString("user.account") req, err := http.NewRequest("POST", common.GithubApiReposDomain+"/"+userName+"/"+projectName+"/merge-upstream", bytes.NewBuffer(payload)) - req.Header = common.GitHubHeader(viper.GetString("user.token")) + req.Header = common.GitHubHeader(common.GetToken()) resp, err := client.Do(req) if err != nil { fmt.Println("请求失败:", err) diff --git a/cmd/upgrade.go b/cmd/upgrade.go index d89f26d..f3a65af 100644 --- a/cmd/upgrade.go +++ b/cmd/upgrade.go @@ -96,7 +96,7 @@ func upgradeCmdMain() { os.Exit(1) } - req.Header = common.GitHubHeader(viper.GetString("user.token")) + req.Header = common.GitHubHeader(common.GetToken()) resp, err := client.Do(req) if err != nil { fmt.Println("请求失败:", err) diff --git a/common/common.go b/common/common.go index 852602a..47c8114 100644 --- a/common/common.go +++ b/common/common.go @@ -4,11 +4,17 @@ Copyright © 2024 jamie HERE package common import ( - "encoding/json" + "crypto/aes" + "crypto/cipher" + "crypto/rand" + "encoding/hex" + "encoding/json" "fmt" "github.com/mitchellh/go-homedir" + "github.com/spf13/viper" "io" "os" + "strings" ) func HomeDir() string { @@ -29,6 +35,79 @@ func CurrentWorkDir() string { return dir } +var key = []byte("isxcode-20240719") + +func Encrypt(token string) string { + ciphertext, err := encryptAES([]byte(token), key) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + return ciphertext +} + +func GetToken() string { + token := viper.GetString("user.token") + if token == "" { + fmt.Println("请先登录") + os.Exit(1) + } + if strings.HasPrefix(token, "ghp_") { + encryptToken := Encrypt(token) + viper.Set("user.token", encryptToken) + viper.WriteConfig() + return token + } + s, err := decryptAES(token, key) + if err != nil { + fmt.Println("解密失败...", err) + os.Exit(1) + } + return s +} + +func encryptAES(plaintext, key []byte) (string, error) { + block, err := aes.NewCipher(key) + if err != nil { + return "", err + } + + ciphertext := make([]byte, aes.BlockSize+len(plaintext)) + iv := ciphertext[:aes.BlockSize] + if _, err := io.ReadFull(rand.Reader, iv); err != nil { + return "", err + } + + stream := cipher.NewCFBEncrypter(block, iv) + stream.XORKeyStream(ciphertext[aes.BlockSize:], plaintext) + + return hex.EncodeToString(ciphertext), nil +} + +func decryptAES(ciphertext string, key []byte) (string, error) { + ciphertextBytes, err := hex.DecodeString(ciphertext) + if err != nil { + return "", err + } + + block, err := aes.NewCipher(key) + if err != nil { + return "", err + } + + if len(ciphertextBytes) < aes.BlockSize { + return "", fmt.Errorf("ciphertext too short") + } + + iv := ciphertextBytes[:aes.BlockSize] + ciphertextBytes = ciphertextBytes[aes.BlockSize:] + + stream := cipher.NewCFBDecrypter(block, iv) + stream.XORKeyStream(ciphertextBytes, ciphertextBytes) + + return string(ciphertextBytes), nil +} + func Parse(reader io.Reader, v any) { body, err := io.ReadAll(reader) if err != nil {