求AES加密算法 C代码

求AES加密算法 C代码,第1张

以前编过的,c++可以用的

#include <iostream>

using namespace std;

long gcd(long a, long b)

{

if(b>a) //a中存放较大的数,b中存放较小的数

{

int temp;

temp=a;

a=b;

b=temp;

}

long n;

while((n=a%b)!=0)

{

a=b;

b=n;

}

return b;

}

//---------------------------------------

long cheng_niyuan(long a, long b)

{

for(long i=1; (ia)%b!=1; i++);

return i;

}

//---------------------------------------

int mi_mo(int a, int b, int n)

{

int K[100];

int top=-1;

while(b)

{

top++;

K[top]=(b%2);

b/=2;

}

int c=0, f=1;

for(; top>=0; top--)

{

c=2c;

f=(ff)%n;

if(K[top]==1)

{

c+=1;

f=(fa)%n;

}

}

return f;

}

//---------------------------------------

int main()

{

int p=5,q=11;

cout<<"p="<<p<<endl;

cout<<"q="<<q<<endl;

long int n=pq;

cout<<"n="<<n<<endl;

long int fi_n=(p-1)(q-1);

cout<<"fi_n="<<fi_n<<endl;

int e=3;

cout<<"e="<<e<<endl;

long d=cheng_niyuan(e,fi_n);

int M, C;

cout<<"请输入明文:"<<endl;

cin>>M;

C=mi_mo(M, e, n);

cout<<"对应的密文为:"<<endl;

cout<<C<<endl;

cout<<"请输入密文:"<<endl;

cin>>C;

M=mi_mo(C, d, n);

cout<<"对应的明文为:"<<endl;

cout<<M<<endl;

return 0;

}

AES(Advanced Encryption Standard),高级加密标准,对称算法,是下一代的加密算法标准,速度快,安全级别高,在21世纪AES 标准的一个实现是 Rijndael 算法;

AES加密算法是密码学中的高级加密标准,该加密算法采用对称分组密码体制,密钥长度的最少支持为128、192、256,分组长度128位,算法应易于各种硬件和软件实现。这种加密算法是美国联邦政府采用的区块加密标准,这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用。

它适用于敏感内容进行加密传输,防止被窃取。

Java有相关的实现类:具体原理如下

对于任意长度的明文,AES首先对其进行分组,每组的长度为128位。分组之后将分别对每个128位的明文分组进行加密。

对于每个128位长度的明文分组的加密过程如下:

(1)将128位AES明文分组放入状态矩阵中。

(2)AddRoundKey变换:对状态矩阵进行AddRoundKey变换,与膨胀后的密钥进行异或 *** 作(密钥膨胀将在实验原理七中详细讨论)。

(3)10轮循环:AES对状态矩阵进行了10轮类似的子加密过程。前9轮子加密过程中,每一轮子加密过程包括4种不同的变换,而最后一轮只有3种变换,前9轮的子加密步骤如下:

● SubBytes变换:SubBytes变换是一个对状态矩阵非线性的变换;

● ShiftRows变换:ShiftRows变换对状态矩阵的行进行循环移位;

● MixColumns变换:MixColumns变换对状态矩阵的列进行变换;

● AddRoundKey变换:AddRoundKey变换对状态矩阵和膨胀后的密钥进行异或 *** 作。

最后一轮的子加密步骤如下:

● SubBytes变换:SubBytes变换是一个对状态矩阵非线性的变换;

● ShiftRows变换:ShiftRows变换对状态矩阵的行进行循环移位;

● AddRoundKey变换:AddRoundKey变换对状态矩阵和膨胀后的密钥进行异或 *** 作;

(4)经过10轮循环的状态矩阵中的内容就是加密后的密文。

AES的加密算法的伪代码如下。

在AES算法中,AddRoundKey变换需要使用膨胀后的密钥,原始的128位密钥经过膨胀会产生44个字(每个字为32位)的膨胀后的密钥,这44个字的膨胀后的密钥供11次AddRoundKey变换使用,一次AddRoundKey使用4个字(128位)的膨胀后的密钥。

三.AES的分组过程

对于任意长度的明文,AES首先对其进行分组,分组的方法与DES相同,即对长度不足的明文分组后面补充0即可,只是每一组的长度为128位。

AES的密钥长度有128比特,192比特和256比特三种标准,其他长度的密钥并没有列入到AES联邦标准中,在下面的介绍中,我们将以128位密钥为例。

四.状态矩阵

