2014-02-13 19:23:43 关键词:用C#和delphi编写AES 类 毕业设计 贵阳网站建设

用 C# 编写 AES 类构造函数

来源: 百优资源网 作者:管理员

核心提示:现在我已研究了构成 AES 加密算法的各个成分,我将用 C# 来实现它。官方的 AES 算法规范包含在联邦信息处理标准出版物197 (Federal Information Processing Standards Publication 197)中。我决定尽可能贴切地以它作为我的实现的基础,
已被点击
查看
收藏
  • 开心网
  • 人人网
  • i贴吧
分享
分享

| 服装连锁店ERP管理系统

服装连锁店ERP管理系统可以高效完成物流配送,考勤管理,工资管理,员工管理,报表管理,陈列管理等功能,是服装连锁企业理想的选择。[详细]

手动刷新 更新时间:14:08:37
---------------------------------------------

---------------------------------------------

用 C# 编写 AES 类构造函数

五、用 C# 编写 AES 类构造函数
  现在我已研究了构成 AES 加密算法的各个成分,我将用 C# 来实现它。官方的 AES 算法规范包含在联邦信息处理标准出版物197 (Federal Information Processing Standards Publication 197)中。我决定尽可能贴切地以它作为我的实现的基础,但是我很快发现这个规范更是一个理论文献而非一个实现的向导。为了将这个官方规范作为资源来使用,我使用 的变量名与标准出版物中所用的相同。(即便它们是那么晦涩,如“Nr”和“W”)。
    我的设计使用9个数据成员和一个枚举类型,如下所示:
public enum KeySize { Bits128, Bits192, Bits256 }; private int Nb; private int Nk; private int Nr; private byte[] key; private byte[,] Sbox; private byte[,] iSbox; private byte[,] w; private byte[,] Rcon; private byte[,] State;
    因为密钥长度只能是128位、192位或256位比特,它是非常适于用枚举类型:
public enum KeySize { Bits128, Bits192, Bits256 };
    该规范文档一般用字节作为基本储存单元而不是用4字节的字作为两个重要数据成员的长度。这两个成员 Nb 和 Nk 代表 以字为单位的块长以及以字为单位的密钥长度。Nr代表轮数。块长度总是16字节(或这说是 128 位,即为 AES 的 4个字),因此它可以被声明为一个常量。密钥长度 依照枚举参数 KeySize 的值被赋值为 4、6 或 8。AES 算法强调通过大量轮数来增加加密数据的复杂性。轮数是10、12或14中的任意一个并且是基于密码分析学理论的。它直接取决于密钥长度。
  当设计一个类接口时,我喜欢向后来做。我设想从应用程序中调用构造函数和方法。使用这个办法,我决定象下面这样来实例化一个 AES 对象:
Aes a = new Aes(the key size, the seed key)
我调用的加密和解密例程如下:
a.Cipher(plainText, cipherText); a.InvCipher(cipherText, decipheredText);
我选择少许笨拙的方法来命名 Cipher 和 InvCipher,因为它们是用在 AES 规范文档中的。这里是 AES 类构造函数的代码为:
public Aes(KeySize keySize, byte[] keyBytes) { SetNbNkNr(keySize); this.key = new byte[this.Nk * 4]; keyBytes.CopyTo(this.key, 0); BuildSbox(); BuildInvSbox(); BuildRcon(); KeyExpansion(); }
该构造函数首先调用一个辅助方法 SetNbNkNr 给 Nb、Nk 和 Nr 赋值,如 Figure 8 所示。如果考虑到效率,你可能将这些代码直接放入构造函数 以避免方法调用的开销。
  接下来,你必须将传入构造函数的字节拷贝到类域变量中。密钥用其它的类域声明,并且用如下方法获得它的值:
this.key = new byte[this.Nk * 4]; keyBytes.CopyTo(this.key, 0);
    我决定在构造函数中调用私有辅助方法 BuildSbox 和 BuildInvSbox 来初始化替换表 Sbox[] 和 iSbox[] 。现在密钥扩展例程 、Cipher 方法和 InvCipher 方法各自都需要 Sbox[] 和 iSbox[],因此我本来可以在 Cipher 和 InvCipher 两个方法中初始化 Sbox[] 并调用 KeyExpansion 方法,但是将它们放入构造函数会代码结构更加清晰。在 Figure 9 中 sBox[] 被填充。填充 iSbox[] 代码 类似。为了可读性对代码进行了结构化处理。正如后面你将看到的,还有另外一个可供选择的令人惊讶的方法为 Sbox 和 iSbox 表提供值。
  在构造函数中声明密钥调度表 w[]、轮常数表 Rcon[] 和状态矩阵 State[],并用私有辅助方法来给 Rcon[] 和 w[] 赋值在我看来似乎是组织它们的最好办法,但那主要还是个风格问题。置换轮常数表 Rcon 的赋值代码参见Figure 7。
