高級加密標準(英語:Advanced Encryption
Standard,縮寫:AES),在密碼學中又稱Rijndael加密法,是美國聯邦政府采用的一種區塊加密標準。這個標準用來替代原先的DES,已經被多方分析且廣為全世界所使用。經過五年的甄選流程,高級加密標準由美國國家標準與技術研究院(NIST)于2001年11月26日發布于FIPS
PUB 197,并在2002年5月26日成為有效的標準。2006年,高級加密標準已然成為對稱密鑰加密中最流行的算法之一。
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自動生成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
密碼說明
嚴格地說,AES和Rijndael加密法并不完全一樣(雖然在實際應用中二者可以互換),因為Rijndael加密法可以支持更大范圍的區塊和密鑰長度:AES的區塊長度固定為128
比特,密鑰長度則可以是128,192或256比特;而Rijndael使用的密鑰和區塊長度可以是32位的整數倍,以128位為下限,256比特為上限。加密過程中使用的密鑰是由Rijndael密鑰生成方案產生。
大多數AES計算是在一個特別的有限域完成的。
AES加密過程是在一個4×4的字節矩陣上運作,這個矩陣又稱為“狀態(state)”,其初值就是一個明文區塊(矩陣中一個元素大小就是明文區塊中的一個Byte)。(Rijndael加密法因支持更大的區塊,其矩陣行數可視情況增加)加密時,各輪AES加密循環(除最后一輪外)均包含4個步驟:
AddRoundKey — 矩陣中的每一個字節都與該次輪秘鑰(round key)做XOR運算;每個子密鑰由密鑰生成方案產生。
SubBytes — 通過非線性的替換函數,用查找表的方式把每個字節替換成對應的字節。 ShiftRows —
將矩陣中的每個橫列進行循環式移位。 MixColumns — 為了充分混合矩陣中各個直行的操作。這個步驟使用線性轉換來混合每列的四個字節。
最后一個加密循環中省略MixColumns步驟,而以另一個AddRoundKey取代。
加密標準
對稱密碼體制的發展趨勢將以分組密碼為重點。分組密碼算法通常由密鑰擴展算法和加密(解密)算法兩部分組成。密鑰擴展算法將b字節用戶主密鑰擴展成r個子密鑰。加密算法由一個密碼學上的弱函數f與r個子密鑰迭代r次組成。混亂和密鑰擴散是分組密碼算法設計的基本原則。抵御已知明文的差分和線性攻擊,可變長密鑰和分組是該體制的設計要點。
AES是美國國家標準技術研究所NIST旨在取代DES的21世紀的加密標準。
AES的基本要求是,采用對稱分組密碼體制,密鑰的長度最少支持為128、192、256,分組長度128位,算法應易于各種硬件和軟件實現。1998年NIST開始AES第一輪分析、測試和征集,共產生了15個候選算法。1999年3月完成了第二輪AES2的分析、測試。2000年10月2日美國政府正式宣布選中比利時密碼學家Joan
Daemen 和 Vincent Rijmen 提出的一種密碼算法RIJNDAEL 作為 AES.
在應用方面,盡管DES在安全上是脆弱的,但由于快速DES芯片的大量生產,使得DES仍能暫時繼續使用,為提高安全強度,通常使用獨立密鑰的三級DES。但是DES遲早要被AES代替。流密碼體制較之分組密碼在理論上成熟且安全,但未被列入下一代加密標準。
AES加密數據塊分組長度必須為128比特,密鑰長度可以是128比特、192比特、256比特中的任意一個(如果數據塊及密鑰長度不足時,會補齊)。AES加密有很多輪的重復和變換。大致步驟如下:1、密鑰擴展(KeyExpansion),2、初始輪(Initial
Round),3、重復輪(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;
/**
* 自動生成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, "請輸入加密內容", Toast.LENGTH_SHORT).show();
return;
}
try {
String hexKey = new AlgorithmUtil().getAESKey();
// 注意,這里的encoded是不能強轉成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";
/**
* 將二進制轉換成16進制
*
* @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進制轉換為二進制
*
* @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;
}
/**
* 生成密鑰
* 自動生成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[] 數組
* @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[] 數組
* @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;
}
}