状态矩阵是一个4行、4列的字节矩阵,所谓字节矩阵就是指矩阵中的每个元素都是一个1字节长度的数据。我们将状态矩阵记为State,State中的元素记为Sij,表示状态矩阵中第i行第j列的元素。128比特的明文分组按字节分成16块,第一块记为“块0”,第二块记为“块1”,依此类推,最后一块记为“块15”,然后将这16块明文数据放入到状态矩阵中,将这16块明文数据放入到状态矩阵中的方法如图2-2-1所示。

块0

块4

块8

块12

块1

块5

块9

块13

块2

块6

块10

块14

块3

块7

块11

块15

图2-2-1 将明文块放入状态矩阵中

五.AddRoundKey变换

状态矩阵生成以后,首先要进行AddRoundKey变换,AddRoundKey变换将状态矩阵与膨胀后的密钥进行按位异或运算,如下所示。

其中,c表示列数,数组W为膨胀后的密钥,round为加密轮数,Nb为状态矩阵的列数。

它的过程如图2-2-2所示。

图2-2-2 AES算法AddRoundKey变换

六.10轮循环

经过AddRoundKey的状态矩阵要继续进行10轮类似的子加密过程。前9轮子加密过程中,每一轮要经过4种不同的变换,即SubBytes变换、ShiftRows变换、MixColumns变换和AddRoundKey变换,而最后一轮只有3种变换,即SubBytes变换、ShiftRows变换和AddRoundKey变换。AddRoundKey变换已经讨论过,下面分别讨论余下的三种变换。

1.SubBytes变换

SubBytes是一个独立作用于状态字节的非线性变换,它由以下两个步骤组成:

(1)在GF(28)域,求乘法的逆运算,即对于α∈GF(28)求β∈GF(28),使αβ =βα = 1mod(x8 + x4 + x3 + x + 1)。

(2)在GF(28)域做变换,变换使用矩阵乘法,如下所示:

由于所有的运算都在GF(28)域上进行,所以最后的结果都在GF(28)上。若g∈GF(28)是GF(28)的本原元素,则对于α∈GF(28),α≠0,则存在

β ∈ GF(28),使得:

β = gαmod(x8 + x4 + x3 + x + 1)

由于g255 = 1mod(x8 + x4 + x3 + x + 1)

所以g255-α = β-1mod(x8 + x4 + x3 + x + 1)

根据SubBytes变换算法,可以得出SubBytes的置换表,如表2-2-1所示,这个表也叫做AES的S盒。该表的使用方法如下:状态矩阵中每个元素都要经过该表替换,每个元素为8比特,前4比特决定了行号,后4比特决定了列号,例如求SubBytes(0C)查表的0行C列得FE。

表2-2-1 AES的SubBytes置换表

它的变换过程如图2-2-3所示。

图2-2-3 SubBytes变换

AES加密过程需要用到一些数学基础,其中包括GF(2)域上的多项式、GF(28)域上的多项式的计算和矩阵乘法运算等,有兴趣的同学请参考相关的数学书籍。

2.ShiftRows变换

ShiftRows变换比较简单,状态矩阵的第1行不发生改变,第2行循环左移1字节,第3行循环左移2字节,第4行循环左移3字节。ShiftRows变换的过程如图2-2-4所示。

图2-2-4 AES的ShiftRows变换

3.MixColumns变换

在MixColumns变换中,状态矩阵的列看作是域GF(28)的多项式,模(x4+1)乘以c(x)的结果:

c(x)=(03)x3+(01)x2+(01)x+(02)

这里(03)为十六进制表示,依此类推。c(x)与x4+1互质,故存在逆:

d(x)=(0B)x3+(0D)x2+(0G)x+(0E)使c(x)•d(x) = (D1)mod(x4+1)。

设有:

它的过程如图2-2-5所示。

图2-2-5 AES算法MixColumns变换

七.密钥膨胀

在AES算法中,AddRoundKey变换需要使用膨胀后的密钥,膨胀后的密钥记为子密钥,原始的128位密钥经过膨胀会产生44个字(每个字为32位)的子密钥,这44个字的子密钥供11次AddRoundKey变换使用,一次AddRoundKey使用4个字(128位)的膨胀后的密钥。

密钥膨胀算法是以字为基础的(一个字由4个字节组成,即32比特)。128比特的原始密钥经过膨胀后将产生44个字的子密钥,我们将这44个密钥保存在一个字数组中,记为W[44]。128比特的原始密钥分成16份,存放在一个字节的数组:Key[0],Key[1]……Key[15]中。

