golang递归加解密指定文件夹下所有文件

package main
 
import (
	"bufio"
	"crypto/sha256"
	"database/sql"
	"encoding/hex"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"strings"
	"sync"
	"time"
 
	_ "./go-sqlite3"
)
 
// 加密字符串
func GetNegation(strb []byte) []byte {
	var strsN []byte
	for i, b := range strb {
		ii := i ^ (i % 3)
		strsN = append(strsN, ^b-uint8(ii))
	}
	return strsN
}
 
//md5值,参数为字符串,输出md5字符串
func GetSha256(str string) string {
	strM := sha256.Sum256([]byte(str))
	return hex.EncodeToString(strM[:])
}
 
// 保存修改后的文件,文件名为md5值,内容为1024字节后内容
func SaveFile(fileMd5 string, content []byte) bool {
	contentNeg := GetNegation(content)
	err := ioutil.WriteFile(fileMd5, contentNeg, 0777) //将源文件,写入目标文件
	if err != nil {
		return false
	}
	return true
}
 
//返回子文件夹

func GetAllDir(pathname string, s []string) ([]string, error) {
	rd, err := ioutil.ReadDir(pathname)
	if err != nil {
		fmt.Println("read dir fail:", err)
		return s, err
	}
	for _, fi := range rd {
		if fi.IsDir() {
			fullDir := pathname + "/" + fi.Name()
			s = append(s, fullDir)
			s, err = GetAllDir(fullDir, s)
			if err != nil {
				fmt.Println("read dir fail:", err)
				return s, err
			}
		} 
	}
	return s, nil
}

//返回文件名列表
func ReadFolder(fileDir string, extlist []string) []string {
	var fileNameList []string
	files, _ := ioutil.ReadDir(fileDir) //读取目录
	for _, onefile := range files {     //遍历目录下文件
		if !onefile.IsDir() { //是文件
			fileName := onefile.Name()
			fileNames := strings.Split(fileName, ".")
			ext := fileNames[len(fileNames)-1]
			for _, e := range extlist {
				if strings.EqualFold(ext, e) {
					fileNameList = append(fileNameList, fileName)
					break
				}
			}
		}
	}
	return fileNameList
}
 
//返回加密后的文件列表
func ReadFolderNeg(fileDir string) []string {
	var fileNameList []string
	files, _ := ioutil.ReadDir(fileDir) //读取目录
	for _, onefile := range files {     //遍历目录下文件
		if !onefile.IsDir() { //是文件
			fileName := onefile.Name()
			if len(fileName) == 64 {
				fileNameList = append(fileNameList, fileName)
			}
		}
	}
	return fileNameList
}
 
//删除文件
func DelFile(file *os.File, path string, jiajie string) {
	if file != nil {
		file.Close()
	}
	if IsFileExist(path) {
		err := os.Remove(path)
		if err == nil {
			// fmt.Printf("%s -> %s删除成功!\n", path, jiajie)
			return
		}
	}
	// fmt.Printf("%s -> %s删除失败!\n", path, jiajie)
}
 
//判断文件是否存在
func IsFileExist(path string) bool {
	fileInfo, err := os.Stat(path)
	if err != nil {
		return false
	}
	if fileInfo.IsDir() { //是目录
		return false
	}
	return true
}
 
//错误处理
func CheckErr(err error) {
	if err != nil {
		panic(err)
	}
}
 
//保存到数据库
func SaveFileToDb(db *sql.DB, fileName256 string, fileName string, content string, password string) bool {
	stmt, err := db.Prepare("insert into secret_key(fileName256,fileName,content,password) values(?,?,?,?)")
	defer func() {
		if stmt != nil {
			stmt.Close()
		}
	}()
	CheckErr(err)
	rwm.Lock()
	res, err := stmt.Exec(fileName256, fileName, content, password)
	rwm.Unlock()
	if stmt != nil {
		stmt.Close()
	}
	CheckErr(err)
	id, err := res.LastInsertId()
	CheckErr(err)
	if id > 0 {
		return true
	}
	return false
}
 