回想一下,GF(28)中,Rcon[] 每一行左边的字节都 2 的幂,因此这个表可用下面的方法建立:
newVal = prevVal * 0x02;
  AES 构造函数在建立完密钥调度表 w[] 后结束,而 w[] 是在 KeyExpansion 方法中完成的(参见 Figure 10)。 其代码相当简单。规范文档使用一个假设的 4-字节的字数据类型。因为 C# 没有那样的类型,但可以用一个4个字节的数组来模拟。在用 new 操作符为密钥调度 表 w[] 分配空间后,w[] 最初的 Nk(4, 6, 或 8) 行从被传递到构造函数的种子密钥 key[] 数组中获值。
this.w[row,0] = this.key[4*row]; this.w[row,1] = this.key[4*row+1]; this.w[row,2] = this.key[4*row+2]; this.w[row,3] = this.key[4*row+3];
  两个字节相互的异或操作在这个代码中频频发生。它需要一些从 byte 到 int 的强制类型转换并转回到 byte,因为异或操作“^”是不能定义在 C# 的 byte 类型上,例如:
temp[0] = (byte)( (int)temp[0] ^ (int)this.Rcon[row/Nk,0] );
用来替代:
temp[0] = temp[0] ^ this.Rcon[row/Nk,0];
  KeyExpansion 方法有条件地调用私有方法 SubWord 和 RotWord 以保持同规范命名的一致性。此外,因为在C#中没有 word类型,我用 4字节数组实现了一个字。SubWord 和 RotWord 的代码是相当简单,参见本文附带的 AesLib 源代码,它应该很容易理解。
  稍微具备有些技巧的部分是在 SubWord 中查找替代值。回想一下,为了寻找代替值,你将输入字节分成最左边的4位比特和最右边的4位比特。对于一个给定字节,用 >> 操作符右移 4 位将得到 x 索引,并且与 0000 1111 进行逻辑与得到 y 值。虽然有些长,但比实际代码更可读,我可以象下面这样:
int x = word[0] >> 4; int y = word[0] & 0x0f; byte substitute = this.Sbox[x,y]; result[0] = substitute;
代替我原来用的代码:
result[0] = this.Sbox[ word[0] >> 4, word[0] & 0x0f ];
  总的来说,AES 构造函数接受一个密钥的长度为128,192 或 256 位和一个字节数组种子密钥值。构造函数为输入块长度,种子密钥长度 以及加密算法的轮数赋值,并将种子密钥拷贝到一个名为 key 的数据成员中。构造函数还创建了四个表:两个由加密和解密方法使用的替换表,一个轮常数表,和一个轮密钥的密钥调度表。


 

六、用C#编写的 AES Cipher 方法

  Cipher方法如 Figure 11 所示。它真的非常简单,因为它分出了大部分的工作给私有方法AddRoundKey, SubBytes, ShiftRows 和 MixColumns。
  Cipher 方法以拷贝明文输入数组到状态矩阵 State[] 为开始。最初调用 AddRoundKey 之后,Cipher 方法比总轮数少迭代一次。在最后一轮时,正如规范中所说的那样,MixColumns 调用被省略了。
  AddRoundKey 和 SubBytes 私有方法的代码如 Figure 12 所示。AddRoundKey 方法需要知道它处在那一轮,以便它正确引用4行密钥调度数组 w[]。请注意 State[r,c] 是用 w[c,r] 来异或并不是w[r,c]。SubBytes 方法从输入字节中提取索引,与 KeyExpansion 方法中所用的右移4位和 0x0f 屏蔽技术相同。
  ShiftRows 方法的代码如 Figure 13 所示。回想一下,ShiftRows(可能叫做 RotateRows 更好)将 row[0] 向左旋转 0 个位置,将 row[1] 向左旋转 1 位置等等。
把 State[] 拷贝到 temp[] 矩阵之后,然后用下面的这行代码实现转换:
this.State[r, (c + r) % Nb ] = temp[r,c];
这里利用%操作符的优点抱合一行。
  MixColumns 方法(Figure 14)用GF(28)加和乘,以字节列中所有其它值的线性组合对每一个字节进行替换。