在密钥膨胀算法中,Rcon是一个10个字的数组,在数组中保存着算法定义的常数,分别为:

Rcon[0] = 0x01000000

Rcon[1] = 0x02000000

Rcon[2] = 0x04000000

Rcon[3] = 0x08000000

Rcon[4] = 0x10000000

Rcon[5] = 0x20000000

Rcon[6] = 0x40000000

Rcon[7] = 0x80000000

Rcon[8] = 0x1b000000

Rcon[9] = 0x36000000

另外,在密钥膨胀中包括其他两个 *** 作RotWord和SubWord,下面对这两个 *** 作做说明:

RotWord( B0,B1,B2,B3 )对4个字节B0,B1,B2,B3进行循环移位,即

RotWord( B0,B1,B2,B3 ) = ( B1,B2,B3,B0 )

SubWord( B0,B1,B2,B3 )对4个字节B0,B1,B2,B3使用AES的S盒,即

SubWord( B0,B1,B2,B3 ) = ( B’0,B’1,B’2,B’3 )

其中,B’i = SubBytes(Bi),i = 0,1,2,3。

密钥膨胀的算法如下:

八.解密过程

AES的加密和解密过程并不相同,首先密文按128位分组,分组方法和加密时的分组方法相同,然后进行轮变换。

AES的解密过程可以看成是加密过程的逆过程,它也由10轮循环组成,每一轮循环包括四个变换分别为InvShiftRows变换、InvSubBytes变换、InvMixColumns变换和AddRoundKey变换;

这个过程可以描述为如下代码片段所示:

九.InvShiftRows变换

InvShiftRows变换是ShiftRows变换的逆过程,十分简单,指定InvShiftRows的变换如下。

Sr,(c+shift(r,Nb))modNb= Sr,c for 0 < r< 4 and 0 ≤ c < Nb

图2-2-6演示了这个过程。

图2-2-6 AES算法InvShiftRows变换

十.InvSubBytes变换

InvSubBytes变换是SubBytes变换的逆变换,利用AES的S盒的逆作字节置换,表2-2-2为InvSubBytes变换的置换表。

表2-2-2 InvSubBytes置换表

十一.InvMixColumns变换

InvMixColumns变换与MixColumns变换类似,每列乘以d(x)

d(x) = (OB)x3 + (0D)x2 + (0G)x + (0E)

下列等式成立:

( (03)x3 + (01)x2 + (01)x + (02) )⊙d(x) = (01)

上面的内容可以描述为以下的矩阵乘法:

十二.AddRoundKey变换

AES解密过程的AddRoundKey变换与加密过程中的AddRoundKey变换一样,都是按位与子密钥做异或 *** 作。解密过程的密钥膨胀算法也与加密的密钥膨胀算法相同。最后状态矩阵中的数据就是明文。

unit AES;                  

 

interface

 

uses

  SysUtils, Classes, Math, ElAES;

 

type

  TKeyBit = (kb128, kb192, kb256);

 

function StrToHex(Value: string): string;

function HexToStr(Value: string): string;

function EncryptString(Value: string; Key: string;

  KeyBit: TKeyBit = kb128): string;

function DecryptString(Value: string; Key: string;

  KeyBit: TKeyBit = kb128): string;

function EncryptStream(Stream: TStream; Key: string;

  KeyBit: TKeyBit = kb128): TStream;

function DecryptStream(Stream: TStream; Key: string;

  KeyBit: TKeyBit = kb128): TStream;

procedure EncryptFile(SourceFile, DestFile: string;

  Key: string; KeyBit: TKeyBit = kb128);

procedure DecryptFile(SourceFile, DestFile: string;

  Key: string; KeyBit: TKeyBit = kb128);

   

implementation

 

function StrToHex(Value: string): string;

var

  I: Integer;

begin

  Result := '';

  for I := 1 to Length(Value) do

    Result := Result + IntToHex(Ord(Value[I]), 2);

end;

 

function HexToStr(Value: string): string;

var

  I: Integer;

begin

  Result := '';

  for I := 1 to Length(Value) do

  begin

    if ((I mod 2) = 1) then

      Result := Result + Chr(StrToInt('0x'+ Copy(Value, I, 2)));

  end;

end;

 

{  --  字符串加密函数 默认按照 128 位密匙加密 --  }

function EncryptString(Value: string; Key: string;

  KeyBit: TKeyBit = kb128): string;

var

  SS, DS: TStringStream;

  Size: Int64;

  AESKey128: TAESKey128;

  AESKey192: TAESKey192;

  AESKey256: TAESKey256;

