Browse Source

change pwd

master
godo 7 months ago
parent
commit
af710d0c9a
  1. 297
      godo/files/pwd.go
  2. 198
      godo/files/pwdfile.go
  3. 61
      godo/files/pwdfile_test.go
  4. 3
      godo/libs/config.go
  5. 319
      godo/libs/filecode.go
  6. 66
      godo/libs/filecode_test.go

297
godo/files/pwd.go

@ -0,0 +1,297 @@
package files
import (
"encoding/base64"
"fmt"
"godo/libs"
"io"
"net/http"
"os"
"path/filepath"
"strings"
)
func HandleReadFile(w http.ResponseWriter, r *http.Request) {
path := r.URL.Query().Get("path")
if path == "" {
libs.ErrorMsg(w, "文件路径不能为空")
return
}
basePath, err := libs.GetOsDir()
if err != nil {
libs.ErrorMsg(w, err.Error())
return
}
fullFilePath := filepath.Join(basePath, path)
file, err := os.Open(fullFilePath)
if err != nil {
libs.ErrorMsg(w, err.Error())
return
}
fileData, err := io.ReadAll(file)
if err != nil {
libs.ErrorMsg(w, err.Error())
return
}
text := string(fileData)
//log.Printf("isPwd: %v", strData)
if strings.HasPrefix(text, "link::") {
libs.SuccessMsg(w, text, "文件读取成功")
return
}
// 判断是否为加密文件
isPwd := libs.IsEncryptedFile(text)
if !isPwd {
// 未加密文件,直接返回
text = base64.StdEncoding.EncodeToString(fileData)
// if len(text)%8 == 0 {
// text += " "
// }
//log.Printf("fileData: %s", content)
libs.SuccessMsg(w, text, "文件读取成功")
return
}
filePwd := r.Header.Get("pwd")
// 获取文件密钥
fileSecret := libs.GetConfigString("filePwd")
if filePwd == "" && fileSecret == "" {
libs.Error(w, "加密文件,需要密码", "needPwd")
return
}
decodeFile := ""
needPwd := false
if fileSecret != "" {
decodeFile, err = libs.DecodeFile(fileSecret, text)
if err != nil {
libs.Error(w, "请输入文件密码", "needPwd")
return
}
needPwd = true
}
if filePwd != "" && !needPwd {
decodeFile, err = libs.DecodeFile(filePwd, text)
if err != nil {
libs.Error(w, "文件密码输入错误", "needPwd")
return
}
}
// if len(decodeFile)%8 == 0 {
// decodeFile = decodeFile + " "
// }
libs.SuccessMsg(w, decodeFile, "加密文件读取成功")
}
func HandleWriteFile(w http.ResponseWriter, r *http.Request) {
path := r.URL.Query().Get("path")
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
}
fullFilePath := filepath.Join(basePath, path)
// 获取文件内容
fileContent, _, err := r.FormFile("content")
if err != nil {
libs.HTTPError(w, http.StatusBadRequest, err.Error())
return
}
defer fileContent.Close()
content, err := io.ReadAll(fileContent)
if err != nil {
libs.HTTPError(w, http.StatusInternalServerError, err.Error())
return
}
// 打开文件,如果不存在则创建
file, err := os.OpenFile(fullFilePath, os.O_RDWR|os.O_CREATE, 0644)
if err != nil {
libs.ErrorMsg(w, "Failed to create file.")
return
}
defer file.Close()
oldContent, err := io.ReadAll(file)
text := string(oldContent)
//log.Printf("text: %s", text)
if err != nil {
libs.ErrorMsg(w, err.Error())
return
}
isPwdFile := libs.IsEncryptedFile(text)
filePwd := r.Header.Get("pwd")
// 获取文件密钥
fileSecret := libs.GetConfigString("filePwd")
haslink := strings.HasPrefix(string(content), "link::")
//log.Printf("haslink:%v,fileSecret: %s,isPwdFile:%v,filePwd:%s", haslink, fileSecret, isPwdFile, filePwd)
needPwd := false
if !haslink {
needPwd = true
}
if fileSecret != "" || filePwd != "" {
needPwd = true
}
if isPwdFile {
needPwd = true
}
// 即不是加密用户又不是加密文件
if !needPwd {
// 直接写入新内容
file.Truncate(0)
file.Seek(0, 0)
_, err = file.Write(content)
if err != nil {
libs.ErrorMsg(w, "Failed to write file content.")
return
}
CheckAddDesktop(path)
libs.SuccessMsg(w, "", "文件写入成功")
return
}
//log.Printf("fileSecret:%s,filePwd:%s,ispwdfile:%v", fileSecret, filePwd, isPwdFile)
// 是加密文件,写入需继续加密
pwd := ""
if isPwdFile {
//先尝试系统解密
if fileSecret != "" {
_, err := libs.DecodeFile(fileSecret, text)
if err == nil {
pwd = fileSecret
}
}
//先用户输入解密
if pwd == "" && filePwd != "" {
_, err := libs.DecodeFile(filePwd, text)
if err == nil {
pwd = filePwd
}
}
} else {
// 不是加密文件,先判断是否有用户输入
if filePwd != "" {
pwd = filePwd
} else {
// 没有用户输入,则使用系统默认密码
if fileSecret != "" {
pwd = fileSecret
}
}
}
if pwd == "" {
libs.Error(w, "文件密码错误", "needPwd")
//log.Printf("pwd is empty, returning error")
return
}
//log.Printf("pwd: %s", pwd)
encryData, err := libs.EncodeFile(pwd, string(content))
if err != nil {
libs.ErrorMsg(w, err.Error())
return
}
// 清空文件内容
file.Truncate(0)
file.Seek(0, 0)
_, err = file.Write([]byte(encryData))
if err != nil {
libs.ErrorMsg(w, fmt.Sprintf("文件内容写入失败: %s", err.Error()))
return
}
CheckAddDesktop(path)
libs.SuccessMsg(w, "", "文件写入成功")
/*
//log.Printf("fileData: %s", string(fileData))
configPwd, ishas := libs.GetConfig("filePwd")
// 如果不是加密文件或者exe文件
if !ishas || strings.HasPrefix(string(fileData), "link::") {
// 没开启加密,直接明文写入
_, err := newFile.Write(fileData)
if err != nil {
libs.HTTPError(w, http.StatusInternalServerError, "数据写入失败")
return
}
err = CheckAddDesktop(path)
if err != nil {
log.Printf("Error adding file to desktop: %s", err.Error())
}
libs.SuccessMsg(w, "", "文件写入成功")
return
} else {
// 开启加密后,写入加密数据
configPwdStr, ok := configPwd.(string)
if !ok {
libs.HTTPError(w, http.StatusInternalServerError, "配置文件密码格式错误")
return
}
// 拼接密码和加密后的数据
passwordPrefix := fmt.Sprintf("@%s@", configPwdStr)
// _, err = newFile.WriteString(fmt.Sprintf("@%s@", configPwdStr))
// if err != nil {
// libs.HTTPError(w, http.StatusInternalServerError, "密码写入失败")
// return
// }
entryData, err := libs.EncryptData(fileData, []byte(configPwdStr))
if err != nil {
libs.HTTPError(w, http.StatusInternalServerError, "文件加密失败")
return
}
// 将密码前缀和加密数据拼接成一个完整的字节切片
completeData := []byte(passwordPrefix + string(entryData))
// 一次性写入文件
_, err = newFile.Write(completeData)
if err != nil {
libs.HTTPError(w, http.StatusInternalServerError, "文件写入失败")
return
}
err = CheckAddDesktop(path)
if err != nil {
log.Printf("Error adding file to desktop: %s", err.Error())
}
libs.SuccessMsg(w, "", "文件写入成功")
}*/
}
/*
func resEncode(w http.ResponseWriter, fileData []byte, filePwd string) {
decryptData, err := libs.DecryptData(fileData[34:], []byte(filePwd))
if err != nil {
libs.ErrorMsg(w, err.Error())
return
}
//content := base64.StdEncoding.EncodeToString(decryptData)
if len(decryptData)%8 == 0 {
decryptData = append(decryptData, ' ')
}
// res := libs.APIResponse{Message: "加密文件读取成功", Data: decryptData}
// json.NewEncoder(w).Encode(res)
libs.SuccessMsg(w, decryptData, "加密文件读取成功")
}
*/
func HandleSetFilePwd(w http.ResponseWriter, r *http.Request) {
Pwd := r.Header.Get("Pwd")
if Pwd == "" {
err := libs.DeleteConfig("filePwd")
if err != nil {
libs.ErrorMsg(w, fmt.Sprintf("取消加密失败:%s", err.Error()))
return
}
libs.SuccessMsg(w, nil, "取消加密成功")
return
}
err := libs.SetConfigByName("filePwd", Pwd)
if err != nil {
libs.ErrorMsg(w, err.Error())
return
}
libs.SuccessMsg(w, nil, "设置密码成功")
}