//数据库搜索
func selectDb(db *sql.DB, sql string) (string, string, string, string) {
	rows, err := db.Query(sql)
	defer func() {
		if rows != nil {
			rows.Close()
		}
	}()
	CheckErr(err)
	var (
		uid          int
		fileNameb256 string
		fileNameb    string
		contentb     string
		password     string
	)
	rows.Next()
	rows.Scan(&uid, &fileNameb256, &fileNameb, &contentb, &password)
	return fileNameb256, fileNameb, contentb, password
}
 
//删除数据项
func DelData(db *sql.DB, fileName256 string) {
	stmt3, err := db.Prepare("delete from secret_key where fileName256=?")
	defer func() {
		if stmt3 != nil {
			stmt3.Close()
		}
	}()
	CheckErr(err)
	rwm.Lock() //加锁
	_, err = stmt3.Exec(fileName256)
	rwm.Unlock() //解锁
	CheckErr(err)
}
 
//加密过程
func encrypt(fileDir string, fileName string, db *sql.DB, encryptPw string, jiajie string) {
	// delfileName := fileName
	waiB := 0
	fileSha256 := GetSha256(fileName) //文件名改为哈希256
	sql1 := fmt.Sprintf(`select * from secret_key where fileName256="%s"`, fileSha256)
	sfileSha256, _, sbeforeNegation, _ := selectDb(db, sql1) //查找数据库文件名是否已存在
	filePath := fileDir + "/" + fileName
	srcFile, err := os.Open(filePath)                        //读取原文件
	if err != nil {                                          //读取错误
		// fmt.Println(fileName, " -> 打开错误!")
		if waiB == 0 {
			waitgroup.Done()
			waiB++
		}
		return
	}
	//
	fileSha256Path := fileDir + "/" +fileSha256
	dstFile, err2 := os.OpenFile(fileSha256Path, os.O_WRONLY|os.O_CREATE, 0666) //加密后的文件
	if err2 != nil {                                                        //读取错误
		// fmt.Println(fileSha256Path, " -> 打开错误!")
		if waiB == 0 {
			waitgroup.Done()
			waiB++
		}
		return
	}
	defer func() { //关闭打开的文件
		srcFile.Close()
		dstFile.Close()
	}()
	r := bufio.NewReader(srcFile) //读文件
	w := bufio.NewWriter(dstFile) //写文件
	buf := make([]byte, 4096)     //读写缓冲区
	var sBuf []byte               //加密后的数据
	bbb := 0                      //计数器,第一次读到的文件内容存储到数据库,后面内容存储到文件中
	for {
		n, err3 := r.Read(buf) //读文件到缓冲区
		if err3 != nil {       //读文件错误
			if err3 == io.EOF { //读取完毕
				w.Flush()
				fmt.Println(filePath, " -> 完成!")
				DelFile(srcFile, filePath, jiajie) //删除原文件
			} else { //非读取完毕错误
				// fmt.Println(fileName, " -> 读取错误!")
 
			}
			if waiB == 0 {
				waitgroup.Done()
				waiB++
			}
			return
		} else { //读取正常
			if bbb == 0 {
				//加密保存数据库
				beforeNegation := string(GetNegation(buf[:n])) // 加密数据库文件内容
				if sfileSha256 != "" {
					if sbeforeNegation == beforeNegation { //数据库有相同内容
						if IsFileExist(sfileSha256) { //加密后文件存在
							fmt.Println(fileName, ":文件已加密!")
							DelFile(srcFile, filePath, jiajie) //直接删除原文件
							if waiB == 0 {
								waitgroup.Done()
								waiB++
							}
							return
						}
					} else { //数据库没有相同内容,只是文件名相同
						ns := time.Now().UnixNano()
						fileName = fmt.Sprintf("%v%s", ns, fileName) // 重命名文件名
						fileSha256 = GetSha256(fileName)             //文件名哈希256
					}
				}
				fileNegation := string(GetNegation([]byte(fileName)))                     //原文件名加密存储到数据库
				password := GetSha256(encryptPw)                                            //密码的哈希值
				if SaveFileToDb(db, fileSha256, fileNegation, beforeNegation, password) { //保存内容到数据库
					// fmt.Println(fileName, " -> 数据库保存成功!")
				}
			} else {
				//加密保存文件
				sBuf = GetNegation(buf[:n]) //加密数据
				_, err4 := w.Write(sBuf)    //保存数据
				if err4 != nil {            //保存错误
					fmt.Println(fileSha256, " -> 保存错误!")
					if waiB == 0 {
						waitgroup.Done()
						waiB++
					}
					return
				}
			}
		}
		bbb++ //计数器加一
	}
}
 