begin

  Result := '';

  SS := TStringStreamCreate(Value);

  DS := TStringStreamCreate('');

  try

    Size := SSSize;

    DSWriteBuffer(Size, SizeOf(Size));

    {  --  128 位密匙最大长度为 16 个字符 --  }

    if KeyBit = kb128 then

    begin

      FillChar(AESKey128, SizeOf(AESKey128), 0 );

      Move(PChar(Key)^, AESKey128, Min(SizeOf(AESKey128), Length(Key)));

      EncryptAESStreamECB(SS, 0, AESKey128, DS);

    end;

    {  --  192 位密匙最大长度为 24 个字符 --  }

    if KeyBit = kb192 then

    begin

      FillChar(AESKey192, SizeOf(AESKey192), 0 );

      Move(PChar(Key)^, AESKey192, Min(SizeOf(AESKey192), Length(Key)));

      EncryptAESStreamECB(SS, 0, AESKey192, DS);

    end;

    {  --  256 位密匙最大长度为 32 个字符 --  }

    if KeyBit = kb256 then

    begin

      FillChar(AESKey256, SizeOf(AESKey256), 0 );

      Move(PChar(Key)^, AESKey256, Min(SizeOf(AESKey256), Length(Key)));

      EncryptAESStreamECB(SS, 0, AESKey256, DS);

    end;

    Result := StrToHex(DSDataString);

  finally

    SSFree;

    DSFree;

  end;

end;

 

{  --  字符串解密函数 默认按照 128 位密匙解密 --  }

function DecryptString(Value: string; Key: string;

  KeyBit: TKeyBit = kb128): string;

var

  SS, DS: TStringStream;

  Size: Int64;

  AESKey128: TAESKey128;

  AESKey192: TAESKey192;

  AESKey256: TAESKey256;

begin

  Result := '';

  SS := TStringStreamCreate(HexToStr(Value));

  DS := TStringStreamCreate('');

  try

    Size := SSSize;

    SSReadBuffer(Size, SizeOf(Size));

    {  --  128 位密匙最大长度为 16 个字符 --  }

    if KeyBit = kb128 then

    begin

      FillChar(AESKey128, SizeOf(AESKey128), 0 );

      Move(PChar(Key)^, AESKey128, Min(SizeOf(AESKey128), Length(Key)));

      DecryptAESStreamECB(SS, SSSize - SSPosition, AESKey128, DS);

    end;

    {  --  192 位密匙最大长度为 24 个字符 --  }

    if KeyBit = kb192 then

    begin

      FillChar(AESKey192, SizeOf(AESKey192), 0 );

      Move(PChar(Key)^, AESKey192, Min(SizeOf(AESKey192), Length(Key)));

      DecryptAESStreamECB(SS, SSSize - SSPosition, AESKey192, DS);

    end;

    {  --  256 位密匙最大长度为 32 个字符 --  }

    if KeyBit = kb256 then

    begin

      FillChar(AESKey256, SizeOf(AESKey256), 0 );

      Move(PChar(Key)^, AESKey256, Min(SizeOf(AESKey256), Length(Key)));

      DecryptAESStreamECB(SS, SSSize - SSPosition, AESKey256, DS);

    end;

    Result := DSDataString;

  finally

    SSFree;

    DSFree;

  end;

end;

 

{  --  流加密函数 默认按照 128 位密匙解密 --  }

function EncryptStream(Stream: TStream; Key: string;

  KeyBit: TKeyBit = kb128): TStream;

var

  Count: Int64;

  OutStrm: TStream;

  AESKey128: TAESKey128;

  AESKey192: TAESKey192;

  AESKey256: TAESKey256;

begin

  OutStrm := TStreamCreate;

  StreamPosition := 0;

  Count := StreamSize;

  OutStrmWrite(Count, SizeOf(Count));

  try

    {  --  128 位密匙最大长度为 16 个字符 --  }

    if KeyBit = kb128 then

    begin

      FillChar(AESKey128, SizeOf(AESKey128), 0 );

      Move(PChar(Key)^, AESKey128, Min(SizeOf(AESKey128), Length(Key)));

      EncryptAESStreamECB(Stream, 0, AESKey128, OutStrm);

    end;

    {  --  192 位密匙最大长度为 24 个字符 --  }

    if KeyBit = kb192 then

    begin

      FillChar(AESKey192, SizeOf(AESKey192), 0 );

      Move(PChar(Key)^, AESKey192, Min(SizeOf(AESKey192), Length(Key)));

      EncryptAESStreamECB(Stream, 0, AESKey192, OutStrm);

    end;

    {  --  256 位密匙最大长度为 32 个字符 --  }

    if KeyBit = kb256 then

    begin

      FillChar(AESKey256, SizeOf(AESKey256), 0 );

      Move(PChar(Key)^, AESKey256, Min(SizeOf(AESKey256), Length(Key)));

      EncryptAESStreamECB(Stream, 0, AESKey256, OutStrm);

    end;

    Result := OutStrm;

  finally

    OutStrmFree;

  end;

