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