// 解密过程
func decrypt(fileDir string, fileName string, db *sql.DB, decryptPw string, jiajie string) {
	sql := fmt.Sprintf(`select * from secret_key where fileName256="%s"`, fileName)
	fileNameDb256, fileNameDb, contentDb, passwordDb := selectDb(db, sql) //查找数据库
	waiB := 0
	fileNamePath := fileDir + "/" +fileName
	fileNameDb256Path := fileDir + "/" + fileNameDb256
	if fileNameDb256 != "" && GetSha256(decryptPw) == passwordDb { //数据存在加密文件,并验证密码
		fileNameDbs := string(GetNegation([]byte(fileNameDb))) //解密后文件名
		contentDbs := GetNegation([]byte(contentDb))           //解密后前半内容
		//文件名已存在,判断前半内容是否相同,若相同,直接删除加密文件、数据库内容
		//
		fileNameDbsPath := fileDir + "/" + fileNameDbs
		if IsFileExist(fileNameDbs) { //解密后文件名已存在
			srcFile, err := os.Open(fileNameDbsPath) //读取原文件
			if err != nil {                      //读取错误
				// fmt.Println(fileNameDbsPath, " -> 打开错误!")
				if waiB == 0 {
					waitgroup.Done()
					waiB++
				}
				return
			}
			defer func() { //关闭打开的文件
				srcFile.Close()
			}()
			r := bufio.NewReader(srcFile) //读文件
			buf := make([]byte, 4096)     //读写缓冲区
			n, err3 := r.Read(buf)        //读文件到缓冲区
			if err3 != nil {              //读文件错误
				// fmt.Println(fileNameDbsPath, " -> 读取错误!")
				if waiB == 0 {
					waitgroup.Done()
					waiB++
				}
				return
			} else { //读取正常
				if string(buf[:n]) == string(contentDbs) {
					//解密后文件已存在

					DelData(db, fileNameDb256) //解密文件已存在,删除数据库中内容
					if waiB == 0 {
						waitgroup.Done()
						waiB++
					}
					return
				} else {
					//解密后文件名存在,但是文件内容不同
					ns := time.Now().UnixNano()
					fileNameDbs = fmt.Sprintf("%v%s", ns, fileName) // 重命名文件名
				}
			}
		}
		f, err2 := os.Open(fileNamePath)
		if err2 != nil {
			// fmt.Println(fileNamePath, " -> 打开错误!")
			if waiB == 0 {
				waitgroup.Done()
				waiB++
			}
			return
		}
		f2, err3 := os.OpenFile(fileNameDbsPath, os.O_WRONLY|os.O_CREATE, 0666)
		if err3 != nil {
			// fmt.Println(fileNameDbsPath, " -> 打开错误!")
			if waiB == 0 {
				waitgroup.Done()
				waiB++
			}
			return
		}
		defer func() {
			f.Close()
			f2.Close()
		}()
		r := bufio.NewReader(f)
		w := bufio.NewWriter(f2)
		buf2 := make([]byte, 4096)
		ddd := 0
		var sBuf []byte
		for {
			if ddd == 0 {
				w.Write(contentDbs)
			} else {
				n, err4 := r.Read(buf2)
				if err4 != nil {
					if err4 == io.EOF {
						w.Flush()
						fmt.Println(fileNamePath, " -> 完成!")
						DelFile(f, fileNameDb256Path, jiajie) //解密成功,删除加密后的文件
 
					} else { //非读取完毕错误
						// fmt.Println(fileName, " -> 读取错误!")
					}
					if waiB == 0 {
						waitgroup.Done()
						waiB++
					}
					return
				} else {
					sBuf = GetNegation(buf2[:n]) //解密数据
					w.Write(sBuf)
				}
			}
			ddd++
		}
	} else {
		fmt.Println(fileNamePath, " -> 密码错误!")
	}
	if waiB == 0 {
		waitgroup.Done()
		waiB++
	}
}
 