乘法所用的常量系数基于域论的,并且是0x01, 0x02或 0x03中的任意一个值。给定某一列 c ,其替代式如下:
State[0,c] = 0x02 * State[0,c] + 0x03 * State[1,c] + 0x01 * State[2,c] + 0x01 * State[3,c] State[1,c] = 0x01 * State[0,c] + 0x02 * State[1,c] + 0x03 * State[2,c] + 0x01 * State[3,c] State[2,c] = 0x01 * State[0,c] + 0x01 * State[1,c] + 0x02 * State[2,c] + 0x03 * State[3,c] State[3,c] = 0x03 * State[0,c] + 0x01 * State[1,c] + 0x01 * State[2,c] + 0x02 * State[3,c]
  这些表达式稍微有些长,因此我决定编写返回 GF(28)与 0x01,0x02 和 0x03 之乘积的私有辅助函数。这些辅助函数非常短。例如,一个字节 b 被 0x03 域乘的代码如下:
return (byte) ( (int)gfmultby02(b) ^ (int)b );
  正如我前面讨论的,被 0x02 乘是所有 GF(28) 乘法的基本操作。我调用了我的 gfmultby02 方法,我改变了使用与规范相同的方法命名惯例,规范上称此例程为 xtime。
  Cipher 方法其输入反复应用四个操作来产生加密的输出。AddRoundKey 用源于单个原始种子密钥的多重轮密钥来替代字节。SubBytes 用某个替换表中的值替代字节。ShiftRows 用移动字节行置换字节,而 MixColumns 用某一列的域加和乘法值来替代字节。

 

七、用C#编写 AES InvCipher 方法

  AES 解密算法背后的基本原则很简单:解密一个加密块,也就是以反向顺序还原(Undo)每个操作。尽管这是基本概念,但仍有几个细节要处理。
  AES规范称解密例程为 InvCipher,而不是 Decipher 或 Decrypt 中的一个。这是 AES 背后的数学基础的反映,它基于可逆的数学操作。
  如果你将这个代码和 Cipher 代码比较的话,你会看到它比你预期的漂亮很多,但是有两点例外。首先,在 InvCipher 方法中逆方法调用(如 InvSubBytes)顺序并不完全与在 Cipher 方法中相应调用(如 SubBytes)的逆向顺序正好相同。其次,InvCipher 调用的是一个 AddRoundKey 方法而不是 InvAddRoundKey 方法。值得注意的是 InvCipher 算法用密钥调度表并不是从较高编号的索引处开始向下处理至第0行。
  InvSubBytes,InvShiftRows 和 InvMixColumns 方法的代码和与之有关的 SubBytes,ShiftRows和 MixColumns 方法的代码非常接近。InvSubBytes 方法几乎就是 SubBytes 方法,只是它用逆替换表 iSbox[] 而不是 Sbox[] 表。
  正如你可能猜测到的,iSbox[] 就是还原任何被 Sbox[] 处理的对应操作。比如,如果你有字节 b 等于 0x20,并在 Sbox[] 中找到其代替值,你得到 0xb7。如果你在 iSbox[] 中找到 0xb7的替代值,你便可得到 0x20。
  相似地,InvShiftRows 方法还原 ShiftRows 方法—— row[0] 被右移了 0 个位置,row[1] 被右移了 1个位置,row[2] 被右移了 2 个位置,而 row[3] 被右移了 3个位置。
  InvMixColumns 方法还原 MixColumns 的工作,但没有用显而易见的方法。回想一下,MixColumns 用原始字节列中的字节线性组合替换状态矩阵中的每个字节,并且系数是 0x01,0x02,和 0x03,域论再一次得到应用。它证明逆运算是相似的,只是被 0x09,0x0b,0x0d 和 0x0e 乘,如下所示:
State[0,c] = 0x0e * State[0,c] + 0x0b * State[1,c] + 0x0d * State[2,c] + 0x09 * State[3,c] State[1,c] = 0x09 * State[0,c] + 0x0e * State[1,c] + 0x0b * State[2,c] + 0x0d * State[3,c] State[2,c] = 0x0d * State[0,c] + 0x09 * State[1,c] + 0x0e * State[2,c] + 0x0b * State[3,c] State[3,c] = 0x0b * State[0,c] + 0x0d * State[1,c] + 0x09 * State[2,c] + 0x0e * State[3,c]
  对于 MixColumns 方法,我决定专门写一个辅助函数,而不是内联展开已经较长的表达式或写一个普通的乘法辅助函数。让我向你展示一下我示如何编写这个任何字节 b 被常数 0x0e (在10进制中的14)乘的函数,像任何数字一样,数字 14 可以被表示成 2 的幂的和,因此,14 等于 2 + 4 + 8。并且 4 等于 2 的平方,8 等于 2 的立方,你可以将14表示为 2 + 22 + 23。记住加法就是 GF(28)中上的异或(^),既然我已经有了 gfmultby02 函数,我可以用它得到我的结果:
