以前在《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/ 文件夹,解密只要稍微修改一下加密的代码,也就可以搞定了。
其实加密和解密本来就是互逆的,所以最好可以合并到一块儿写。这些就留给读者吧。