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变换一样,都是按位与子密钥做异或操作。解密过程的密钥膨胀算法也与加密的密钥膨胀算法相同。最后状态矩阵中的数据就是明文。
❷ AES加密算法256位密钥与128位密钥的不同是什么
一、指代不同
1、256位密钥:AES的区块长度固定为256位,密钥长度则可以是256。
2、128位密钥:AES的区块长度固定为128位,密钥长度则可以是128。
二、安全性不同
1、256位密钥:256位密钥安全性高于128位密钥。
2、128位密钥:128位密钥安全性低于256位密钥。
(2)javaaes128扩展阅读
AES和Rijndael加密法并不完全一样(虽然在实际应用中二者可以互换),因为Rijndael加密法可以支持更大范围的区块和密钥长度。
AES的区块长度固定为128位,密钥长度则可以是128,192或256位;而Rijndael使用的密钥和区块长度可以是32位的整数倍,以128位为下限,256位为上限。加密过程中使用的密钥是由Rijndael密钥生成方案产生。
对称/分组密码一般分为流加密(如OFB、CFB等)和块加密(如ECB、CBC等)。对于流加密,需要将分组密码转化为流模式工作。对于块加密(或称分组加密),如果要加密超过块大小的数据,就需要涉及填充和链加密模式。
ECB模式是最早采用和最简单的模式,将加密的数据分成若干组,每组的大小跟加密密钥长度相同,然后每组都用相同的密钥进行加密。
❸ AES-128 加密算法的问题
AES内部始终使用16 byte的分组长度!加密时,如果明文字节长度不是16的整数倍,要填充到大于该长度的最接近的16的倍数,但是如果刚好等于16的倍数,就额外在添加一个完整的分组,也就是添加16字节。具体你的例子,得到的是32字节长度的密文。细节请参考PKCS5/7,这些标准是权威指南!
❹ aes128绠楁硶 瀵嗘枃鍜屾槑鏂囧备綍绠楀嚭瀵嗙爜
AES-128鏄涓绉嶅圭О锷犲瘑绠楁硶锛屼娇鐢ㄧ浉钖岀殑瀵嗛挜杩涜屽姞瀵嗗拰瑙e瘑銆傚瘑阍ラ暱搴︿负128浣嶏纸16瀛楄妭锛夛纴瀵嗛挜鍙浠ユ槸闅忔満鐢熸垚镄勚
瑕佽$畻鍑哄瘑镰侊纸鍗冲瘑鏂囧拰鏄庢枃涔嬮棿镄勮浆鎹锛夛纴闇瑕佷互涓嬫ラわ细
1. 瀵嗛挜鐢熸垚锛氶栧厛锛岄渶瑕佺敓鎴愪竴涓128浣岖殑瀵嗛挜銆傚瘑阍ュ彲浠ユ槸闅忔満鐢熸垚镄勶纴涔熷彲浠ヤ娇鐢ㄥ瘑镰佸﹀畨鍏ㄧ殑浼闅忔満鏁扮敓鎴愬櫒鐢熸垚銆
2. 鍒嗙粍鍜屽~鍏咃细灏嗘槑鏂囧垎鎴愬浐瀹氶暱搴︾殑鍧楋纸阃氩父涓128浣嶏级銆傚傛灉鏄庢枃镄勯暱搴︿笉鏄鍧楅暱搴︾殑鏁存暟鍊嶏纴闇瑕佽繘琛屽~鍏咃纴浠ユ弧瓒冲潡闀垮害镄勮佹眰銆
3. 鍒濆嬭疆瀵嗛挜锷狅细灏嗙敓鎴愮殑瀵嗛挜涓庣涓涓瀵嗘枃鍧楄繘琛屽纾鎴栨搷浣溿
4. 杞鍑芥暟锛欰ES绠楁硶涓浣跨敤浜嗕竴绯诲垪镄勮疆鍑芥暟锛屽寘𨰾瀛楄妭浠f崲锛圫ubBytes锛夈佽屼綅绉伙纸ShiftRows锛夈佸垪娣锋穯锛圡ixColumns锛夊拰杞瀵嗛挜锷狅纸AddRoundKey锛夌瓑镎崭綔銆傝繖浜涙搷浣滃湪姣忎竴杞涓閮戒细琚搴旂敤鍒板瘑鏂囧潡涓娿
5. 杞鏁板惊鐜锛氭牴鎹瓵ES绠楁硶镄勮勫畾锛屾牴鎹瀵嗛挜闀垮害纭瀹氩姞瀵呜疆鏁般傛疮涓杞涓閮戒细瀵瑰瘑鏂囧潡杩涜屼竴绯诲垪镄勮疆鍑芥暟镎崭綔銆
6. 链钖庝竴杞锛氩湪链钖庝竴杞涓锛屼笉浼氭墽琛屽垪娣锋穯锛圡ixColumns锛夋搷浣溿
7. 瀵嗘枃鐢熸垚锛氱粡杩囨墍链夎疆鏁扮殑澶勭悊钖庯纴链钖庡缑鍒扮殑瀵嗘枃鍗充负锷犲瘑钖庣殑缁撴灉銆
瑙e瘑杩囩▼涓庡姞瀵呜繃绋嬬浉浼硷纴鍙鏄鍦ㄨ疆瀵嗛挜锷狅纸AddRoundKey锛夋ラや腑浣跨敤镄勬槸阃嗗瘑阍ワ纴浠ラ嗗簭杩涜岃В瀵嗘搷浣溿
闇瑕佹敞镒忕殑鏄锛屽姞瀵嗗拰瑙e瘑浣跨敤鐩稿悓镄勫瘑阍ワ纴锲犳ゅ湪杩涜屾暟鎹浼犺緭镞讹纴闇瑕佺‘淇濆瘑阍ョ殑瀹夊叏镐э纴浠ュ厤琚链鎺堟潈镄勪汉銮峰缑瀵嗛挜骞惰В瀵嗘暟鎹銆
❺ java实现ase加密解密
这个算法java SDK自带的额 参考代码如下:
/**解密
*@paramcontent待解密内容
*@parampassword解密密钥
*@return
*/
publicstaticbyte[]decrypt(byte[]content,Stringpassword){
try{
KeyGeneratorkgen=KeyGenerator.getInstance("AES");
kgen.init(128,newSecureRandom(password.getBytes()));
SecretKeysecretKey=kgen.generateKey();
byte[]enCodeFormat=secretKey.getEncoded();
SecretKeySpeckey=newSecretKeySpec(enCodeFormat,"AES");
Ciphercipher=Cipher.getInstance("AES");//创建密码器
cipher.init(Cipher.DECRYPT_MODE,key);//初始化
byte[]result=cipher.doFinal(content);
returnresult;//加密
}catch(NoSuchAlgorithmExceptione){
e.printStackTrace();
}catch(NoSuchPaddingExceptione){
e.printStackTrace();
}catch(InvalidKeyExceptione){
e.printStackTrace();
}catch(IllegalBlockSizeExceptione){
e.printStackTrace();
}catch(BadPaddingExceptione){
e.printStackTrace();
}
returnnull;
}
/**
*加密
*
*@paramcontent需要加密的内容
*@parampassword加密密码
*@return
*/
publicstaticbyte[]encrypt(Stringcontent,Stringpassword){
try{
KeyGeneratorkgen=KeyGenerator.getInstance("AES");
kgen.init(128,newSecureRandom(password.getBytes()));
SecretKeysecretKey=kgen.generateKey();
byte[]enCodeFormat=secretKey.getEncoded();
SecretKeySpeckey=newSecretKeySpec(enCodeFormat,"AES");
Ciphercipher=Cipher.getInstance("AES");//创建密码器
byte[]byteContent=content.getBytes("utf-8");
cipher.init(Cipher.ENCRYPT_MODE,key);//初始化
byte[]result=cipher.doFinal(byteContent);
returnresult;//加密
}catch(NoSuchAlgorithmExceptione){
e.printStackTrace();
}catch(NoSuchPaddingExceptione){
e.printStackTrace();
}catch(InvalidKeyExceptione){
e.printStackTrace();
}catch(UnsupportedEncodingExceptione){
e.printStackTrace();
}catch(IllegalBlockSizeExceptione){
e.printStackTrace();
}catch(BadPaddingExceptione){
e.printStackTrace();
}
returnnull;
}
http://blog.csdn.net/hbcui1984/article/details/5201247
图像界面的话就不说了