return (byte)( (int)gfmultby02(gfmultby02(gfmultby02(b))) ^ /* 23 + */ (int)gfmultby02(gfmultby02(b)) ^ /* 22 + */ (int)gfmultby02(b) ); /* 2 */
用于 AES 加密算法的所有的操作都是可逆的,因此解密算法本质上是加密的所有操作的倒转。

 

八、使用 AES 类

  用C#实现 AES 的特色之一就简单。看看 Figure 15,它是我用来生成输出 Figure 1 的代码。声明了 16 字节 明文输入硬代码值和 24 字节(192位)的种子密钥后,一个 AES 对象被初始化,加密 Cipher 方法 将明文加密成为密文,然后再用 InvCipher 将密文解密。非常清楚和简单。
  因为 AES 对象针对字节数组进行处理,你可以轻松地用它处理.NET的其它数据类型。我创建了一个基于 Windows 的小Demo程序,它接受一个 单纯的字符串——有 8 个字符 (16-byte) ,对它进行加密和解密处理。运行画面如 Figure 16。
 

软件设计


Figure 16 加密 Demo 程序

    因为加密和解密例程都需要知道用户定义的密钥长度,我把它当作一个类范围的变量来声明,像这样:
private Aes.KeySize keysize;
  注意种子密钥并不是由用户定义的。这个demo 程序用一个“空密钥”(null key)作为种子密钥,通过为构造函数提供一个哑参数new byte[16] 使得它全部由零字节组成。哑参数的长度是不相关的,因为种子密钥还是要被初始化为零。空密钥加密和解密是一个容易和有效的办法来阻止外界对数据偶然的检查。在System.Text 中的Encoding.Unicode.GetBytes和Encoding.Unicode.GetString 方法使得将一个.NET 字符串转换成一个字节数组变得非常容易,反之亦然。
 

九、实现选择
     现在让我们看看本文AES 实现中出现的一些重要的变量,本文提供的代码可能出现的扩展,以及针对AES 的密码分析学攻击。
    和我曾经处理的任何代码一样,AES 算法也可以用其它可选的途径来实现。为什么这很重要呢?AES 被试图广泛应用于各种系统,从只有很少内存容量的智能卡(smart cards)到大型的多处理器主机系统。在许多情况下,性能是关键因素,并且有时内存或处理器资源是有限的。事实上,AES 的每个例程都能针对非常昂贵的内存资源进行性能优化,反之亦然。比如,为替换表Sbox[] 分配256 个值看起来好像很简单直白。但是,这些值是基于GF(28) 理论的,它们都可以用编程方式来生成。逆向替换表和轮常数表也是如此。
     可选实现另外一个有趣的可能性是Cipher 和InvCipher 方法所用的GF(28) 乘法。我的实现代码是一个被0x02 乘的基本函数,而后是六个调用gfmultby02 的附加函数。另一个可能性应该是写一个一般的乘法函数,并用它代替我目前实现的七个单独函数。另一个极端是你可以用被0x01, 0x02, 0x03, 0x09, 0x0b, 0x0d 和0x0e 乘好的所有256 个可能的字节值构成的一个完整乘积表。此外,实现GF(28) 乘法另一途径是通过在两个256 个字节的数组里查找,通常称为alog[] 和log[],因为它们在GF(28)中基于某些类似对数的方法。
    虽然这里给出的AES 类完全能用于加密任何形式的.NET数据,你可能考虑想用各种方法扩展它。首先,因为本文的重点在于清楚地解释AES,所有 错误检查被剥离掉,以我的经验,为某个象AES 这样的类添加合理数量的错误检查将会产生三倍的代码量膨胀。因为AES 使用了这么多的数组,需要做很多索引 边界检查。例如,所给出的构造函数甚至都不检查种子密钥参数的长度。
