diff --git a/go.mod b/go.mod index f17fbfd..1ad175b 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( github.com/leaanthony/slicer v1.6.0 // indirect github.com/leaanthony/u v1.1.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.19 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/rivo/uniseg v0.4.4 // indirect diff --git a/go.sum b/go.sum index 62d0f8b..15cc2ec 100644 --- a/go.sum +++ b/go.sum @@ -41,8 +41,8 @@ github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxec github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= -github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/minio/selfupdate v0.6.0 h1:i76PgT0K5xO9+hjzKcacQtO7+MjJ4JKA8Ak8XQ9DDwU= github.com/minio/selfupdate v0.6.0/go.mod h1:bO02GTIPCMQFTEvE5h4DjYB58bCoZ35XLeBf0buTDdM= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= diff --git a/godo/files/fs.go b/godo/files/fs.go index 98f850d..4719135 100644 --- a/godo/files/fs.go +++ b/godo/files/fs.go @@ -24,7 +24,9 @@ package files import ( + "crypto/md5" "encoding/base64" + "encoding/hex" "encoding/json" "fmt" "godo/libs" @@ -165,15 +167,20 @@ func HandleExists(w http.ResponseWriter, r *http.Request) { // HandleReadFile reads a file's content func HandleReadFile(w http.ResponseWriter, r *http.Request) { path := r.URL.Query().Get("path") + fpwd := r.Header.Get("fpwd") + haspwd := IsHavePwd(fpwd) + // 校验文件路径 if err := validateFilePath(path); err != nil { libs.HTTPError(w, http.StatusBadRequest, err.Error()) return } + // 获取文件路径 basePath, err := libs.GetOsDir() if err != nil { libs.HTTPError(w, http.StatusInternalServerError, err.Error()) return } + // 读取内容 fileContent, err := ReadFile(basePath, path) if err != nil { libs.HTTPError(w, http.StatusNotFound, err.Error()) @@ -184,11 +191,28 @@ func HandleReadFile(w http.ResponseWriter, r *http.Request) { if !strings.HasPrefix(content, "link::") { content = base64.StdEncoding.EncodeToString(fileContent) } - res := libs.APIResponse{ - Message: fmt.Sprintf("File '%s' read successfully.", path), - Data: content, // Optionally, encode content as base64 for transmission - //Data: string(fileContent), + + // 初始响应 + res := libs.APIResponse{Code: 0, Message: "success"} + switch haspwd { + case true: + // 有密码检验密码 + isreal := CheckFilePwd(fpwd) + // 密码正确返回原文,否则返回加密文本 + if isreal { + res.Data = content + } else { + data, err := libs.EncryptData(fileContent, libs.EncryptionKey) + if err != nil { + libs.HTTPError(w, http.StatusInternalServerError, err.Error()) + return + } + res.Data = base64.StdEncoding.EncodeToString(data) + } + case false: + res.Data = content } + json.NewEncoder(w).Encode(res) } @@ -523,3 +547,26 @@ func HandleDesktop(w http.ResponseWriter, r *http.Request) { } libs.SuccessMsg(w, rootInfo, "success") } + +// 设置文件密码 +func HandleSetFilePwd(w http.ResponseWriter, r *http.Request) { + fpwd := r.Header.Get("filepwd") + // 密码最长16位 + if fpwd == "" || len(fpwd) > 16 { + libs.ErrorMsg(w, "密码长度为空或者过长,最长为16位") + return + } + // 服务端存储 + req := libs.ReqBody{ + Name: "filepwd", + Value: fpwd, + } + libs.SetConfig(req) + // 客户端加密 + mhash := md5.New() + mhash.Write([]byte(fpwd)) + v := mhash.Sum(nil) + pwdstr := hex.EncodeToString(v) + res := libs.APIResponse{Message: "success", Data: pwdstr} + json.NewEncoder(w).Encode(res) +} diff --git a/godo/files/os.go b/godo/files/os.go index 0eaeeab..11efc8c 100644 --- a/godo/files/os.go +++ b/godo/files/os.go @@ -24,6 +24,8 @@ package files import ( + "crypto/md5" + "encoding/hex" "fmt" "godo/libs" "io" @@ -334,3 +336,21 @@ func CheckDeleteDesktop(filePath string) error { } return nil } + +// 校验文件密码 +func CheckFilePwd(fpwd string) bool { + mhash := md5.New() + mhash.Write([]byte(fpwd)) + v := mhash.Sum(nil) + pwdstr := hex.EncodeToString(v) + oldpwd, _ := libs.GetConfig("filepwd") + return oldpwd == pwdstr +} + +func IsHavePwd(pwd string) bool { + if len(pwd) > 0 { + return true + } else { + return false + } +} diff --git a/godo/libs/encode.go b/godo/libs/encode.go new file mode 100644 index 0000000..3ff3b03 --- /dev/null +++ b/godo/libs/encode.go @@ -0,0 +1,52 @@ +package libs + +import ( + "bytes" + "crypto/aes" + "crypto/cipher" + "crypto/hmac" + "crypto/rand" + "crypto/sha256" + "io" +) + +// 密钥 +var EncryptionKey = []byte("37ac3edea15eec37b48eb1c8f769ae0c") + +// pkcs7填充 +func pkcs7Pad(data []byte, blockSize int) []byte { + padding := blockSize - len(data)%blockSize + padtext := bytes.Repeat([]byte{byte(padding)}, padding) + return append(data, padtext...) +} + +func EncryptData(data []byte, key []byte) ([]byte, error) { + block, err := aes.NewCipher(key) + if err != nil { + return nil, err + } + + // 对原始数据进行 PKCS#7 填充 + paddedData := pkcs7Pad(data, block.BlockSize()) + + // 生成随机的初始化向量 + ciphertext := make([]byte, aes.BlockSize+len(paddedData)) + iv := ciphertext[:aes.BlockSize] + if _, err := io.ReadFull(rand.Reader, iv); err != nil { + return nil, err + } + + // 使用 CBC 模式加密数据 + mode := cipher.NewCBCEncrypter(block, iv) + mode.CryptBlocks(ciphertext[aes.BlockSize:], paddedData) + + // 计算 HMAC-SHA256 签名 + mac := hmac.New(sha256.New, key) + mac.Write(ciphertext) + macSum := mac.Sum(nil) + + // 将加密后的数据和 HMAC 签名组合起来 + result := append(ciphertext, macSum...) + + return result, nil +}