信息安全实验RC4和MD5

信息安全实验

RC4和MD5


实验要求

RC4和MD5。将用户的密码通过md5加密之后作为RC4加密的输入key进行设置RC4的密钥,并使用此密钥对用户内容进行加密。

实验

几个关键词

  1. 密钥流:RC4算法的关键是根据明文和密钥生成相应的密钥流,密钥流的长度和明文的长度是对应的,也就是说明文的长度是500字节,那么密钥流也是500字节。当然,加密生成的密文也是500字节,因为密文第i字节=明文第i字节^密钥流第i字节;
  2. 状态向量S:长度为256,S[0],S[1].....S[255]。每个单元都是一个字节,算法运行的任何时候,S都包括0-255的8比特数的排列组合,只不过值的位置发生了变换;
  3. 临时向量T:长度也为256,每个单元也是一个字节。如果密钥的长度是256字节,就直接把密钥的值赋给T,否则,轮转地将密钥的每个字节赋给T;
  4. 密钥K:长度为1-256字节,注意密钥的长度keylen与明文长度、密钥流的长度没有必然关系,通常密钥的长度取为16字节(128比特)。

RC4的原理分为三步

  1. 初始化S和T
for i=0 to 255 do
   S[i]=i;
   T[i]=K[ i mod keylen ];
  1. 初始排列S
j=0;
for i=0 to 255 do
   j= ( j+S[i]+T[i])mod256;
   swap(S[i],S[j]);
  1. 产生密钥流
i,j=0;
for r=0 to len do  //r为明文长度,r字节
   i=(i+1) mod 256;
   j=(j+S[i])mod 256;
   swap(S[i],S[j]);
   t=(S[i]+S[j])mod 256;
   k[r]=S[t];//K为密钥
  1. 利用密钥流与明文进行按位异或

则我们需要做的是把K替换为用户输入key的MD5值。

获取MD5

利用openssl库(文档里对md5相关的部分函数介绍),一般有两种方式:

#include<openssl/md5.h>

MD5_CTX ctx;
unsigned char *data="123";
unsigned char md[16];
MD5_Init(&ctx);
MD5_Update(&ctx,data,strlen(data));//data为要加密的串
MD5_Final(md,&ctx);//md为密文

或者:

unsigned char * userKey;//从用户获取的明文
unsigned char md5Value[32];//md5值
MD5((unsigned char*)userKey,strlen(userKey),md5Value);

解密

解密则只需要将保存的密钥和密文按位异或即可。

Tips

char && unsigned char

在C中,默认的基础数据类型均为signed,在内存中,char与unsigned char没有什么不同,都是一个字节,唯一的区别是,char的最高位为符号位,因此char能表示-128~127, unsigned char没有符号位,因此能表示0~255.
主要是符号位,但是在普通的赋值,读写文件和网络字节流都没什么区别,反正就是一个字节,不管最高位是什么,最终的读取结果都一样,只是你怎么理解最高位而已,在屏幕上面的显示可能不一样。
但是我们却发现在表示byte时,都用unsigned char,这是为什么呢?
首先我们通常意义上理解,byte没有什么符号位之说,更重要的是如果将byte的值赋给int,long等数据类型时,系统会做一些额外的工作。
如果是char,那么系统认为最高位是符号位,而int可能是16或者32位,那么会对最高位进行扩展(注意,赋给unsigned int也会扩展),是根据当前char的最高位进行扩展的。
而如果是unsigned char,那么不会扩展。
这就是二者的最大区别。
同理可以推导到其它的类型,比如short, unsigned short。等等

Code

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/md5.h>  

unsigned char * userKey;
unsigned char md5Value[32];
int keylen;

char  *plaintext;
char ciphertext[1024];
//keystream
    unsigned  char *key;

int pLen;
size_t result;

void readUserKey(){
    FILE *fin;
    if((fin=fopen("userKey","r"))==NULL){
        printf("Read UserKey failed\n");
        exit(1);
    };
    fseek(fin,0,SEEK_END);
    int userkeySize=ftell(fin);
    rewind(fin);
    userKey=(unsigned char*)malloc(sizeof(unsigned char)*userkeySize);
    result = fread(userKey,1,userkeySize,fin);
    if(result!=userkeySize){
        printf("Read userKey error when malloc\n");
        exit(1);
    }
    if(userKey==NULL)printf("null\n");
        printf("userkey %s\n",userKey );
    fclose(fin);
};
void readUserContent(){
    long lSize;
    FILE *fin2;
    if((fin2=fopen("userContent","rb"))==NULL){
        printf("Read userContent error\n");
        exit(2);
    }
    //get the file size 
    fseek(fin2,0,SEEK_END);
    lSize=ftell(fin2);
    rewind(fin2);

    plaintext=(char*)malloc(sizeof(char)*lSize);

    result=fread(plaintext,1,lSize,fin2);
    if(result!=lSize){
        printf("Read userContent error when malloc\n");
        exit(3);
    }
    printf("%s\n",plaintext );
    fclose(fin2);
}

void getMD5(){
    //attention !!!! malloc!!!!!!!!!!!!!!!
    MD5((unsigned char*)userKey,strlen(userKey),md5Value);
    keylen=strlen(md5Value);
    int i;
    for(i=0;i<keylen;i++)
        printf("%2.2x",md5Value[i] );
    printf("\n");
};

void encrypt(){
    unsigned  char  s[256],t[256];
    int i,j,temp,q,m,n;
    for(i=0;i<256;i++){
        s[i]=i;
        t[i]=md5Value[i%keylen];
    }
    for(i=0;i<256;i++){
         j=(j+s[i]+t[i])%256;
         temp=s[i];
         s[i]=s[j];
         s[j]=temp;
    }
    pLen=strlen(plaintext);
    key=(unsigned char*)malloc(sizeof(unsigned char)*pLen);
    m=n=0;
    for(i=0;i<pLen;i++){
        m=(m+1)% 256;
        n=(n+s[n])% 256;
        temp=s[m];
        s[m]=s[n];
        s[n]=temp;
        q=(s[m]+s[n])%256;
        key[i]=s[q];
        ciphertext[i]=plaintext[i]^key[i];
        printf("%X",ciphertext[i] );
    }
    ciphertext[i]='/0';
    printf("\n");
}

void decrypt(){
    int i;
    printf("\n");
    for(i=0;i<pLen;i++){
        printf("%c", ciphertext[i]^key[i]);
    }
}

int main(int argc, char const *argv[])
{
    readUserKey();
    getMD5();
    readUserContent();
    encrypt();
    decrypt();
    return 0;
}

Reference

RC4加密原理及代码
RC4加密原理及代码
char 与 unsigned char的本质区别

路漫漫其修远兮,吾将上下而求索

文章若未注明转载皆为原创,如需转载请注明出处FindHao博客及文章链接,文章markdown格式源码现已开放,欢迎转载。文章源码地址:

分享到:

You may like..(由于采用了谷歌的推荐系统,需要对本站关闭广告过滤~)

Find

新浪微博(FindSpace博客)QQ群:不安分的Coder(375670127) 不安分的Coder

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*