Chinaunix首页 | 论坛 | 博客
  • 博客访问: 265183
  • 博文数量: 74
  • 博客积分: 1470
  • 博客等级: 上尉
  • 技术积分: 793
  • 用 户 组: 普通用户
  • 注册时间: 2008-11-25 21:01
文章分类

全部博文(74)

文章存档

2011年(1)

2010年(32)

2009年(32)

2008年(9)

我的朋友

分类: C/C++

2010-05-01 14:11:26

以前在《Linux库函数encrypt的用法http://blog.chinaunix.net/u2/86590/showart.php?id=1725233
中说过linux库函数中自带的3-des加密函数的用法。这篇就进一步用这个加密算法,对目录中的文件进行进行加密,同时还要保持原有的目录结构。
crypt.h
--------------------------------------

#ifndef PF_CRYPT_H
#define PF_CRYPT_H

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
void stringtobyte(char *sptr,int slen,char *bptr);
void bytetostring(char* bptr,int blen,char* sptr);
int pad(char* buf,int slen);
int unpad(char *buf, int slen);
int DEScrypt(char* str, int slen,char* key,int flag);

#endif


crypt.c
-----------------------------------------

#include "crypt.h"

void stringtobyte(char *sptr,int slen,char *bptr)
{
    int i,j,op,tmp;
    for(i=0;i<slen;i++)
    {
        op=0x80;
        for(j=0;j<8;j++)
        {
            tmp=sptr[i]&op;
            if(tmp == 0)
                bptr[i*8+j] = 0x0;
            else
                bptr[i*8+j] = 0x1;
            op>>=1;
        }
    }
}

void bytetostring(char* bptr,int blen,char* sptr)
{
    int j,op;

    op=0;
    for(j=0;j<blen;j++)
    {
        op|=bptr[j];
        if (j%8 == 7)
        {
            sptr[(j+1)/8-1]=op;
            op=0;
        }
        else
            op<<=1;
    }
}

int pad(char* buf,int slen)
{
    int padlen=0,i;
    if(slen%8 != 0)
        padlen = 8-slen%8;
    for(i=0;i<padlen;i++)
        buf[slen+i]='$';
    return slen+padlen;
}

int unpad(char *buf,int slen)
{
    int tlen=slen;
    while(1)
    {
        if(buf[tlen-1]=='$')
            tlen--;
        else
            return tlen;
    }
}

int DEScrypt(char* src,int slen,char* key,int flag)
{
    char* ptr,*bitbuf,bytekey[64];
    int i,blen,tlen;

    
//the key

    stringtobyte(key,8,bytekey);
    setkey(bytekey);

    tlen=slen;
    if(!flag)
//encrypt

        tlen=pad(src,slen);
//padding

    
//change char to byte

    blen=tlen*8;
    bitbuf=(char*)malloc(blen*sizeof(char));
    stringtobyte(src,tlen,bitbuf);
    
//crypt

    for(i=0;i<blen;i+=64)
    {
        ptr=&bitbuf[i];
        encrypt(ptr,flag);
    }
    bytetostring(bitbuf,blen,src);
    if(flag)
//decrypt

        tlen=unpad(src,slen);
//unpadding

    free(bitbuf);
    return tlen;
}



encrypt.h
--------------------------------------------

#include <dirent.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "crypt.h"

#define CRYPT_BLOCK_SIZE 800
char orgin_path[PATH_MAX];
char encry_path[PATH_MAX];
const char* _cryp="_cryp";
int count = 0;

void dir_scan(char *path, char *file);
void check_make_path(char* filename);
int get_mode(char* filepath);
void crypt(char *src,char* dst);
void readfile(int fd,char* buffer,int size);
void writefile(int fd,char* buffer,int size);
void err_sys(char* str);



encrypt.c
---------------------------------------------

#include "encrypt.h"

int main(int argc,char *argv[])
{
    if(argc != 2)
        err_sys("Usage: ./encyrpt direct");

    strcpy(orgin_path, argv[1]);
    int len=strlen(orgin_path);
    if(len > PATH_MAX)
        err_sys("the path is longer than 4096");
    if(orgin_path[len-1]=='/')
        orgin_path[len-1]=0;
    strcpy(encry_path, orgin_path);
    strcat(encry_path, _cryp);
    dir_scan("",orgin_path);
    printf("total: %d files\n", count);
    return 0;
}

