现在的位置: 首页 > 综合 > 正文

简单的加解密工具

2013年02月17日 ⁄ 综合 ⁄ 共 3317字 ⁄ 字号 评论关闭

目的:
        一、部分私人文件不想让别人看到, 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);
}

抱歉!评论已关闭.