你可能还考虑通过添加更多的特性来扩展AES 类。最明显的一个地方是添加加密和解密.NET基本数据类型的方法,比如:System.String 和System.Int32。更加雄心勃勃的扩展可能会是实现一个 流数据加密类。
    AES 的安全性怎样呢?这是一个很难回答的问题,但是一般多数人的意见是:它是目前可获得的最安全的加密算法。AES 已被列为比任何现今其它加密算法更 安全的一种算法。在理论和实践基础上,AES 被认为是“安全的”,因为要破解它的话,唯一有效的方法是强行(brute-force)生成所有可能的密钥。 如果密钥长度为256 位,还没有已知的攻击可以在一个可接受的时间内破解AES(即便在当今最快的系统上,它也要花费数年时间)。
    注意针对AES 密码最可能成功的攻击来自一个允许时间选择攻击的弱实现。攻击者用不同的密钥并精确地测量出加密例程所需的时间。如果加密例程被粗心编码 ,因此执行时间便依赖于密钥值,它就有可能推导出有关密钥的信息。在AES 中,这种事情最可能发生在MixColumns 例程中,因为有域乘。 针对这种攻击的两个安全措施是加入虚指令,以便所以所有乘法都需要相同数量的指令,或者将域乘实现为一个查询表,就象我前面描述的那样。
    AES 有许多种可能的实现,尤其是是使用查询表而不是计算。本文提供的AES 基本类可以被用于加解密任何形式的.NET数据或 被扩展成一个具有更多功能的类。


 
十、结束语
     新的AES 将无疑成为加密所有形式电子信息的事实上的标准,取代DES。AES 加密的数据在某种意义上是牢不可破的,因为没有已知的密码分析攻击可以解密AES 密文,除非强行遍历搜索所有可能的256 位密钥。
    我发现在Microsoft .NET Framework 上实现AES 类的主要的障碍是官方文档是以一个数学家的观点,而不是以一个软件开发者的观点来写的。尤其是该规范假定读者十分熟悉GF(28) 域,并省略了几个正确实现AES 所必需的关于GF(28) 乘法的关键事实。我在本文中试图努力去掉AES 的神秘面纱,特别是围绕在GF(28) 域乘法部分的。
以.NET Framework 库的形式从Microsoft 以及第三方供应商处获得对AES 的广泛支持只是一个时间问题。然而,处于种种理由,让本文代码作为你的技能储备仍然是有价值的。这个实现尤其简单,并且是低资源开销。另外,阅读并理解源代码将使你能定制AES 类且更有效地使用它的任何实现。
在任何软件设计过程中安全已不再是后顾之忧。AES 是一个重大进步,使用并理解它将大大增加软件系统的可靠性和安全性。

 

十一、用delphi编写 AES方法
 

软件设计


测试demo:
加密:
procedure TForm1.Button1Click(Sender: TObject);
begin
    Case Combobox1.ItemIndex of
    0://128位密钥加密
      CText.Text:=EncryptString(MText.Text,KText.Text,kb128,trim(ComboBox2.Text),trim(edit1.text));
    1://192位密钥加密
      CText.Text:=EncryptString(MText.Text,KText.Text,kb192,trim(ComboBox2.Text),trim(edit1.text));
    2://256位密钥加密
      CText.Text:=EncryptString(MText.Text,KText.Text,kb256,trim(ComboBox2.Text),trim(edit1.text));
  end;
  memo1.Lines.Add(getbase64);
end;
解密:
procedure TForm1.Button2Click(Sender: TObject);
begin
  Case Combobox1.ItemIndex of
    0://128位密钥解密
      PText.Text:=DecryptString(CText.Text,KText.Text,kb128,trim(ComboBox2.Text),trim(edit1.text));
    1://192位密钥解密
      PText.Text:=DecryptString(CText.Text,KText.Text,kb192,trim(ComboBox2.Text),trim(edit1.text));
    2://256位密钥解密
      PText.Text:=DecryptString(CText.Text,KText.Text,kb256,trim(ComboBox2.Text),trim(edit1.text));
  end;
end;


单元文件(完整收费版本,支持四种模式,支持16位、24位、32位密码)。
unit ElAES;
interface
{
修改日期:2014-02-12
设计:QQ262928596
调用方法:
1: AES字符串加密
function EncryptString(Value: string; Key: AnsiString;
  KeyBit: TKeyBit = kb128;mode:string='ECB';iv:AnsiString='1234567890abcdef'): string;
Value:等加密字符串
Key  :16位\24位\32位的密钥
KeyBit:密钥长度,16字符的密钥长度选择128位, 24字符的密钥长度选择192位,32字符的密钥长度选择256位
mode:   是ECB\CBC\CFB\OFB 其中一种.
iv  :   初始化向量
返回:返回加密后的十六进制字符串

2:AES算法字符串解密
function DecryptString(Value: string; Key: AnsiString;
  KeyBit: TKeyBit = kb128;mode:string='ECB';iv:AnsiString='1234567890abcdef'): string;
Value:为十六进制的加密码串(即调用EncryptString后返回的结果)
其中参数同EncryptString的一至.

3:返回Base64码:
function GetBase64():string;//Base64编码
注意:请先调用 EncryptString方法后再调用该方法.
返回加密串的Base64编码的字符串.

}
uses
  Classes, SysUtils;
