C++简单数据加密算法实现加密和解密

/*
  This is a program for Encryption and Decryption
  This program uses the Simple Data Encryption Standard (SDES) Algorithm.
  This Algo takes 8-bits of plaintext at a time and produces 8-bits of ciphertext.
  It uses 10-bits of key for Encryption and Decryption.
 
  Developed by : Vivek Kumar (vivek_kumar_bt@yahoo.co.in)
 
   Created on : 31 March 2005
   Last Modified on : 10 April 2005
 
   Any sort of suggetions/comments are most welcome at vivek_kumar_bt@yahoo.co.in
*/
 
#include<iostream.h>
#include<stdio.h>
#include<conio.h>
#include<string.h>
#include<stdlib.h>
#include<assert.h>
void mainmenu(int *);
void menuEn();
void menuDe();
int DoEnDe(int);
 
class SDES
{
private:
    char KEY[11],K1[9],K2[9],IPOutput[9],InvIPOutput[9];
    char F1Output[9],F2Output[9];
    char INPUT_BIT[9],OUTPUT_BIT[9];
 
public:
    unsigned char INPUT,OUTPUT;
 
    SDES(char *key);
    ~SDES();
    void GenerateKeys();
    char *Left_Shift(char *,int );
    void conv_to_bits(unsigned char );
    void IP(char *);
    void InvIP(char *);
    void DES_Encryption(unsigned char );
    void DES_Decryption(unsigned char );
    void Function_F(char *,char *,int );
    char *EX_OR(char *,int );
    char *SBOX0(char *);
    char *SBOX1(char *);
    void SDES::GetChar();
};
SDES::SDES(char *key)  //Initializes the object with 10-bits key
{
    int i;
    if (strlen(key)!=10)  //Checks for valid length key
    {
        printf("\nInValid Key-Length %s %d",key,strlen(key));
        getch();
        exit(1);
    }
    for (i=0;i<10;i++)  //Assigning the key privatly
    {
        KEY[i]=key[i];
    }
    KEY[10]='\0';
    GenerateKeys(); //Key Genaration Starts. Output: (K1/K2)
 
}
 
void SDES::GenerateKeys()
{
    int P10[10]={3,5,2,7,4,10,1,9,8,6};      //P10 permutation-array
    char P10_OP[11];            //Output of P10 is to be stored here
    int P8[8]={6,3,7,4,8,5,10,9};       //P8 permutation-array
    char *P10LEFT,*pl,*pl1,*P10RIGHT,*pr,*pr1,*plpr;
    int i;
 
    /*P10 operation is done on main key*/
    for (i=0;i<10;i++)
        P10_OP[i]=KEY[P10[i]-1];
 
    P10_OP[10]='\0';
 
    /*Dividing 10-bit output of P10 operation into
      two parts*/
    for (i=0;i<5;i++)
    {
        P10LEFT[i]=P10_OP[i];
        P10RIGHT[i]=P10_OP[i+5];
    }
    P10LEFT[5]='\0';
    P10RIGHT[5]='\0';
 
    pl=new char[6];
    pr=new char[6];
 
    /*Perform Left-Circular shift by 1 bit on the
      two parts of P10 output*/
    pl=Left_Shift(P10LEFT,1);
    pr=Left_Shift(P10RIGHT,1);
 
    /*Combine the above two parts after
      the left-cicular operation into 'plpr' string*/
    for (i=0;i<5;i++)
    {
        plpr[i]=pl[i];
        plpr[i+5]=pr[i];
    }
    plpr[10]='\0';
 
    /*Performing P8 Operation on plpr and assigning to K1*/
    for (i=0;i<8;i++)
        K1[i]=plpr[P8[i]-1];
 
    K1[8]='\0'; //This is our first sub-key K1
 
    /*Again performing Left-Circular-Shift(LCS) by 2 bits on
      the output of previous Left-Cicular-Shift(LCS)*/
    pl1=Left_Shift(pl,2);
    pr1=Left_Shift(pr,2);
 
    /*Combining the output of above LCS2 into 1 string*/
    for (i=0;i<5;i++)
    {
        plpr[i]=pl1[i];
        plpr[i+5]=pr1[i];
    }
    plpr[10]='\0';
 
    /*Again performing P8 operation on the above combined
      string*/
    for (i=0;i<8;i++)
    {
        K2[i]=plpr[P8[i]-1];
    }
    K2[8]='\0'; //This is our second sub-key K2
 
}
 