var waitgroup sync.WaitGroup
var rwm sync.RWMutex
 
//主函数
func main() {
	db, err := sql.Open("sqlite3", "./重要勿删")
	defer db.Close()
	if err != nil {
		// fmt.Println("打开数据库错误!")
	}
	sqlTable := `
        CREATE TABLE IF NOT EXISTS secret_key(
            uid INTEGER PRIMARY KEY AUTOINCREMENT,
            fileName256 VARCHAR NULL,
            fileName VARCHAR NULL,
	        content VARCHAR NULL,
			password VARCHAR NULL
        );
	`
	db.Exec(sqlTable)
	//fileDir := "./test"         //需要加密的相对路径
	var selectMenus string //选择菜单
	var extlist []string   //加密扩展名列表
	var decryptPw string
	var encryptPw string
	var fileDir string
	var DirList [] string
	for {
		selectMenus = ""
		fmt.Println("\n\n************************* 加密、解密小程序 *************************")
		fmt.Print("1. 加密    2. 解密    3. 退出\n请输入数字并回车:")
		fmt.Scanln(&selectMenus) //主菜单
		if selectMenus == "1" {  //选择加密
			extlist = []string{"txt","doc","docx","xls","xlsx","pptx","pdf","png","jpg","jpeg","mp4","zip","go","c","exe"}
			fmt.Print("请输入要加密的文件夹:")
			fmt.Scanln(&fileDir)
			fmt.Print("请输入加密密码:")
			fmt.Scanln(&encryptPw)
			/*
			for _, fileName := range ReadFolder(fileDir, extlist) {
				waitgroup.Add(1)
				go encrypt(fileDir,fileName, db, encryptPw, "加密")
			}
			waitgroup.Wait()
			*/
			DirList = []string{} //清空
			DirList, _= GetAllDir(fileDir,DirList)
			DirList = append(DirList, fileDir)
			for i := range DirList{
				for _, fileName := range ReadFolder(DirList[i], extlist){
					waitgroup.Add(1)
					go encrypt(DirList[i],fileName, db, encryptPw, "加密")
				}
				waitgroup.Wait() 
			}

		} else if selectMenus == "2" {
			fmt.Print("请输入要解密的文件夹:")
			fmt.Scanln(&fileDir)
			fmt.Print("请输入解密密码:")
			fmt.Scan(&decryptPw)
			
			/*
			for _, fileName := range ReadFolderNeg(fileDir) { //读取已加密的文件列表
				waitgroup.Add(1)
				go decrypt(fileDir, fileName, db, decryptPw, "解密") //解密
			}
			waitgroup.Wait()
			*/
			DirList = []string{} //清空
			DirList, _= GetAllDir(fileDir,DirList)
			DirList = append(DirList, fileDir)
			fmt.Println(DirList)
			for i := range DirList{
				for _, fileName := range ReadFolderNeg(DirList[i]){
					waitgroup.Add(1)
					go decrypt(DirList[i],fileName, db, decryptPw, "解密")
				}
				waitgroup.Wait() 
			}
			
		} else if selectMenus == "3" {
			break
		} else {
			fmt.Println("输入错误,请重新选择!")
		}
	}
}

需要下载依赖

github.com/mattn/go-sqlite3

可以在此处继续添加各种格式的文件

extlist = []string{"txt","doc","docx","xls","xlsx","pptx","pdf","png","jpg","jpeg","mp4","zip","go","c","exe"}

编译成exe

go build en_decrypt.go

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:深蓝海洋 设计师:CSDN官方博客 返回首页
评论

打赏作者

丘比特爱睡觉

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值