type
  TKeyBit = (kb128, kb192, kb256);

type
  EAESError = class(Exception);

  PInteger  = ^Integer;


  TAESBuffer = array [0..15] of byte;
  TAESKey128 = array [0..15] of byte;
  TAESKey192 = array [0..23] of byte;
  TAESKey256 = array [0..31] of byte;
  TAESExpandedKey128 = array [0..43] of longword;
  TAESExpandedKey192 = array [0..53] of longword;
  TAESExpandedKey256 = array [0..63] of longword;
  //FCB
  Tw = array [0..59] of integer;
  //w =^Tw;
  Ts = array [0..3,0..3] of integer;
  s=^Ts;

………….

加密算法:
function encryptCBC(Source:string;const iv:string;Dest: TStream):string;
var
     t,y:string;
     y_block:string;
     xsize:integer;
     I, J,Count: integer;
     val:char;
     TempIn, TempOut: TAESBuffer;
     Done: cardinal;
begin
      result := '';
      t:='';
      y:='';                      //returned plain text;
      y_block:=iv;
      xsize:= length(Source);     //12 源字串长度//hello world!
      i:=0;
      while i<(xsize)  do
      begin
           t:='';
           for J:=0 to 15 do
           begin
                 //$y_block[$j] = chr(ord(($i+$j)<$xsize ? $x[$i+$j] : chr(0)) ^ ord($t[$j]));
                 if (i+j)<xsize then
                 begin
                      val:=Source[i+j+1];
                 end
                 else
                 begin
                      val:=chr(0);
                 end;
                 t:=t+chr(ord(val) xor ord(y_block[j+1]));
           end;
           y_block:= encryptBlock(t);
           y:=(y) + (y_block);
           INC(i,16);
      end;
      result:=y;
end;

function encryptBlock(x:string):string;
var
     y:string;
     I, J,m,n,o,io,mm,nn: integer;
     Nb:integer;
     s:Ts;
     temp:integer;
     temp1:array [0..100] of integer;
     s0,s1,s2,s3:integer;