198
godo/files/pwdfile.go

@ -1,198 +0,0 @@
package files
import (
"fmt"
"godo/libs"
"io"
"log"
"net/http"
"os"
"path/filepath"
"strings"
)
func HandleWriteFile(w http.ResponseWriter, r *http.Request) {
path := r.URL.Query().Get("path")
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
}
fullFilePath := filepath.Join(basePath, path)
newFile, err := os.Create(fullFilePath)
if err != nil {
libs.HTTPError(w, http.StatusInternalServerError, err.Error())
return
}
defer newFile.Close()
// 获取文件内容
fileContent, _, err := r.FormFile("content")
if err != nil {
libs.HTTPError(w, http.StatusBadRequest, err.Error())
return
}
defer fileContent.Close()
fileData, err := io.ReadAll(fileContent)
if err != nil {
libs.HTTPError(w, http.StatusInternalServerError, err.Error())
return
}
//log.Printf("fileData: %s", string(fileData))
configPwd, ishas := libs.GetConfig("filePwd")
// 如果不是加密文件或者exe文件
if !ishas || strings.HasPrefix(string(fileData), "link::") {
// 没开启加密,直接明文写入
_, err := newFile.Write(fileData)
if err != nil {
libs.HTTPError(w, http.StatusInternalServerError, "数据写入失败")
return
}
err = CheckAddDesktop(path)
if err != nil {
log.Printf("Error adding file to desktop: %s", err.Error())
}
libs.SuccessMsg(w, "", "文件写入成功")
return
} else {
// 开启加密后,写入加密数据
configPwdStr, ok := configPwd.(string)
if !ok {
libs.HTTPError(w, http.StatusInternalServerError, "配置文件密码格式错误")
return
}
// 拼接密码和加密后的数据
passwordPrefix := fmt.Sprintf("@%s@", configPwdStr)
// _, err = newFile.WriteString(fmt.Sprintf("@%s@", configPwdStr))
// if err != nil {
// libs.HTTPError(w, http.StatusInternalServerError, "密码写入失败")
// return
// }
entryData, err := libs.EncryptData(fileData, []byte(configPwdStr))
if err != nil {
libs.HTTPError(w, http.StatusInternalServerError, "文件加密失败")
return
}
// 将密码前缀和加密数据拼接成一个完整的字节切片
completeData := []byte(passwordPrefix + string(entryData))
// 一次性写入文件
_, err = newFile.Write(completeData)
if err != nil {
libs.HTTPError(w, http.StatusInternalServerError, "文件写入失败")
return
}
err = CheckAddDesktop(path)
if err != nil {
log.Printf("Error adding file to desktop: %s", err.Error())
}
libs.SuccessMsg(w, "", "文件写入成功")
}
}
func HandleReadFile(w http.ResponseWriter, r *http.Request) {
path := r.URL.Query().Get("path")
if path == "" {
libs.ErrorMsg(w, "文件路径不能为空")
return
}
basePath, err := libs.GetOsDir()
if err != nil {
libs.ErrorMsg(w, err.Error())
return
}
fullFilePath := filepath.Join(basePath, path)
file, err := os.Open(fullFilePath)
if err != nil {
libs.ErrorMsg(w, err.Error())
return
}
fileData, err := io.ReadAll(file)
if err != nil {
libs.ErrorMsg(w, err.Error())
return
}
strData := string(fileData)
//log.Printf("isPwd: %v", strData)
if strings.HasPrefix(strData, "link::") {
libs.SuccessMsg(w, strData, "文件读取成功")
return
}
// 判断是否为加密文件
isPwd := IsPwdFile(fileData)
if !isPwd {
// 未加密文件,直接返回
//content := base64.StdEncoding.EncodeToString(fileData)
if len(fileData)%8 == 0 {
fileData = append(fileData, ' ')
}
//log.Printf("fileData: %s", content)
libs.SuccessMsg(w, fileData, "文件读取成功")
return
}
Pwd := r.Header.Get("Pwd")
filePwd := strData[1:33]
// Pwd为空,info密码与文件密码做比对
if Pwd == "" {
configPwd, ishas := libs.GetConfig("filePwd")
if !ishas {
libs.Error(w, "未设置密码", "needPwd")
return
}
configPwdStr, ok := configPwd.(string)
if !ok {
libs.Error(w, "后端配置文件密码格式错误", "needPwd")
return
}
// 校验密码
if filePwd != configPwdStr {
libs.Error(w, "密码错误,请输入正确的密码", "needPwd")
return
}
resEncode(w, fileData, filePwd)
} else {
// Pwd不为空,Pwd与文件密码做比对
if Pwd != filePwd {
libs.Error(w, "密码错误,请输入正确的密码", "needPwd")
return
}
resEncode(w, fileData, filePwd)
}
}
func resEncode(w http.ResponseWriter, fileData []byte, filePwd string) {
decryptData, err := libs.DecryptData(fileData[34:], []byte(filePwd))
if err != nil {
libs.ErrorMsg(w, err.Error())
return
}
//content := base64.StdEncoding.EncodeToString(decryptData)
if len(decryptData)%8 == 0 {
decryptData = append(decryptData, ' ')
}
// res := libs.APIResponse{Message: "加密文件读取成功", Data: decryptData}
// json.NewEncoder(w).Encode(res)
libs.SuccessMsg(w, decryptData, "加密文件读取成功")
}
func HandleSetFilePwd(w http.ResponseWriter, r *http.Request) {
Pwd := r.Header.Get("Pwd")
if Pwd == "" {
err := libs.DeleteConfig("filePwd")
if err != nil {
libs.ErrorMsg(w, fmt.Sprintf("取消加密失败:%s", err.Error()))
return
}
libs.SuccessMsg(w, nil, "取消加密成功")
return
}
err := libs.SetConfigByName("filePwd", Pwd)
if err != nil {
libs.ErrorMsg(w, err.Error())
return
}
libs.SuccessMsg(w, nil, "设置密码成功")
}

