Android資料加密DES、3DES、AES
在Android開發中,可能會遇到對資料進行加密的情況。典型的對稱加密演算法有DES、3DES、AES等。
一.DES
DES演算法的入口引數有三個:Key、Data、Mode。其中Key為7個位元組共56位,是DES演算法的工作金鑰;Data為8個位元組64位,是要被加密或被解密的資料;Mode為DES的工作方式,有兩種:加密或解密。
DES設計中使用了分組密碼設計的兩個原則:混淆(confusion)和擴散,其目的是抗擊敵手對密碼系統的統計分析。混淆是使密文的統計特性與金鑰的取值之間的關係儘可能複雜化,以使金鑰和明文以及密文之間的依賴性對密碼分析者來說是無法利用的。擴散的作用就是將每一位明文的影響儘可能迅速地作用到較多的輸出密文位中,以便在大量的密文中消除明文的統計結構,並且使每一位金鑰的影響儘可能迅速地擴充套件到較多的密文位中,以防對金鑰進行逐段破譯。
DES演算法把64位的明文輸入塊變為64位的密文輸出塊,它所使用的金鑰也是64位(實際用到了56位,第8、16、24、32、40、48、56、64位是校驗位, 使得每個金鑰都有奇數個1),其演算法主要分為兩步:
(1)初始置換
其功能是把輸入的64位資料塊按位重新組合,並把輸出分為L0、R0兩部分,每部分各長32位,其置換規則為將輸入的第58位換到第一位,第50位換到第2位……依此類推,最後一位是原來的第7位。L0、R0則是換位輸出後的兩部分,L0是輸出的左32位,R0是右32位,例:設定換前的輸入值為D1D2D3……D64,則經過初始置換後的結果為:L0=D58D50……D8;R0=D57D49……D7。
58,50,42,34,26,18,10,2,60,52,44,36,28,20,12,4,
62,54,46,38,30,22,14,6,64,56,48,40,32,24,16,8,
57,49,41,33,25,17,9,1,59,51,43,35,27,19,11,3,
61,53,45,37,29,21,13,5,63,55,47,39,31,23,15,7,
(2)逆置換
經過16次迭代運算後,得到L16、R16,將此作為輸入,進行逆置換,逆置換正好是初始置換的逆運算,由此即得到密文輸出。
此演算法是對稱加密演算法體系中的代表,在計算機網路系統中廣泛使用。 二.3DES
3DES又稱Triple DES,是DES加密演算法的一種模式,它使用3條56位的金鑰對資料進行三次加密。資料加密標準(DES)是美國的一種由來已久的加密標準,它使用對稱金鑰加密法,並於1981年被ANSI組織規範為ANSI X.3.92。DES使用56位金鑰和密碼塊的方法,而在密碼塊的方法中,文字被分成64位大小的文字塊然後再進行加密。比起最初的DES,3DES更為安全。
3DES是DES向AES過渡的加密演算法(1999年,NIST將3-DES指定為過渡的加密標準),加密演算法,其具體實現如下:設Ek()和Dk()代表DES演算法的加密和解密過程,K代表DES演算法使用的金鑰,M代表明文,C代表密文,這樣:
3DES加密過程為:C=Ek3(Dk2(Ek1(M)))
3DES解密過程為:M=Dk1(EK2(Dk3(C)))
三.AES
20世紀末,當差分密碼分析及線性密碼分析出現以後,由美國人開創的DES(DataEncryptionStandard,即資料加密標準)逐漸由繁榮走向衰落。1997年 1月2日,美國國家和標準技術研究所 (NIST)釋出高階加密標準fAES—FIPS)研發計劃,9月12日釋出徵集候選演算法公告,NIST計劃確定一種可以保護敏感資訊的公開、全球通用並且免費的演算法作為AES(Advanced EncryptionStandard,即高階加密標準),用以取代DES。對該標準的基本要求是
:支援 128位元分組長度和 128、192、256位元 金鑰長度,並且演算法必須是私鑰體制的分組密碼。經過 3年多時間的反覆較量,對首輪人選的15種不同演算法進行了廣泛的評估和測試,篩選出5種演算法進人決賽。由比利時的密碼專家JoanDaemen及VincentRijmen所提出的R~ndeal加密演算法,最終勝出。2000年l0月2日,Rijndael演算法被 NIST確定為新一代高階加密標準。
密碼演算法的理論與實現研究是資訊保安研究的基礎。對各類電子資訊進行加密,在其儲存、處理、傳送以及交換過程中實施保護,是保證資訊保安的有效措施。資料加密標準DES於 1977年1月向社會公佈,它是第一個世界公認的實用分組密碼演算法標準。但在經過20年的應用後,DES已被認為不可靠。3DES作為DES的替代,金鑰長度為168bits,可克服窮舉攻擊問題。同時,3DES的底層加密演算法對密碼分析攻擊有很強的免疫力。但由於用軟體實現該演算法的速度慢,使得3DES不能成為長期使用的加密演算法標準,需要一種新的高階加密標準來替代。
AES具有金鑰靈活性及較高的可實現性,具有較高的安全效能及實現效率,其金鑰建立時間極短,且靈敏性 良好。Rijndeal 演算法給出了最佳查分特徵概率,進行了演算法抵抗差分密碼分析以及線性密碼分析。無論Rijndeal使用反饋模式或無反饋模式,其硬體和軟體實現效能都表現優秀。此外,Rijndeal對記憶體的極低需求使其適合於在儲存器受限環境下使用,並能夠表現出極好的效能。
下面就寫一個簡單的demo來實現DES、3DES、AES的加密功能。在這個工程中需要引入特定的jar包。(http://download.csdn.net/detail/ldld1717/9667995)。
工程結構見圖1:
MainActivity.java
package com.example.leidong.encrypttest;
import android.graphics.Color;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.Window;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import com.example.leidong.encrypttest.utils.AESUtil;
import com.example.leidong.encrypttest.utils.DESUtil;
import com.example.leidong.encrypttest.utils.DESedeUtil;
import org.apache.commons.codec.binary.Base64;
/**
* Created by leidong on 2016/11/9.
*/
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
//標籤
private static final String TAG = "MainActivity";
//明文輸入框(可輸入、單行)
private EditText et_inputInfo;
//金鑰輸入框(不可輸入、單行)
private EditText et_secretKey;
//已加密資訊輸入框(不可輸入、單行)
private EditText et_encryptInfo;
//已解密資訊輸入框(不可輸入、單行)
private EditText et_decryptInfo;
//DES處理按鈕
private Button bt_des;
//3DES處理按鈕
private Button bt_3des;
//AES處理按鈕
private Button bt_aes;
//清空按鈕
private Button bt_clear;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//去除標題欄
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
//獲取並初始化元件
init();
}
/**
* 獲取並初始化元件
*/
private void init() {
et_inputInfo = (EditText)findViewById(R.id.et_inputInfo);
et_secretKey = (EditText)findViewById(R.id.et_secretKey);
et_encryptInfo = (EditText)findViewById(R.id.et_encryptInfo);
et_decryptInfo = (EditText)findViewById(R.id.et_decryptInfo);
//設定文字輸入框不可輸入
et_secretKey.setEnabled(false);
et_encryptInfo.setEnabled(false);
et_decryptInfo.setEnabled(false);
bt_des = (Button)findViewById(R.id.bt_des);
bt_3des = (Button)findViewById(R.id.bt_3des);
bt_aes = (Button)findViewById(R.id.bt_aes);
bt_clear = (Button)findViewById(R.id.bt_clear);
//設定按鈕監聽器
bt_des.setOnClickListener(MainActivity.this);
bt_3des.setOnClickListener(MainActivity.this);
bt_aes.setOnClickListener(MainActivity.this);
bt_clear.setOnClickListener(MainActivity.this);
//初始化按鈕的顏色,未點選為灰色,點選為綠色
initButtonsColor();
}
/**
* 對按鈕點選事件的監控
* @param view
*/
@Override
public void onClick(View view) {
switch(view.getId()){
/**
* 點選DES按鈕
*/
case R.id.bt_des:{
try {
initButtonsColor();
bt_des.setTextColor(Color.GREEN);
Toast.makeText(MainActivity.this, "DES", Toast.LENGTH_LONG).show();
String inputStr = et_inputInfo.getText().toString().trim();
byte[] inputData = inputStr.getBytes();
byte[] key = DESUtil.initKey();
et_secretKey.setText(new String(Base64.encodeBase64(key)));
inputData = DESUtil.encrypt(inputData, key);
et_encryptInfo.setText(new String(Base64.encodeBase64(inputData)));
byte[] outputData = DESUtil.decrypt(inputData, key);
et_decryptInfo.setText(new String(outputData));
}
catch (Exception e){
e.printStackTrace();
}
}
break;
/**
* 點選3DES按鈕
*/
case R.id.bt_3des:{
try {
initButtonsColor();
bt_3des.setTextColor(Color.GREEN);
Toast.makeText(MainActivity.this, "3DES", Toast.LENGTH_LONG).show();
String inputStr = et_inputInfo.getText().toString().trim();
byte[] inputData = inputStr.getBytes();
byte[] key = DESedeUtil.initKey();
et_secretKey.setText(new String(Base64.encodeBase64(key)));
inputData = DESedeUtil.encrypt(inputData, key);
et_encryptInfo.setText(new String(Base64.encodeBase64(inputData)));
byte[] outputData = DESedeUtil.decrypt(inputData, key);
et_decryptInfo.setText(new String(outputData));
}catch (Exception e){
e.printStackTrace();
}
}
break;
/**
* 點選AES按鈕
*/
case R.id.bt_aes:{
try {
initButtonsColor();
bt_aes.setTextColor(Color.GREEN);
Toast.makeText(MainActivity.this, "AES", Toast.LENGTH_LONG).show();
String inputStr = et_inputInfo.getText().toString().trim();
byte[] inputData = inputStr.getBytes();
byte[] key = AESUtil.initKey();
et_secretKey.setText(new String(Base64.encodeBase64(key)));
inputData = AESUtil.encrypt(inputData, key);
et_encryptInfo.setText(new String(Base64.encodeBase64(inputData)));
byte[] outputData = AESUtil.decrypt(inputData, key);
et_decryptInfo.setText(new String(outputData));
}
catch(Exception e){
e.printStackTrace();
}
}
break;
/**
* 點選清空內容按鈕
*/
case R.id.bt_clear:{
et_inputInfo.setText(null);
et_secretKey.setText(null);
et_encryptInfo.setText(null);
et_decryptInfo.setText(null);
Toast.makeText(MainActivity.this, "清空完成", Toast.LENGTH_LONG).show();
}
break;
/**
* 預設情況
*/
default:
break;
}
}
/**
* 初始化按鈕的顏色
*/
private void initButtonsColor(){
bt_des.setTextColor(Color.GRAY);
bt_3des.setTextColor(Color.GRAY);
bt_aes.setTextColor(Color.GRAY);
}
}
DESUtil.java(AESUtil.java和DESedeUtil.java略)
package com.example.leidong.encrypttest.utils;
import java.security.Key;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
/**
* Created by leidong on 2016/11/9.
* DES類
*/
public abstract class DESUtil {
/**
* 金鑰演算法
*/
private static final String KEY_ALGORITHM = "DES";
/**
* 加密/解密演算法 工作模式 填充模式
*/
private static final String CIPHER_ALGORITHM = "DES/ECB/PKCS5Padding";
/**
* 轉換金鑰
* @param key
* @return
* @throws Exception
*/
private static Key toKey(byte[] key) throws Exception{
//例項化金鑰
SecretKey secretKey = new SecretKeySpec(key, KEY_ALGORITHM);
return secretKey;
}
/**
* 加密
* @param data
* @param key
* @return
* @throws Exception
*/
public static byte[] encrypt(byte[] data, byte[] key) throws Exception{
//還原金鑰
Key k = toKey(key);
//例項化
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
//初始化
cipher.init(Cipher.ENCRYPT_MODE, k);
//執行操作
return cipher.doFinal(data);
}
/**
* 解密
* @param data
* @param key
* @return
* @throws Exception
*/
public static byte[] decrypt(byte[] data, byte[] key) throws Exception{
//還原金鑰
Key k = toKey(key);
//例項化
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
//初始化
cipher.init(Cipher.DECRYPT_MODE, k);
//執行操作
return cipher.doFinal(data);
}
/**
* 初始化金鑰
* @return
* @throws Exception
*/
public static byte[] initKey() throws Exception{
//例項化KeyGenerator
KeyGenerator keyGenerator = KeyGenerator.getInstance(KEY_ALGORITHM);
//初始化
keyGenerator.init(56);
//生成金鑰
SecretKey secretKey = keyGenerator.generateKey();
//返回金鑰
return secretKey.getEncoded();
}
}
執行結果:
DES的情況:
3DES的情況:
AES的情況:
完整的工程下載地址:
http://download.csdn.net/detail/ldld1717/9678097