/*Method to perform Left-Circular-Shift on bit-string*/
char *SDES::Left_Shift(char *bs,int n)
{
    int length=strlen(bs);
    char *char_ptr,firstbit,*str;
 
    char_ptr = new char[length +1];
    str=new char[length+1];
    char_ptr=bs;
 
    int i,j;
    for (j=0;j<n;j++)
    {
        firstbit=char_ptr[0];
 
        for (i=0;i<length-1;i++)
        {
            str[i]=char_ptr[i+1];
        }
        str[length-1]=firstbit;
        char_ptr[length]='\0';
        char_ptr=str;
    }
    char_ptr[length]='\0';
    return(str);
}
 
/*Method to convert unsigned char to bit-string
  For Ex. 1="00000001"*/
void SDES::conv_to_bits(unsigned char ch)
{
    int i,bit;
    INPUT_BIT[8]='\0';
    for (i=7;i>=0;i--)
    {
        bit=ch%2;
        ch=ch/2;
 
        if (bit!=0)
            INPUT_BIT[i]='1';
        else
            INPUT_BIT[i]='0';
    }
 
}
 
/*Method to perform Initial-Permutation*/
void SDES::IP(char *input)
{
    int IPArray[8]={2,6,3,1,4,8,5,7};
    int i;
    IPOutput[8]='\0';
    for (i=0;i<8;i++)
    {
        IPOutput[i]=input[IPArray[i]-1];
    }
}
 
/*Method to perform Inverse of Initial-Permutation*/
void SDES::InvIP(char *input)
{
    int InvIPArray[8]={4,1,3,5,7,2,8,6};
    int i;
    InvIPOutput[8]='\0';
    for (i=0;i<8;i++)
    {
        InvIPOutput[i]=input[InvIPArray[i]-1];
    }
}
 
/*Method to perform SDES-Encryption on 8-bit 'input'*/
void SDES::DES_Encryption(unsigned char input)
{
    char LIP[5],RIP[5],L1[5],R1[5];
    int i;
 
    INPUT=input;
    conv_to_bits(INPUT);  //Converts the input to bit-string
    IP(INPUT_BIT);        //Initial-Permutation
 
    //gotoxy(1,1);
    printf("\nEncrpyting.........");
 
    /*Dividing the output of IP into 2 parts*/
    for (i=0;i<4;i++)
    {
        LIP[i]=IPOutput[i];
        RIP[i]=IPOutput[i+4];
    }
    LIP[4]='\0';
    RIP[4]='\0';
 
    /*Sending the above divided parts to Function_F and  sub-key K1*/
    Function_F(LIP,RIP,1);
 
    /*Dividing the output of the Function_F into 2 parts*/
    for (i=0;i<4;i++)
    {
        L1[i]=F1Output[i];
        R1[i]=F1Output[4+i];
    }
    L1[4]='\0';
    R1[4]='\0';
 
    /*This time the string-parameters swaped and uses sub-key K2*/
    Function_F(R1,L1,2);
 
    /*Performing the Inverse IP on the output of the Funtion_F*/
    InvIP(F1Output); //The output of the function will give us
    //Cipher-string
 
    /*Cipher string is converted back to unsigned char and stored
      in private-variable OUTPUT of this class*/
    GetChar();
}
 
 
/*Decryption is just inverse of Encryption
  Here IP, InvIP, E/P, SBOX1 and SBOX2 are same
  But Function_F first operats on sub-key K2 and
  then on sub-key K1*/
void SDES::DES_Decryption(unsigned char input)
{
    char LIP[5],RIP[5],L1[5],R1[5];
    int i;
 
    INPUT=input;
    conv_to_bits(INPUT);
    IP(INPUT_BIT);        //Initial-Permutation
 
    //gotoxy(1,1);
    printf("\nDecrpyting.........");
 
    for (i=0;i<4;i++)
    {
        LIP[i]=IPOutput[i];
        RIP[i]=IPOutput[i+4];
    }
    LIP[4]='\0';
    RIP[4]='\0';
 
    Function_F(LIP,RIP,2);
 
    for (i=0;i<4;i++)
    {
        L1[i]=F1Output[i];
        R1[i]=F1Output[4+i];
    }
    L1[4]='\0';
    R1[4]='\0';
 
    Function_F(R1,L1,1);
    InvIP(F1Output);
    GetChar();
}
 