61
godo/files/pwdfile_test.go

@ -1,61 +0,0 @@
package files
import (
"fmt"
"godo/libs"
"io"
"os"
"testing"
)
func Test_WriteFile(t *testing.T) {
filePath := "test.txt"
content := "hello world"
configPwd := "b854f92a0bb8462ad75239152081c12b"
file, err := os.Create(filePath)
if err != nil {
t.Error(err)
}
defer file.Close()
_, err = file.WriteString(fmt.Sprintf("@%s@", configPwd))
if err != nil {
t.Error(err)
}
encryData, err := libs.EncryptData([]byte(content), []byte(configPwd))
if err != nil {
t.Error(err)
}
_, err = file.Write(encryData)
if err != nil {
t.Error(err)
}
}
func Test_ReadFile(t *testing.T) {
filePath := "test.txt"
pwd := "b854f92a0bb8462ad75239152081c12b"
file, err := os.Open(filePath)
if err != nil {
t.Error(err)
}
defer file.Close()
data, err := io.ReadAll(file)
if err != nil {
t.Error(err)
}
if pwd == "" {
fmt.Println(string(data))
return
}
realPwd := data[1:33]
if pwd != string(realPwd) {
t.Error("密码错误")
return
}
content := data[34:]
decryData, err := libs.DecryptData(content, []byte(pwd))
if err != nil {
t.Error(err)
}
fmt.Println(string(decryData))
}