end;

 

{  --  流解密函数 默认按照 128 位密匙解密 --  }

function DecryptStream(Stream: TStream; Key: string;

  KeyBit: TKeyBit = kb128): TStream;

var

  Count, OutPos: Int64;

  OutStrm: TStream;

  AESKey128: TAESKey128;

  AESKey192: TAESKey192;

  AESKey256: TAESKey256;

begin

  OutStrm := TStreamCreate;

  StreamPosition := 0;

  OutPos :=OutStrmPosition;

  StreamReadBuffer(Count, SizeOf(Count));

  try

    {  --  128 位密匙最大长度为 16 个字符 --  }

    if KeyBit = kb128 then

    begin

      FillChar(AESKey128, SizeOf(AESKey128), 0 );

      Move(PChar(Key)^, AESKey128, Min(SizeOf(AESKey128), Length(Key)));

      DecryptAESStreamECB(Stream, StreamSize - StreamPosition,

        AESKey128, OutStrm);

    end;

    {  --  192 位密匙最大长度为 24 个字符 --  }

    if KeyBit = kb192 then

    begin

      FillChar(AESKey192, SizeOf(AESKey192), 0 );

      Move(PChar(Key)^, AESKey192, Min(SizeOf(AESKey192), Length(Key)));

      DecryptAESStreamECB(Stream, StreamSize - StreamPosition,

        AESKey192, OutStrm);

    end;

    {  --  256 位密匙最大长度为 32 个字符 --  }

    if KeyBit = kb256 then

    begin

      FillChar(AESKey256, SizeOf(AESKey256), 0 );

      Move(PChar(Key)^, AESKey256, Min(SizeOf(AESKey256), Length(Key)));

      DecryptAESStreamECB(Stream, StreamSize - StreamPosition,

        AESKey256, OutStrm);

    end;

    OutStrmSize := OutPos + Count;

    OutStrmPosition := OutPos;

    Result := OutStrm;

  finally

    OutStrmFree;

  end;

end;

,也分别为128比特,192比特和256比特,并分别被称为AES-128,AES-192,AES-256。

AES和传统的分组密码算法不同的是它不采用Feistel结构(比如DES中采用的),而是采用了三个不同的可逆一致变换层:线性混合层、非线性层、密钥加层。具体的算法数学基础和过程请祥见: >

一般的加密通常都是块加密,如果要加密超过块大小的数据,就需要涉及填充和链加密模式,本文对对称加密和分组加密中的几种种模式进行一一分析(ECB、CBC、CFB、OFB,CTR)

这种模式是将整个明文分成若干段相同的小段,然后对每一小段进行加密。

优点:

这种模式是先将明文切分成若干小段,然后每一小段与初始块或者上一段的密文段进行异或运算后,再与密钥进行加密。

优点:

计算器模式不常见,在CTR模式中, 有一个自增的算子,这个算子用密钥加密之后的输出和明文异或的结果得到密文,相当于一次一密。这种加密方式简单快速,安全可靠,而且可以并行加密,但是 在计算器不能维持很长的情况下,密钥只能使用一次 。CTR的示意图如下所示:

优点:

优点:

优点:

你是对文件内容加的密,应该和文件类型无关把。如果用的是

AES算法加的密的话,初始化的时候就会写到

keygen = KeyGeneratorgetInstance("AES");

//生成密钥

deskey = keygengenerateKey();

//生成Cipher对象,指定其支持的DES算法

c = CiphergetInstance("AES");

加密和解密的过程几乎是一样的,AES是对称加密方式,你看看加密和解密方法里的有没有写错的地方。

以上就是关于求AES加密算法 C代码全部的内容,包括:求AES加密算法 C代码、对称加密算法AES、如何使用java对密码加密 加密方式aes等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/zz/10103026.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-05-05
下一篇2023-05-05

发表评论

登录后才能评论

评论列表(0条)

    保存