void SDES::Function_F(char *linput,char *rinput,int key)
{
    int E_P[8]={4,1,2,3,2,3,4,1}; //E/P Operation-Array
    int P4[4]={2,4,3,1};          //P4 Operation-Array
    int i;
    char E_POutput[9],*EXOR_Output,*LEXOR,*REXOR;
    char *SBOX0_Output,*SBOX1_Output;
    char SBOX_Output[5];
    char P4_Output[5];
    char fk_Output[5];
    char Main_Output[9];
 
    /*E/P Operaion is performed here*/
    for (i=0;i<8;i++)
    {
        E_POutput[i]=rinput[E_P[i]-1];
    }
    E_POutput[8]='\0';
 
    /*Bitwise-EXOR is done on E/P Output and sub-key(K1/K2)*/
    EXOR_Output=EX_OR(E_POutput,key);
 
    /*Divide the output of Exor in 2 parts*/
    LEXOR=new char[strlen(EXOR_Output)/2+1];
    REXOR=new char[strlen(EXOR_Output)/2+1];
 
    for (i=0;i<strlen(EXOR_Output)/2;i++)
    {
        LEXOR[i]=EXOR_Output[i];
        REXOR[i]=EXOR_Output[i+4];
    }
    LEXOR[4]=REXOR[4]='\0';
 
 
    /*Peforming SBOX0 Operation on left 4 bits*/
    SBOX0_Output=SBOX0(LEXOR);
 
    /*Peforming SBOX1 Operation on right 4 bits*/
    SBOX1_Output=SBOX1(REXOR);
 
    /*Combining the 2-bits output of both SBOXES in one string*/
    for (i=0;i<2;i++)
    {
        SBOX_Output[i]=SBOX0_Output[i];
        SBOX_Output[i+2]=SBOX1_Output[i];
    }
    SBOX_Output[4]='\0';
 
    /*Performing the P4 operation on SBOX output*/
    for (i=0;i<4;i++)
    {
        P4_Output[i]=SBOX_Output[P4[i]-1];
    }
    P4_Output[4]='\0';
 
    /*Performing the EXOR operation on 4-bits P4-output
      and 4-bits Leftinput of Funtion_F*/
    for (i=0;i<4;i++)
    {
        if (P4_Output[i]==linput[i])
            fk_Output[i]='0';
        else
            fk_Output[i]='1';
    }
    fk_Output[4]='\0';
 
    /*Cancating the 4-bits output of above EXOR-operation
      and 4-bits Right-input of Function_F*/
    for (i=0;i<4;i++)
    {
        Main_Output[i]=fk_Output[i];
        Main_Output[i+4]=rinput[i];
    }
    Main_Output[8]='\0';
    /*Assigning this Cucaneted string to Private variable 'F1Output'*/
    strcpy(F1Output,Main_Output);
}
 
/*This method EXORS the output ofE/P and sub-keys
  depending on the parameter k.
  k=1:subkey K1  k=2:subkey K2*/
char *SDES::EX_OR(char *ep,int k)
{
    char *output,*key;
    int i,klen;
 
    output=new char[strlen(ep)+1];
    key=new char[strlen(K1)+1];
    if (k==1)
    {
        strcpy(key,K1);
    } else
    {
        if (k==2)
        {
            strcpy(key,K2);
        } else
        {
            printf("\n\nWrong Choice in the key parameter(1/2)");
            getch();
            exit(1);
        }
    }
    klen=strlen(K1);
    if (strlen(ep)!=klen)
    {
        printf("\ninput=%d is not equal to K=%d",strlen(ep),klen);
        printf("\n\nError in the Output of E/P (Length)..Press any key");
        getch();
        exit(1);
    }
    for (i=0;i<strlen(ep);i++)
    {
        if (ep[i]==key[i])
            output[i]='0';
        else
            output[i]='1';
    }
    output[strlen(ep)]='\0';
    return(output);
}
 