3
godo/libs/config.go

@ -23,6 +23,7 @@ import (
"fmt"
"os"
"path/filepath"
"strings"
"sync"
)
@ -138,7 +139,7 @@ func GetConfigString(name string) string {
return ""
}
return stringValue
return strings.Trim(stringValue, " ")
}
func ExistConfig(Name string) bool {
_, exists := reqBodyMap.Load(Name)

319
godo/libs/filecode.go

@ -0,0 +1,319 @@
package libs
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/md5"
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"crypto/x509"
"encoding/base64"
"encoding/hex"
"fmt"
"io"
"log"
"strings"
)
func GetEncryptedCode(data string) (string, error) {
// 检查是否以 @ 开头
if !strings.HasPrefix(data, "@") {
return "", fmt.Errorf("invalid input format")
}
// 去掉开头的 @
data = data[1:]
// 分割加密的私钥和加密的文本
parts := strings.SplitN(data, "@", 2)
if len(parts) != 2 {
return "", fmt.Errorf("invalid input format")
}
return parts[0], nil
}
func IsEncryptedFile(data string) bool {
if len(data) < 2 {
return false
}
// 检查是否以 @ 开头
if !strings.HasPrefix(data, "@") {
return false
}
// 去掉开头的 @
data = data[1:]
// 分割加密的私钥和加密的文本
parts := strings.SplitN(data, "@", 2)
if len(parts) != 2 {
return false
}
// 检查加密私钥和加密文本是否都不为空
hexEncodedPrivateKey := parts[0]
// 检查十六进制字符串是否有效
base64Str, err := hex.DecodeString(hexEncodedPrivateKey)
if err != nil {
return false
}
// 尝试将 Base64 字符串解码为字节切片
_, err = base64.URLEncoding.DecodeString(string(base64Str))
return err == nil
}
// EncodeFile 加密文件
func EncodeFile(password string, longText string) (string, error) {
privateKey, publicKey, err := GenerateRSAKeyPair(1024)
if err != nil {
fmt.Println("生成RSA密钥对失败:", err)
return "", err
}
// 使用公钥加密
encryptedText := ""
if len(longText) > 0 {
encryptedText, err = EncryptLongText(longText, publicKey)
if err != nil {
return "", fmt.Errorf("加密失败:%v", err)
}
}
pwd, err := hashAndMD5(password)
if err != nil {
return "", fmt.Errorf("加密密码失败:%v", err)
}
encryptedPrivateKey, err := EncryptPrivateKey(privateKey, pwd)
if err != nil {
fmt.Println("加密私钥失败:", err)
return "", fmt.Errorf("加密私钥失败")
}
// 对 encryptedPrivateKey 进行 Base64 编码
base64EncryptedPrivateKey := base64.URLEncoding.EncodeToString([]byte(encryptedPrivateKey))
// 将 Base64 编码后的字符串转换为十六进制字符串
hexEncodedPrivateKey := hex.EncodeToString([]byte(base64EncryptedPrivateKey))
return "@" + hexEncodedPrivateKey + "@" + encryptedText, nil
}
// DecodeFile 解密文件
func DecodeFile(password string, encryptedData string) (string, error) {
// 去掉开头的@
// log.Printf("encryptedData: %s", encryptedData)
if !strings.HasPrefix(encryptedData, "@") {
return "", fmt.Errorf("无效的加密数据格式")
}
encryptedData = encryptedData[1:]
// 分割加密的私钥和加密的文本
parts := strings.SplitN(encryptedData, "@", 2)
log.Printf("parts:%v", parts)
if len(parts) == 1 {
return "", nil
}
if len(parts) != 2 {
return "", fmt.Errorf("无效的加密数据格式")
}
hexEncodedPrivateKey := parts[0]
encryptedText := parts[1]
if len(encryptedText) == 0 {
return "", nil
}
// 将十六进制字符串转换回 Base64 编码字符串
base64DecodedPrivateKey, err := hex.DecodeString(hexEncodedPrivateKey)
if err != nil {
return "", fmt.Errorf("十六进制字符串解码失败:%v", err)
}
// 将 Base64 编码字符串解码回原始的 encryptedPrivateKey
encryptedPrivateKey, err := base64.URLEncoding.DecodeString(string(base64DecodedPrivateKey))
if err != nil {
return "", fmt.Errorf("Base64字符串解码失败:%v", err)
}
pwd, err := hashAndMD5(password)
if err != nil {
return "", fmt.Errorf("加密密码失败:%v", err)
}
// 解密私钥
privateKey, err := DecryptPrivateKey(string(encryptedPrivateKey), pwd)
if err != nil {
return "", fmt.Errorf("解密私钥失败:%v", err)
}
// 解密文本
decryptedText, err := DecryptLongText(encryptedText, privateKey)
if err != nil {
return "", fmt.Errorf("解密文本失败:%v", err)
}
return decryptedText, nil
}
// GenerateRSAKeyPair 生成RSA密钥对
func GenerateRSAKeyPair(bits int) (*rsa.PrivateKey, *rsa.PublicKey, error) {
privateKey, err := rsa.GenerateKey(rand.Reader, bits)
if err != nil {
return nil, nil, err
}
publicKey := &privateKey.PublicKey
return privateKey, publicKey, nil
}
func GenertePrivateKey(password string, privateKey *rsa.PrivateKey) (*rsa.PrivateKey, error) {
encryptedPrivateKey, err := EncryptPrivateKey(privateKey, password)
if err != nil {
fmt.Println("加密私钥失败:", err)
return nil, fmt.Errorf("加密私钥失败")
}
decryptedPrivateKey, err := DecryptPrivateKey(encryptedPrivateKey, password)
if err != nil {
fmt.Println("解密私钥失败:", err)
return nil, fmt.Errorf("加密私钥失败")
}
return decryptedPrivateKey, nil
}
// EncryptWithPublicKey 使用公钥加密数据
func EncryptWithPublicKey(data []byte, publicKey *rsa.PublicKey) (string, error) {
ciphertext, err := rsa.EncryptOAEP(sha256.New(), rand.Reader, publicKey, data, nil)
if err != nil {
return "", err
}
return base64.URLEncoding.EncodeToString(ciphertext), nil
}
// DecryptWithPrivateKey 使用私钥解密数据
func DecryptWithPrivateKey(encryptedData string, privateKey *rsa.PrivateKey) ([]byte, error) {
ciphertext, err := base64.URLEncoding.DecodeString(encryptedData)
if err != nil {
return nil, err
}
plaintext, err := rsa.DecryptOAEP(sha256.New(), rand.Reader, privateKey, ciphertext, nil)
if err != nil {
return nil, err
}
return plaintext, nil
}
// hashAndMD5 使用 MD5 哈希密码
func hashAndMD5(password string) (string, error) {
hasher := md5.New()
_, err := hasher.Write([]byte(password))
if err != nil {
return "", err
}
return hex.EncodeToString(hasher.Sum(nil)), nil
}
// EncryptLongText 使用公钥加密长文本
func EncryptLongText(longText string, publicKey *rsa.PublicKey) (string, error) {
// 分块加密
blockSize := publicKey.N.BitLen()/8 - 2*sha256.Size - 2
chunks := splitIntoChunks([]byte(longText), blockSize)
var encryptedChunks []string
for _, chunk := range chunks {
encryptedChunk, err := EncryptWithPublicKey(chunk, publicKey)
if err != nil {
return "", err
}
encryptedChunks = append(encryptedChunks, encryptedChunk)
}
return strings.Join(encryptedChunks, ":"), nil
}
// DecryptLongText 使用私钥解密长文本
func DecryptLongText(encryptedLongText string, privateKey *rsa.PrivateKey) (string, error) {
// 分块解密
encryptedChunks := strings.Split(encryptedLongText, ":")
var decryptedChunks [][]byte
for _, encryptedChunk := range encryptedChunks {
decryptedChunk, err := DecryptWithPrivateKey(encryptedChunk, privateKey)
if err != nil {
return "", err
}
decryptedChunks = append(decryptedChunks, decryptedChunk)
}
return string(bytes.Join(decryptedChunks, nil)), nil
}
// splitIntoChunks 将数据分割成指定大小的块
func splitIntoChunks(data []byte, chunkSize int) [][]byte {
var chunks [][]byte
for i := 0; i < len(data); i += chunkSize {
end := i + chunkSize
if end > len(data) {
end = len(data)
}
chunks = append(chunks, data[i:end])
}
return chunks
}
// EncryptPrivateKey 使用AES加密RSA私钥
func EncryptPrivateKey(privateKey *rsa.PrivateKey, password string) (string, error) {
privateKeyBytes := x509.MarshalPKCS1PrivateKey(privateKey)
key := []byte(password)
block, err := aes.NewCipher(key)
if err != nil {
return "", err
}
gcm, err := cipher.NewGCM(block)
if err != nil {
return "", err
}
nonce := make([]byte, gcm.NonceSize())
if _, err = io.ReadFull(rand.Reader, nonce); err != nil {
return "", err
}
ciphertext := gcm.Seal(nonce, nonce, privateKeyBytes, nil)
return base64.URLEncoding.EncodeToString(ciphertext), nil
}
// DecryptPrivateKey 使用AES解密RSA私钥
func DecryptPrivateKey(encryptedPrivateKey string, password string) (*rsa.PrivateKey, error) {
ciphertext, err := base64.URLEncoding.DecodeString(encryptedPrivateKey)
if err != nil {
return nil, err
}
key := []byte(password)
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
gcm, err := cipher.NewGCM(block)
if err != nil {
return nil, err
}
nonceSize := gcm.NonceSize()
if len(ciphertext) < nonceSize {
return nil, fmt.Errorf("ciphertext too short")
}
nonce, ciphertext := ciphertext[:nonceSize], ciphertext[nonceSize:]
privateKeyBytes, err := gcm.Open(nil, nonce, ciphertext, nil)
if err != nil {
return nil, err
}
privateKey, err := x509.ParsePKCS1PrivateKey(privateKeyBytes)
if err != nil {
return nil, err
}
return privateKey, nil
}