begin
      result:='';
      y:='';
    for I := 0 to 3 do
    begin
          for J := 0 to 3 do
          begin
                s[I][J]:=0;
          end;
    end;
      Nb:=4;
      //x值为:string(16) "1234567890abcdef"
      //将输入x为初始状态矩阵的列顺序
      for i:=0 to 4*Nb-1 do
      begin
            s[i mod 4][(i-i mod Nb) div Nb]:=ord(x[i+1]); //我们希望为二级指标integerger划分
      end;
      //array(4){[0]=>{ array(4) { [0]=> int(49) [1]=> int(53) [2]=> int(57) [3]=> int(99) }
      //         [1]=> array(4) { [0]=> int(50) [1]=>int(54) [2]=>int(48) [3]=>int(100)}
      //         [2]=> array(4) { [0]=> int(51) [1]=>int(55) [2]=>int(97) [3]=>int(101)}
      //         [3]=> array(4) { [0]=> int(52) [1]=>int(56) [2]=>int(98) [3]=>int(102)}
      //}
                //addRoundKey(0);
                  temp:=0;
                  for i:=0 to 3 do
                  begin
                          for j:=0 to Nb-1 do
                          begin
                                 temp:=((w[0*Nb+j]) shr ((3-i)*8)); //1633837924右移24位值为97
                                 temp:=temp mod 256;
                                 if temp<0 then
                                 begin
                                      temp:=256 + temp;
                                 end;
                                 s[i][j]:=s[i][j] xor temp;
                          end;
                  end;
    //   array(4) { [0]=> array(4) { [0]=> int(80) [1]=> int(80) [2]=> int(80) [3]=> int(15) }
    //              [1]=> array(4) { [0]=> int(80) [1]=> int(80) [2]=> int(90) [3]=>  int(9) }
    //              [2]=> array(4) { [0]=> int(80)  [1]=>int(80) [2]=> int(20) [3]=> int(11) }
    //              [3]=> array(4) { [0]=> int(80)  [1]=>int(80) [2]=> int(9)  [3]=> int(9)  }
     //   }

                //////////////////////////////
                for i:=1 to Nr-1 do
                begin
                     //$this->subBytes();
                     for mm:=0 to 3 do
                     begin
                          for nn:=0 to Nb-1 do
                          begin
                                s[mm][nn]:= LastForwardTable[s[mm][nn]];
                          end;
                     end;
                     //array(4) {
                     // [0]=>  array(4) {  [0]=> int(83) [1]=>int(83)[2]=> int(83) [3]=> int(118) }
                     // [1]=>  array(4) { [0]=>int(83) [1]=> int(83) [2]=>int(190)[3]=> int(1)}
                     // [2]=>  array(4) { [0]=>int(83) [1]=> int(83) [2]=>int(250)[3]=>int(43)}
                     // [3]=>  array(4) { [0]=>int(83) [1]=> int(83) [2]=>int(1)  [3]=>int(1)}
                     //}
                     ////////////////////////////////////////////
                        //$this->shiftRows();
                        for o:=0 to 100 do
                        begin
                              temp1[o]:=0;
                        end;
                        for m:=1 to 3 do
                        begin
                              for n:=0 to Nb-1 do
                              begin
                                    temp1[n]:=s[m][(n+m) mod Nb];
                              end;
                              for n:=0 to Nb-1 do
                              begin
                                    s[m][n]:=temp1[n];
                              end;
                        end;
                        //array(4) {
                        //  [0]=> array(4) {[0]=>int(83)[1]=> int(83) [2]=> int(83)[3]=>int(118) }
                        //  [1]=> array(4) {[0]=>int(83)[1]=> int(190)[2]=> int(1) [3]=>int(83) }
                        //  [2]=> array(4) {[0]=>int(250)[1]=>int(43) [2]=> int(83)[3]=>int(83) }
                        //  [3]=> array(4) {[0]=>int(1)  [1]=>int(83) [2]=> int(83) [3]=>int(1) }
                        //}
                     //////////////////////////////////////////
                        //$this->mixColumns();
                          s0:=0; s1:=0; s2:=0; s3:=0;
                        // There are Nb columns
                        for m:=0 to Nb-1 do
                        begin
                                s0:= s[0][m]; s1:=s[1][m];s2:=s[2][m];s3:=s[3][m];
                                //83==83==250==1
                                s[0][m]:=mult($02, s0) xor mult($03, s1) xor mult($01, s2)xor mult($01,s3);
                                //166 xor  245  xor 250 xor 1
                                s[1][m]:=mult($01, s0) xor  mult($02, s1) xor  mult($03, s2) xor  mult($01, s3);
                                s[2][m]:=  mult($01, s0) xor  mult($01, s1) xor  mult($02, s2) xor  mult($03,s3);
                                s[3][m]:=  mult($03, s0) xor  mult($01, s1) xor  mult($01, s2) xor  mult($02,s3);
                        end;
                        //array(4) {
                        //  [0]=> array(4) { [0]=>int(168) [1]=>int(7)  [2]=>int(165) [3]=>int(75)}
                        //  [1]=> array(4) { [0]=>int(225) [1]=>int(26) [2]=>int(247) [3]=>int(36)}
                        //  [2]=> array(4) { [0]=>int(236) [1]=>int(78) [2]=>int(1)   [3]=> int(128)}
                        //  [3]=> array(4) { [0]=>int(94)  [1]=>int(198)[2]=>int(1)   [3]=> int(152)}
                        //}

 

                        ////////////////////////////////////////
                        // add round key
                        //$this->addRoundKey($i);
                          temp:=0;
                          for m:=0 to 3 do
                          begin
                                  for n:=0 to Nb-1 do
                                  begin
                                         temp:=((w[i*Nb+n]) shr ((3-m)*8));
                                         temp:=temp mod 256;
                                         if temp<0 then
                                         begin
                                              temp:=256 + temp;
                                         end;
                                         s[m][n]:=s[m][n] xor temp;
                                  end;
                          end;
                          //开始array(4) {
                          //  [0]=>array(4) { [0]=> int(152) [1]=>int(51) [2]=> int(157) [3]=> int(121)  }
                          //  [1]=>array(4) { [0]=> int(208) [1]=>int(47) [2]=> int(206) [3]=> int(23) }
                          //  [2]=>array(4) { [0]=> int(222) [1]=>int(120)[2]=> int(49)  [3]=> int(180)  }
                          //  [3]=>array(4) { [0]=> int(109) [1]=>int(241)[2]=> int(48) [3]=> int(173) }
                          //}
                          //未尾array(4) {
                          //  [0]=>  array(4) { [0]=> int(159)[1]=>int(19) [2]=>int(2)   [3]=> int(207)}
                          //  [1]=>  array(4) { [0]=> int(31) [1]=>int(110)[2]=>int(103) [3]=> int(151)}
                          //  [2]=>  array(4) { [0]=> int(223)[1]=>int(67) [2]=>int(160) [3]=> int(86) }
                          //  [3]=>  array(4) { [0]=> int(26) [1]=>int(32) [2]=>int(170) [3]=> int(174)}
                          //}
                       /////////////////////////////////////////
                end;
                io:=i;
                // substitute bytes
                //$this->subBytes();
                for i:=0 to 3 do
                begin
                        for j:=0 to Nb-1 do
                        begin
                            s[i][j] := LastForwardTable[s[i][j]];
                        end;
                end;
                //////////////////////////////////////////////////////////
                // shift rows
                //$this->shiftRows();
                for o:=0 to 100 do
                begin
                    temp1[o]:=0;
                end;
                for m:=1 to 3 do
                begin
                      for n:=0 to Nb-1 do
                      begin
                            temp1[n]:=s[m][(n+m) mod Nb];
                      end;
                      for n:=0 to Nb-1 do
                      begin
                            s[m][n]:=temp1[n];
                      end;
                end;
                //////////////////////////////////////////////////////////
                // add round key
                //$this->addRoundKey($i);
                  temp:=0;
                  for i:=0 to 3 do
                  begin
                          for j:=0 to Nb-1 do
                          begin
                                 temp:=((w[io*Nb+j]) shr ((3-i)*8));
                                 temp:=temp mod 256;
                                 if temp<0 then
                                 begin
                                      temp:=256 + temp;
                                 end;
                                 s[i][j]:=s[i][j] xor temp;
                          end;
                  end;
                //////////////////////////////////////////////////////////
                // place state matrix s into y in column order
                for i:=0 to (4*Nb-1) do
                begin
                       y:=y+chr(s[i mod 4][(i-i mod Nb) div Nb]);
                end;
                //y='??'#$13'nC '#2'g牚蠗V'#$AE
                //int(159)int(31)int(223)int(26)int(19)int(110)int(67)int(32)int(2)int(103)int(160)int(170)int(207)int(151)int(86)int(174)
                result:=y;