void dir_scan(char *path, char *file)
{
    struct stat s;
    DIR *dir;
    struct dirent *dt;
    char dirname[PATH_MAX],dstname[PATH_MAX];
    int fd;

    memset(dirname,0,PATH_MAX*sizeof(char));
    strcpy(dirname,path);

    if(lstat(file,&s) < 0)
        err_sys("lstat error");
    if(S_ISDIR(s.st_mode))
    {
        strcpy(dirname+strlen(dirname),file);
        if(dirname[strlen(dirname)-1] != '/')
            strcat(dirname, "/");
        if((dir=opendir(file)) == NULL)
            err_sys("opendir error");
        if(chdir(file) < 0)
            err_sys("chdir error");
        while((dt = readdir(dir)) != NULL)
        {
            if(dt->d_name[0] == '.')
                continue;
            dir_scan(dirname, dt->d_name);
        }
        if(chdir("..") < 0)
            err_sys("chdir error");
    }
    else
    {
        strcat(dirname,file);
        memset(dstname,0,PATH_MAX*sizeof(char));
        strcpy(dstname,encry_path);
        int len=strlen(orgin_path);
        strcat(dstname, dirname+len);
        check_make_path(dstname);
        printf("start crypt:%s\n", dirname);
        crypt(dirname,dstname);
        count++;
    }
}

void check_make_path(char* file_name)
{
    char* t;
    char filename[PATH_MAX];
    mode_t mode;

    strcpy(filename, file_name);
    t=filename;
    while (t = strchr(++t, '/')) {
        *t = 0;
        if (access(filename, 0) != -1) {
            *t = '/';
            continue;
        }
        mode=get_mode(filename);
        mkdir(filename, mode);
        *t ='/';
    }
}

void crypt(char* src,char* dst)
{
    int src_fd,dst_fd;
    struct stat s;
    mode_t mode;
    off_t src_file_len;
    int readlen,writelen;
    char cryptbuf[CRYPT_BLOCK_SIZE];

    
//open src file

    if( (src_fd=open(src,O_RDONLY)) < 0)
        err_sys("open source file error");
    
//get the src file length

    if(fstat(src_fd,&s) < 0)
        err_sys("lstat error");
    src_file_len = s.st_size;

    
//create dst file

    mode=s.st_mode;
    if( (dst_fd=open(dst,O_WRONLY|O_CREAT|O_TRUNC,mode)) < 0)
        err_sys("open destnation file error");

    
//crypt

    while(src_file_len>0)
    {
        if(src_file_len>CRYPT_BLOCK_SIZE)
            readlen=CRYPT_BLOCK_SIZE;
        else
            readlen=src_file_len;
        readfile(src_fd,cryptbuf,readlen);
        writelen=DEScrypt(cryptbuf,readlen,"abcdefgh",0);
        writefile(dst_fd,cryptbuf,writelen);
        src_file_len-=readlen;
    }
    
//close the file

    close(src_fd);
    close(dst_fd);
}

void readfile(int fd, char* buffer, int size)
{
    int bytes_read;
    char* ptr;

    ptr=buffer;
    while(bytes_read=read(fd,ptr,size))
    {
        if((bytes_read==-1)&&(errno!=EINTR))
            err_sys("read file error");
        else if(bytes_read>0)
        {
            ptr+=bytes_read;
            size-=bytes_read;
        }
        if(size==0)
            break;
    }
}

void writefile(int fd,char* buffer,int size)
{
    int bytes_write;
    char* ptr;

    ptr=buffer;
    while(bytes_write=write(fd,ptr,size))
    {
        if((bytes_write==-1)&&(errno!=EINTR))
            err_sys("write file error");
        else if(bytes_write>0)
        {
            ptr+=bytes_write;
            size-=bytes_write;
        }
        if(size==0)
            break;
    }

}

void err_sys(char * str)
{
    printf("%s\n",str);
    exit(0);
}

int get_mode(char* filepath)
{
    char temp_path[PATH_MAX];
    int len;
    struct stat s;

    strcpy(temp_path, orgin_path);
    len=strlen(encry_path);
    strcat(temp_path, filepath+len);
    stat(temp_path, &s);

    return s.st_mode;
}