66
godo/libs/filecode_test.go

@ -0,0 +1,66 @@
package libs
import (
"strings"
"testing"
)
func TestEncodeFile(t *testing.T) {
password := "testpassword"
longText := "This is a test message."
encryptedData, err := EncodeFile(password, longText)
if err != nil {
t.Fatalf("EncodeFile failed: %v", err)
}
if !strings.HasPrefix(encryptedData, "@") {
t.Errorf("Encoded data does not start with '@': %s", encryptedData)
}
parts := strings.SplitN(encryptedData[1:], "@", 2)
if len(parts) != 2 {
t.Errorf("Encoded data format is incorrect: %s", encryptedData)
}
if !IsEncryptedFile(encryptedData) {
t.Errorf("IsEncryptedFile returned false for valid encrypted data: %s", encryptedData)
}
}
func TestDecodeFile(t *testing.T) {
password := "96e79218965eb72c92a549dd5a330112"
longText := "This is a test message."
encryptedData, err := EncodeFile(password, longText)
if err != nil {
t.Fatalf("EncodeFile failed: %v", err)
}
decryptedText, err := DecodeFile(password, encryptedData)
if err != nil {
t.Fatalf("DecodeFile failed: %v", err)
}
if decryptedText != longText {
t.Errorf("Decrypted text does not match original: expected '%s', got '%s'", longText, decryptedText)
}
}
func TestIsEncryptedFile(t *testing.T) {
password := "testpassword"
longText := "This is a test message."
encryptedData, err := EncodeFile(password, longText)
if err != nil {
t.Fatalf("EncodeFile failed: %v", err)
}
if !IsEncryptedFile(encryptedData) {
t.Errorf("IsEncryptedFile returned false for valid encrypted data: %s", encryptedData)
}
invalidData := "Invalid@Data"
if IsEncryptedFile(invalidData) {
t.Errorf("IsEncryptedFile returned true for invalid encrypted data: %s", invalidData)
}
}
Loading…
Cancel
Save