/*SBOX0 Operation is defined here*/
char *SDES::SBOX0(char *l)
{
    int S0[4][4]={1,0,3,2,  //S0 Matrix
        3,2,1,0,
        0,2,1,3,
        3,1,3,2
    };
 
    char *bits[]={"00","01","10","11"};
    char lrow[3],lcol[3];
    char *SO;
    int i,lr,lc,b;
 
    SO=new char[3];
 
    lrow[0]=l[0];
    lrow[1]=l[3];
    lcol[0]=l[1];
    lcol[1]=l[2];
 
    lrow[2]='\0';
    lcol[2]='\0';
 
 
    for (i=0;i<4;i++)
    {
        if (strcmp(lrow,bits[i])==0)
            lr=i;
        if (strcmp(lcol,bits[i])==0)
            lc=i;
    }
    b=S0[lr][lc];
    for (i=0;i<3;i++)
        SO[i]=bits[b][i];
    SO[3]='\0';
    return(SO);
}
/*SBOX1 Operation is defined here*/
char *SDES::SBOX1(char *l)
{
    int S0[4][4]={0,1,2,3,   //S1 Matrix
        2,0,1,3,
        3,0,1,0,
        2,1,0,3
    };
 
    char *bits[]={"00","01","10","11"};
    char lrow[3],lcol[3];
    char *SO;
    int i,lr,lc,b;
 
    SO=new char[3];
 
    lrow[0]=l[0];
    lrow[1]=l[3];
    lcol[0]=l[1];
    lcol[1]=l[2];
 
    lrow[2]='\0';
    lcol[2]='\0';
 
 
    for (i=0;i<4;i++)
    {
        if (strcmp(lrow,bits[i])==0)
            lr=i;
        if (strcmp(lcol,bits[i])==0)
            lc=i;
    }
    b=S0[lr][lc];
    for (i=0;i<3;i++)
        SO[i]=bits[b][i];
 
    SO[3]='\0';
    return(SO);
}
 
/*Method to get back unsigned char from bit-string*/
void SDES::GetChar()
{
    int i,j,in;
    unsigned char ch=0;
    char *bs;
    bs=new char[9];
    bs=InvIPOutput;
    if (strlen(bs)>8)
    {
        printf("\nWRONG LENGTH STRING");
        exit(0);
    }
    for (i=0;i<8;i++)
    {
        if (bs[i]=='1')
        {
            in=1;
            for (j=1;j<8-i;j++)
            {
                in=in*2;
            }
            ch=ch+in;
        }
    }
    OUTPUT=ch;
}
 
/*Destructor*/
SDES::~SDES()
{
}
 
 
char *sfname,*tfname;
char *key;//="1010000010";
void main(void)
{
    //clrscr();
    unsigned char ch,ch1;
    int i,n=10,choice;
 
    while (1)
    {
        key = new char[11];
        sfname = new char[20];
        tfname = new char[20];
        mainmenu(&choice);
        fflush(stdin);
        switch (choice)
        {
        case 1:
            menuEn();
            DoEnDe(choice);
            break;
        case 2:
            menuDe();
            DoEnDe(choice);
            break;
        case 3:
            exit(0);
        default:
            printf("\nWrong Choice Enter again\nPress any key to return to Main Menu..");
            getch();
            break;
        }
    }
}
 
void mainmenu(int *c)
{
    //clrscr();
    printf("\nWhat do you want to do..");
    printf("\n1. Encryption");
    printf("\n2. Decryption");
    printf("\n3. Exit");
    printf("\n\nEnter the choice? ");
    scanf("%d",c);
}
void menuEn()
{
    //clrscr();
    sfname=new char[20];
    tfname=new char[20];
    key=new char[11];
    printf("\nEncryption Menu\n\n");
    printf("\nEnter the filename to be Encrypted: ");
    gets(sfname);
    printf("\nEnter the Target file name: ");
    gets(tfname);
    printf("\nEnter the 10-bits KEY: ");
    gets(key);
    printf("\n\nNotedown this key, as same key is used for Decryption");
    //getch();
}
 
void menuDe()
{
    //clrscr();
    sfname=new char[20];
    tfname=new char[20];
    key=new char[11];
    printf("\nDecryption Menu\n\n");
    printf("\nEnter the filename to be Decrypted: ");
    gets(sfname);
    printf("\nEnter the Target file name: ");
    gets(tfname);
    printf("\nEnter the 10-bits KEY: ");
    gets(key);
}
 
int DoEnDe(int c)
{
    SDES S(key);
    int i,n;
    n=10; //Number of Rounds
    unsigned char ch;
    FILE *fp;
    FILE *ft;
    fp=fopen(tfname,"w");
    ft=fopen(sfname,"r");
    if (fp==NULL)
    {
        printf("\nTarget File not opened SORRY");
        getch();
        fclose(fp);
        return(0);
    }
    if (ft==NULL)
    {
        printf("\nSource File not opened SORRY");
        getch();
        fclose(ft);
        return(0);
    }
    while (fread(&ch,1,1,ft)==1)
    {
        S.OUTPUT=ch;
 
        for (i=0;i<n;i++)
        {
            if (c==1)
                S.DES_Encryption(S.OUTPUT);
            if (c==2)
                S.DES_Decryption(S.OUTPUT);
        }
        fwrite(&S.OUTPUT,1,1,fp);
    }
    printf("\nCompleted!!!!!");
    getch();
    fclose(fp);
    fclose(ft);
    return(1);
}

编程技巧