Makefile
-----------------------------------------

encrypt:crypt.o encrypt.o
    cc -o encrypt crypt.o encrypt.o -lcrypt

.PHONY:clean
clean:
    -rm -f encrypt *.o


$ make
cc    -c -o crypt.o crypt.c
cc    -c -o encrypt.o encrypt.c
cc -o encrypt crypt.o encrypt.o -lcrypt
$ ./encrypt /home/xulei/LinkAndLoad/
start crypt:/home/xulei/LinkAndLoad/b.o
start crypt:/home/xulei/LinkAndLoad/TinyHelloWorld.o
start crypt:/home/xulei/LinkAndLoad/TinyHelloWorld
start crypt:/home/xulei/LinkAndLoad/SimpleDynamicLink/Program2
start crypt:/home/xulei/LinkAndLoad/SimpleDynamicLink/Program1
start crypt:/home/xulei/LinkAndLoad/SimpleDynamicLink/Lib.c
start crypt:/home/xulei/LinkAndLoad/SimpleDynamicLink/Program2.c
start crypt:/home/xulei/LinkAndLoad/SimpleDynamicLink/Lib.so
start crypt:/home/xulei/LinkAndLoad/SimpleDynamicLink/Lib.h
start crypt:/home/xulei/LinkAndLoad/SimpleDynamicLink/Program1.c
start crypt:/home/xulei/LinkAndLoad/hello.s
start crypt:/home/xulei/LinkAndLoad/a.o
start crypt:/home/xulei/LinkAndLoad/hello.o
start crypt:/home/xulei/LinkAndLoad/hello
start crypt:/home/xulei/LinkAndLoad/b.c
start crypt:/home/xulei/LinkAndLoad/hello.c
start crypt:/home/xulei/LinkAndLoad/hello.i
start crypt:/home/xulei/LinkAndLoad/StaticAndDynamic/main.c
start crypt:/home/xulei/LinkAndLoad/StaticAndDynamic/b.h
start crypt:/home/xulei/LinkAndLoad/StaticAndDynamic/Makefile.ar
start crypt:/home/xulei/LinkAndLoad/StaticAndDynamic/b.c
start crypt:/home/xulei/LinkAndLoad/StaticAndDynamic/Makefile
start crypt:/home/xulei/LinkAndLoad/StaticAndDynamic/a.h
start crypt:/home/xulei/LinkAndLoad/StaticAndDynamic/a.c
start crypt:/home/xulei/LinkAndLoad/SimpleSection.o
start crypt:/home/xulei/LinkAndLoad/a.c
start crypt:/home/xulei/LinkAndLoad/ab
start crypt:/home/xulei/LinkAndLoad/TinyHelloWorld.c
start crypt:/home/xulei/LinkAndLoad/SimpleSection.c
start crypt:/home/xulei/LinkAndLoad/GlobalSymbolTable/a1.c
start crypt:/home/xulei/LinkAndLoad/GlobalSymbolTable/main.c
start crypt:/home/xulei/LinkAndLoad/GlobalSymbolTable/a2.so
start crypt:/home/xulei/LinkAndLoad/GlobalSymbolTable/a2.c
start crypt:/home/xulei/LinkAndLoad/GlobalSymbolTable/b1.c
start crypt:/home/xulei/LinkAndLoad/GlobalSymbolTable/main
start crypt:/home/xulei/LinkAndLoad/GlobalSymbolTable/b2.c
start crypt:/home/xulei/LinkAndLoad/GlobalSymbolTable/b1.so
start crypt:/home/xulei/LinkAndLoad/GlobalSymbolTable/a1.so
start crypt:/home/xulei/LinkAndLoad/GlobalSymbolTable/b2.so
start crypt:/home/xulei/LinkAndLoad/GlobalSymbolTable/b2.so.bak
total:   40   files
$ ll /home/xulei/LinkAndLoad*
LinkAndLoad/      LinkAndLoad_cryp/

加密的结果就是LinkAndLoad_cryp/ 文件夹,解密只要稍微修改一下加密的代码,也就可以搞定了。
其实加密和解密本来就是互逆的,所以最好可以合并到一块儿写。这些就留给读者吧。

阅读(1070) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~