end;

软件设计

 

特别提示: 本站可以为你进行算法程序设计, 有完整的AES算法代码,  其中的Delphi编写的AES算法代码是网上找不到的,如果你需要,可以联系本站服务QQ262928596. 


 【推荐阅读】
软件设计网站建设策略分析
贵阳网站建设的站内结构优化
用 C# 编写 AES 类构造函数
AES对称加密算法原理详解

声明:本站内容凡注明"来源:百优资源网"的所有文字、图片等资料,版权均属百优资源网原创,任何媒体、网站或个人不得转载、链接、转贴或以其他方式复制发布/发表。本网站部分资源来源于网络,如果有侵犯你的权利,请联系本站删除。

网友评论
用户名 密码 自动登录 登录
*网友评论仅供其表达个人看法 发表评论
  • 软件设计 196
    使用VC++加载图片技巧

    软件设计 | 使用VC++加载图片技巧

    在界面添加图片,在VB、delphi等软件设计语言中很简单,但是在VC++中是很难实现,这过程不但要对图片进行导入,还要显示,最后要清除内存。下面小编对这个方法进行了整理,直接复制就可以实现使用VC++加载图片技巧了。

    毕业设计 683
    毕业设计论文智能管理系统设计的意义

    毕业设计 | 毕业设计论文智能管理系统设计的意义

    毕业设计(论文)是高等院校人才培养过程中不可或缺的重要环节,一直受到各高等学校的高度重视。毕业论文网上管理是高校信息化的一个重要体现,本文对毕业设计论文智能管理系统设计的意义进行介绍。

    毕业论文 832
    教育叙事案例

    毕业论文 | 教育叙事案例

     热爱一个学生就等于塑造一个学生,而厌弃一个学生无异于毁坏一个学生。热爱学生,不仅要爱好学生,更要爱有缺点、有问题的落后学生。正因其差,因其问题多,才需要教师付出更多的时间、精力和爱心。 

860010-1102010400