高級加密標(biāo)準(zhǔn)(英語:Advanced Encryption
Standard,縮寫:AES),在密碼學(xué)中又稱Rijndael加密法,是美國聯(lián)邦政府采用的一種區(qū)塊加密標(biāo)準(zhǔn)。這個(gè)標(biāo)準(zhǔn)用來替代原先的DES,已經(jīng)被多方分析且廣為全世界所使用。經(jīng)過五年的甄選流程,高級加密標(biāo)準(zhǔn)由美國國家標(biāo)準(zhǔn)與技術(shù)研究院(NIST)于2001年11月26日發(fā)布于FIPS
PUB 197,并在2002年5月26日成為有效的標(biāo)準(zhǔn)。2006年,高級加密標(biāo)準(zhǔn)已然成為對稱密鑰加密中最流行的算法之一。
MD5加密算法:http://blog.csdn.net/huangxiaoguo1/article/details/78042596
Base64加密解密:http://blog.csdn.net/huangxiaoguo1/article/details/78042715
異或加密解密:http://blog.csdn.net/huangxiaoguo1/article/details/78042802
DES加密解密:http://blog.csdn.net/huangxiaoguo1/article/details/78042908
AES自動(dòng)生成base64密鑰加密解密:http://blog.csdn.net/huangxiaoguo1/article/details/78043000
AES加密解密(ECB模式):http://blog.csdn.net/huangxiaoguo1/article/details/78043098
AES加密解密(CBC模式):http://blog.csdn.net/huangxiaoguo1/article/details/78043169
非對稱RSA加密解密:http://blog.csdn.net/huangxiaoguo1/article/details/78043354
密碼說明
嚴(yán)格地說,AES和Rijndael加密法并不完全一樣(雖然在實(shí)際應(yīng)用中二者可以互換),因?yàn)镽ijndael加密法可以支持更大范圍的區(qū)塊和密鑰長度:AES的區(qū)塊長度固定為128
比特,密鑰長度則可以是128,192或256比特;而Rijndael使用的密鑰和區(qū)塊長度可以是32位的整數(shù)倍,以128位為下限,256比特為上限。加密過程中使用的密鑰是由Rijndael密鑰生成方案產(chǎn)生。
大多數(shù)AES計(jì)算是在一個(gè)特別的有限域完成的。
AES加密過程是在一個(gè)4×4的字節(jié)矩陣上運(yùn)作,這個(gè)矩陣又稱為“狀態(tài)(state)”,其初值就是一個(gè)明文區(qū)塊(矩陣中一個(gè)元素大小就是明文區(qū)塊中的一個(gè)Byte)。(Rijndael加密法因支持更大的區(qū)塊,其矩陣行數(shù)可視情況增加)加密時(shí),各輪AES加密循環(huán)(除最后一輪外)均包含4個(gè)步驟:
AddRoundKey — 矩陣中的每一個(gè)字節(jié)都與該次輪秘鑰(round key)做XOR運(yùn)算;每個(gè)子密鑰由密鑰生成方案產(chǎn)生。
SubBytes — 通過非線性的替換函數(shù),用查找表的方式把每個(gè)字節(jié)替換成對應(yīng)的字節(jié)。 ShiftRows —
將矩陣中的每個(gè)橫列進(jìn)行循環(huán)式移位。 MixColumns — 為了充分混合矩陣中各個(gè)直行的操作。這個(gè)步驟使用線性轉(zhuǎn)換來混合每列的四個(gè)字節(jié)。
最后一個(gè)加密循環(huán)中省略MixColumns步驟,而以另一個(gè)AddRoundKey取代。
加密標(biāo)準(zhǔn)
對稱密碼體制的發(fā)展趨勢將以分組密碼為重點(diǎn)。分組密碼算法通常由密鑰擴(kuò)展算法和加密(解密)算法兩部分組成。密鑰擴(kuò)展算法將b字節(jié)用戶主密鑰擴(kuò)展成r個(gè)子密鑰。加密算法由一個(gè)密碼學(xué)上的弱函數(shù)f與r個(gè)子密鑰迭代r次組成?;靵y和密鑰擴(kuò)散是分組密碼算法設(shè)計(jì)的基本原則。抵御已知明文的差分和線性攻擊,可變長密鑰和分組是該體制的設(shè)計(jì)要點(diǎn)。
AES是美國國家標(biāo)準(zhǔn)技術(shù)研究所NIST旨在取代DES的21世紀(jì)的加密標(biāo)準(zhǔn)。
AES的基本要求是,采用對稱分組密碼體制,密鑰的長度最少支持為128、192、256,分組長度128位,算法應(yīng)易于各種硬件和軟件實(shí)現(xiàn)。1998年NIST開始AES第一輪分析、測試和征集,共產(chǎn)生了15個(gè)候選算法。1999年3月完成了第二輪AES2的分析、測試。2000年10月2日美國政府正式宣布選中比利時(shí)密碼學(xué)家Joan
Daemen 和 Vincent Rijmen 提出的一種密碼算法RIJNDAEL 作為 AES.
在應(yīng)用方面,盡管DES在安全上是脆弱的,但由于快速DES芯片的大量生產(chǎn),使得DES仍能暫時(shí)繼續(xù)使用,為提高安全強(qiáng)度,通常使用獨(dú)立密鑰的三級DES。但是DES遲早要被AES代替。流密碼體制較之分組密碼在理論上成熟且安全,但未被列入下一代加密標(biāo)準(zhǔn)。
AES加密數(shù)據(jù)塊分組長度必須為128比特,密鑰長度可以是128比特、192比特、256比特中的任意一個(gè)(如果數(shù)據(jù)塊及密鑰長度不足時(shí),會補(bǔ)齊)。AES加密有很多輪的重復(fù)和變換。大致步驟如下:1、密鑰擴(kuò)展(KeyExpansion),2、初始輪(Initial
Round),3、重復(fù)輪(Rounds),每一輪又包括:SubBytes、ShiftRows、MixColumns、AddRoundKey,4、最終輪(Final
Round),最終輪沒有MixColumns。
效果
代碼
AES128Activity
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import tsou.com.encryption.R;
import tsou.com.encryption.aes128.AlgorithmUtil;
/**
* 自動(dòng)生成base64密鑰
*/
public class AES128Activity extends AppCompatActivity implements View.OnClickListener {
private EditText encryptionContext;
private Button encryption;
private TextView tvEncryption;
private Button decode;
private TextView tvDecode;
private Activity mActivity;
private Context mContext;
private byte[] encoded;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_aes);
mActivity = this;
mContext = this;
encryptionContext = (EditText) findViewById(R.id.et_encryption_context);
encryption = (Button) findViewById(R.id.btn_encryption);
tvEncryption = (TextView) findViewById(R.id.tv_encryption);
decode = (Button) findViewById(R.id.btn_decode);
tvDecode = (TextView) findViewById(R.id.tv_decode);
initListener();
}
private void initListener() {
encryption.setOnClickListener(this);
decode.setOnClickListener(this);
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.btn_encryption://加密
String encryptionString = encryptionContext.getText().toString().trim();
if (TextUtils.isEmpty(encryptionString)) {
Toast.makeText(mContext, "請輸入加密內(nèi)容", Toast.LENGTH_SHORT).show();
return;
}
try {
String hexKey = new AlgorithmUtil().getAESKey();
// 注意,這里的encoded是不能強(qiáng)轉(zhuǎn)成string類型字符串的
encoded = AlgorithmUtil.getAESEncode(hexKey, encryptionString);
tvEncryption.setText(hexKey);
} catch (Exception e) {
e.printStackTrace();
}
break;
case R.id.btn_decode://解密
String decodeString = tvEncryption.getText().toString().trim();
if (TextUtils.isEmpty(decodeString)) {
Toast.makeText(mContext, "請先加密", Toast.LENGTH_SHORT).show();
return;
}
try {
byte[] decoded = AlgorithmUtil.getAESDecode(decodeString, encoded);
tvDecode.setText(new String(decoded));
} catch (Exception e) {
e.printStackTrace();
}
break;
}
}
}
AlgorithmUtil
package tsou.com.encryption.aes128;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
public class AlgorithmUtil {
public final static String ENCODING = "UTF-8";
/**
* 將二進(jìn)制轉(zhuǎn)換成16進(jìn)制
*
* @param buf
* @return
*/
public static String parseByte2HexStr(byte buf[]) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < buf.length; i++) {
String hex = Integer.toHexString(buf[i] & 0xFF);
if (hex.length() == 1) {
hex = '0' + hex;
}
sb.append(hex.toUpperCase());
}
return sb.toString();
}
/**
* 將16進(jìn)制轉(zhuǎn)換為二進(jìn)制
*
* @param hexStr
* @return
*/
public static byte[] parseHexStr2Byte(String hexStr) {
if (hexStr.length() < 1)
return null;
byte[] result = new byte[hexStr.length() / 2];
for (int i = 0; i < hexStr.length() / 2; i++) {
int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16);
result[i] = (byte) (high * 16 + low);
}
return result;
}
/**
* 生成密鑰
* 自動(dòng)生成base64 編碼后的AES128位密鑰
*
* @throws //NoSuchAlgorithmException
* @throws //UnsupportedEncodingException
*/
public static String getAESKey() throws Exception {
KeyGenerator kg = KeyGenerator.getInstance("AES");
kg.init(128);//要生成多少位,只需要修改這里即可128, 192或256
SecretKey sk = kg.generateKey();
byte[] b = sk.getEncoded();
return parseByte2HexStr(b);
}
/**
* AES 加密
*
* @param base64Key base64編碼后的 AES key
* @param text 待加密的字符串
* @return 加密后的byte[] 數(shù)組
* @throws Exception
*/
public static byte[] getAESEncode(String base64Key, String text) throws Exception {
byte[] key = parseHexStr2Byte(base64Key);
SecretKeySpec sKeySpec = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, sKeySpec);
byte[] bjiamihou = cipher.doFinal(text.getBytes(ENCODING));
return bjiamihou;
}
/**
* AES解密
*
* @param base64Key base64編碼后的 AES key
* @param text 待解密的字符串
* @return 解密后的byte[] 數(shù)組
* @throws Exception
*/
public static byte[] getAESDecode(String base64Key, byte[] text) throws Exception {
byte[] key = parseHexStr2Byte(base64Key);
SecretKeySpec sKeySpec = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, sKeySpec);
byte[] bjiemihou = cipher.doFinal(text);
return bjiemihou;
}
}