AES格式保持加密C++实现

一.描述

字符集为大小写字母与数字,-*,一共64个字符,-*加密后不变,各字符集加密完后应该还是属于该字符集。

二.思路

首先将字符编码,最大的字符集个数为26,5个比特即可表示,用8个比特表示一个字符,前3个比特为控制位,表示其为哪一种类的字符,后五个比特表示该字符在字符集内的具体数值。用CTC模式进行加密,每次从加密后的counter值中取五位出来与每个字符编码的后5个比特异或进行加密,加密完输出时,根据控制位进行相应的处理使其格式保持。解密就是再加密一次,详情见代码注释。aes的源代码请自行下载。

三.程序源代码

//
//  main.cpp
//  csv_ecyt
//
//  Created by 王俊 on 2017/10/29.
//  Copyright © 2017年 王俊. All rights reserved.
//

#include 
#include
#include
#include
#include 
#include 
using namespace std;
#include"aes.h"
string cm;
u8 ct[16], sct[16], cipherKey[16] = { 0x2c ,0x7e, 0x16, 0x17, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xe7, 0x15, 0x87, 0x09, 0xcf, 0x4f, 0x21 };
u32 int_cm[4]={0,0,0,0},rk[44], bigint[4] = { 0,0,0,0}, sm[4]={0,0,0,0,},cms[4],temp_sm[4];
map c_char_int, int_c_char,l_char_int,int_l_char,char_int,int_char;//用于保存字符集与字符之间双向映射的两个map
int find_kind(char a)
//返回值 1是大写字母,2是小写字母,3是数字,4是 - ,5是*,-1出错
{
    if (a >= 'A'&&a <= 'Z')
        return 1;
    if (a >= 'a'&&a <= 'z')
        return 2;
    if (a >= '0'&&a <= '9')
        return 3;
    if (a == '-')
        return 4;
    if (a == '*')
        return 5;
    return -1;
}
void change_to_bigint()
//字符串转化为可加密的0,1编码
// 其思想是用8个bit保存一个字符,前三个比特用于保存种类号,后5个比特用于保存字符集序号,
//组序号与字符在字符串出现的序号相同,组值等于该字符的字符集与int的映射值
{
    unsigned int temp1,kind,sft_cnt=0,count=0;
    for (int i = 0;i < cm.length();i++)
    {
        count = i * 8 / 32;
        sft_cnt = i * 8 - (i * 8 / 32) * 32;
        kind = find_kind(cm[i]);    //获取所属种类
        if(kind==-1)
        {
            cout<<"error:不在字符集内!"<>30);
            temp2 = 0x07;
            temp2 &= xr[1];
            temp2<<=2;
            temp2 ^= temp1;
            temp2 <<= sft_cnt_cm;
            b[count_cm]^=temp2;
            continue;
        }
        if (i*5 == 60)
        {
            temp1 = 0x0f;
            temp1 &= (xr[1] >> 28);
            temp2 = 0x01;
            temp2 &= xr[2];
            temp2<<=4;
            temp2 ^= temp1;
            temp2 <<= sft_cnt_cm;
            b[count_cm]^=temp2;
            temp1 = 0x1f;
            continue;
        }
        temp1 = 0x1f;      //每次取5位
        temp1 <<= sft_cnt_sct;    //移动到相应的位置
        temp2 = temp1&xr[count_sct];   //与xor相与获取6位组的密文
        temp2>>=sft_cnt_sct;
        temp2 <<= sft_cnt_cm;//移动到相应的位置
        b[count_cm]^= temp2;       //更新数据
    }
}
void Show(u32 a[])  //将加解密后的编码以字符串的方式显示出来
//每次取出8位出来,根据控制信息与数值输出字符
{
    unsigned int temp1,temp2,temp3;
    int sft_cnt=0,count=0;
    for(int i=0;;i++)
    {
        count=i*8/32;
        sft_cnt=i*8-((i*8)/32)*32;
        temp1=0xff;
        temp2=0x1f;
        temp3=0xe0;
        temp1<<=sft_cnt;
        temp2<<=sft_cnt;
        temp3<<=sft_cnt;
        temp1&=a[count];
        temp2&=temp1;
        temp3&=temp1;
        temp2>>=sft_cnt;
        temp3>>=(5+sft_cnt);
        if(temp3==1)
            cout<<(char)int_c_char[temp2%26];
        else if(temp3==2)
            cout<<(char)int_l_char[temp2%26];
        else if(temp3==3)
            cout<> cm;    //输入的明文
    init_table();     //初始化字符集的映射表
    change_to_bigint();       //将输入的明文字符串映射为0,1编码
    init_counter();              //用counter模式来实现aes加密,初始化随机数
    Nr = rijndaelKeySetupEnc(rk, cipherKey, 128);   //密钥扩展
    rijndaelEncrypt(rk, Nr, ct, sct);             //加密counter
    for(int i=0;i<4;i++)
    sm[i]=int_cm[i];
    Encrypt(sct,sm);     //与明文异或生成密文并显示(保持格式加密)
    Show(sm);
    Decrypt(sct,sm);      //解密
    Show(sm);
    getchar();
    getchar();
    return 0;
}


你可能感兴趣的:(网络安全)