目的:
一、部分私人文件不想让别人看到, Linux下又不能用Windows上的加解密工具 (也许有现成的东西, 只是我自己不知道吧, 不过也懒得搜了)
二、最近再看APUE, 写点代码当实践与复习 (发现又开始忘了)
算法:
文件字节与密钥顺序进行异或
功能:
一、对指定文件加密或解密
二、对指定文件夹中所有文件加密或解密
缺陷:
一、单个文件必须小于2G
二、由于是直接在文件上做修改, 故而可能因为某些特殊原因(停电等造成的程序非正常终止)致使文件被破坏
注意:
如果忘了密钥, 猜测时一定要注意, 比如用XXX解密, 发现没解密出原始数据, 记得要再用一次XXX解密成猜测前的状态
#include <stdio.h> #include <fcntl.h> #include <assert.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <dirent.h> #include <sys/stat.h> #define PWD_MAX_LEN (64) int encry_file(const char * filename, const char * password, int pwdlen) { int i; int n; int filedes; long position; char buffer[BUFSIZ]; char cwd[PATH_MAX + 1]; if (getcwd(cwd, PATH_MAX + 1) == NULL) { printf("getcwd error\n"); exit(127); } if ((filedes = open(filename, O_RDWR, S_IRWXU | S_IRWXG | S_IRWXO)) == -1) { printf("open failed for \"%s/%s\"\n", cwd, filename); exit(127); } position = 0; while ((n = read(filedes, buffer, BUFSIZ)) > 0) { for (i = 0; i < n; ++i) { buffer[i] ^= password[n % pwdlen]; } lseek(filedes, position, SEEK_SET); if (write(filedes, buffer, n) != n) { printf("write error for \"%s/%s\"\n", cwd, filename); exit(127); } position += n; } if (n < 0) { printf("read error for \"%s/%s\"\n", cwd, filename); exit(127); } close(filedes); return 0; } int encry_dir(const char * dirname, const char * password, int pwdlen) { DIR * dp; struct dirent * dirp; struct stat statbuf; char cwd[PATH_MAX + 1]; if ((dp = opendir(dirname)) == NULL) { printf("opendir failed for \"%s/%s\"\n", cwd, dirname); exit(127); } while ((dirp = readdir(dp)) != NULL) { if (strcmp(dirp->d_name, ".") == 0 || strcmp(dirp->d_name, "..") == 0) { continue; } if (getcwd(cwd, PATH_MAX + 1) == NULL) { printf("getcwd error\n"); exit(127); } if (chdir(dirname) == -1) { printf("chdir error for \"%s\"\n", dirname); exit(127); } if (lstat(dirp->d_name, &statbuf) == -1) { printf("lstat failed for \"%s/%s\"\n", cwd, dirp->d_name); exit(127); } if (S_ISREG(statbuf.st_mode)) { encry_file(dirp->d_name, password, pwdlen); } else if (S_ISDIR(statbuf.st_mode)) { encry_dir(dirp->d_name, password, pwdlen); } if (chdir(cwd) == -1) { printf("chdir error for \"%s\"\n", cwd); exit(127); } } closedir(dp); return 0; } int main(void) { int i; int pwdlen; char * p; char filename[PATH_MAX]; char pathname[PATH_MAX + 1]; char password[PWD_MAX_LEN]; char pwdcheck[PWD_MAX_LEN]; char cwd[PATH_MAX + 1]; struct stat statbuf; printf("input file/directory name:\n"); if (fgets(pathname, PATH_MAX + 1, stdin) == NULL) { printf("fgets error\n"); exit(127); } i = strlen(pathname); assert(i >= 1); if (pathname[i - 1] == '\n') { pathname[i - 1] = '\0'; } if (lstat(pathname, &statbuf) == -1) { printf("lstat failed for \"%s\"\n", pathname); exit(127); } printf("input password:\n"); scanf("%s", password); printf("input password again:\n"); scanf("%s", pwdcheck); password[sizeof(password) - 1] = '\0'; pwdcheck[sizeof(pwdcheck) - 1] = '\0'; pwdlen = strlen(password); if (pwdlen == 0 || strcmp(password, pwdcheck) != 0) { printf("password error\n"); exit(127); } if (getcwd(cwd, PATH_MAX + 1) == NULL) { printf("getcwd error\n"); exit(127); } if (S_ISREG(statbuf.st_mode)) { if ((p = strrchr(pathname, '/')) != NULL) { strcpy(filename, ++p); *p = '\0'; } else { strcpy(filename, pathname); strcpy(pathname, cwd); } if (chdir(pathname) == -1) { printf("chdir error for \"%s\"\n", pathname); exit(127); } encry_file(filename, password, pwdlen); if (chdir(cwd) == -1) { printf("chdir error for \"%s\"\n", cwd); exit(127); } } else if (S_ISDIR(statbuf.st_mode)) { if (chdir(pathname) == -1) { printf("chdir error for \"%s\"\n", pathname); exit(127); } encry_dir(".", password, pwdlen); if (chdir(cwd) == -1) { printf("chdir error for \"%s\"\n", cwd); exit(127); } } else { printf("no file need to encry\n"); } exit(0); }