Browse Source

带加密的读文件接口实现

master
刘子旺 7 months ago
parent
commit
3ae85f08e2
  1. 2
      go.mod
  2. 4
      go.sum
  3. 55
      godo/files/fs.go
  4. 20
      godo/files/os.go
  5. 52
      godo/libs/encode.go

2
go.mod

@ -29,7 +29,7 @@ require (
github.com/leaanthony/slicer v1.6.0 // indirect github.com/leaanthony/slicer v1.6.0 // indirect
github.com/leaanthony/u v1.1.0 // indirect github.com/leaanthony/u v1.1.0 // indirect
github.com/mattn/go-colorable v0.1.13 // 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/browser v0.0.0-20210911075715-681adbf594b8 // indirect
github.com/pkg/errors v0.9.1 // indirect github.com/pkg/errors v0.9.1 // indirect
github.com/rivo/uniseg v0.4.4 // indirect github.com/rivo/uniseg v0.4.4 // indirect

4
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-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.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.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.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= 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 h1:i76PgT0K5xO9+hjzKcacQtO7+MjJ4JKA8Ak8XQ9DDwU=
github.com/minio/selfupdate v0.6.0/go.mod h1:bO02GTIPCMQFTEvE5h4DjYB58bCoZ35XLeBf0buTDdM= github.com/minio/selfupdate v0.6.0/go.mod h1:bO02GTIPCMQFTEvE5h4DjYB58bCoZ35XLeBf0buTDdM=
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU=

55
godo/files/fs.go

@ -24,7 +24,9 @@
package files package files
import ( import (
"crypto/md5"
"encoding/base64" "encoding/base64"
"encoding/hex"
"encoding/json" "encoding/json"
"fmt" "fmt"
"godo/libs" "godo/libs"
@ -165,15 +167,20 @@ func HandleExists(w http.ResponseWriter, r *http.Request) {
// HandleReadFile reads a file's content // HandleReadFile reads a file's content
func HandleReadFile(w http.ResponseWriter, r *http.Request) { func HandleReadFile(w http.ResponseWriter, r *http.Request) {
path := r.URL.Query().Get("path") path := r.URL.Query().Get("path")
fpwd := r.Header.Get("fpwd")
haspwd := IsHavePwd(fpwd)
// 校验文件路径
if err := validateFilePath(path); err != nil { if err := validateFilePath(path); err != nil {
libs.HTTPError(w, http.StatusBadRequest, err.Error()) libs.HTTPError(w, http.StatusBadRequest, err.Error())
return return
} }
// 获取文件路径
basePath, err := libs.GetOsDir() basePath, err := libs.GetOsDir()
if err != nil { if err != nil {
libs.HTTPError(w, http.StatusInternalServerError, err.Error()) libs.HTTPError(w, http.StatusInternalServerError, err.Error())
return return
} }
// 读取内容
fileContent, err := ReadFile(basePath, path) fileContent, err := ReadFile(basePath, path)
if err != nil { if err != nil {
libs.HTTPError(w, http.StatusNotFound, err.Error()) libs.HTTPError(w, http.StatusNotFound, err.Error())
@ -184,11 +191,28 @@ func HandleReadFile(w http.ResponseWriter, r *http.Request) {
if !strings.HasPrefix(content, "link::") { if !strings.HasPrefix(content, "link::") {
content = base64.StdEncoding.EncodeToString(fileContent) 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 res := libs.APIResponse{Code: 0, Message: "success"}
//Data: string(fileContent), 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) json.NewEncoder(w).Encode(res)
} }
@ -523,3 +547,26 @@ func HandleDesktop(w http.ResponseWriter, r *http.Request) {
} }
libs.SuccessMsg(w, rootInfo, "success") 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)
}

20
godo/files/os.go

@ -24,6 +24,8 @@
package files package files
import ( import (
"crypto/md5"
"encoding/hex"
"fmt" "fmt"
"godo/libs" "godo/libs"
"io" "io"
@ -334,3 +336,21 @@ func CheckDeleteDesktop(filePath string) error {
} }
return nil 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
}
}

52
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
}
Loading…
Cancel
Save