1. 程式人生 > >Android加密演算法之對稱加密AES

Android加密演算法之對稱加密AES


        作為一名developer,一些重要檔案存取,網路資料傳輸安全不可忽視,促使我們使用加密演算法手段保證資訊資料的安全。加密並不意味著絕對的安全,總有破解的時候,為了提高破解難度,在演算法要求和品位上也越來越高,常見的有SHA-256、MD5等的Hash演算法,HMAC-SHA256等的資訊認證演算法,RSA(玩過支付寶支付的朋友應該知道其使用的公鑰私鑰就是該演算法)等的非對稱加密演算法,以及今天我要說的主角對稱加密演算法如AES,其他演算法這裡就不提了。

        因需求的不同,對於演算法的選擇也因需而異。這裡強調Base64演算法不叫加密,只是一種編碼方式,可以用來打亂一些不太敏感又不想讓人直接看到的內容,但請不要當加密演算法來用。

       對稱加密演算法,又稱祕鑰加密:用一個祕鑰來管理資訊的加密解密,其優點是演算法公開、計算量小、加密速度快、加密效率高。正如上述,其加密的安全性不在於技術是有多精湛,對祕鑰的保管才是最重要的安全性問題,一旦洩露就沒有安全可言了(將祕鑰投入到演算法中,分分鐘破解密文),可以說是該演算法最大的缺點。常用的對稱演算法有:DES、3DES、TDEA、Blowfish、RC2、RC4、RC5、IDEA、SKIPJACK、AES等。DES等演算法已不再安全,推薦使用AES演算法,而AES演算法中建議使用CBC模式,祕鑰長度則推薦使用256位,但是需要另行下載JCE(Java Cryptography Extension ,下文會有說明)。

        Android中AES加密沿用java裡的API,預設是ECB模式(該模式已不安全),需要顯示指定CBC模式,另外由於jdk版本的限制,使用PKCS5Padding填充方式即可,PKCS7Padding其實和PKCS5Padding差別不大,不必太糾結。簡單實現請看下面貼出的AESUtils.java程式碼:

package cn.icheny.security;

import android.util.Base64;
import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

/**
 * AES加密,解密工具
 * 
 * @author Cheny
 */

public class AESUtils {
	private static final String AES_CBC_PKCS5_PADDING = "AES/CBC/PKCS5Padding";
	private static final String AES = "AES";

	/**
	 * 生成祕鑰
	 * @return Base64編碼的祕鑰
	 */
	public static String generateSecretKey() {
		try {
			// 獲取Key生成器例項,一般一個例項可以多次用來生成祕鑰
			KeyGenerator keyGenerator = KeyGenerator.getInstance(AES);
			// 256位
			keyGenerator.init(256);
			// 生成金鑰
			SecretKey secretKey = keyGenerator.generateKey();
			// 獲取金鑰
			byte[] keyBytes = secretKey.getEncoded();
			return Base64.encodeToString(keyBytes, Base64.DEFAULT);// 生成的祕鑰轉換成Base64編碼,加、解密時需要用Base64還原祕鑰
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 加密
	 * @param plaintext 明文
	 * @param key 祕鑰
	 * @return Base64編碼的密文
	 */
	public static String encrypt(String plaintext, String key) {
		try {
			// Base64還原祕鑰
			byte[] keyBytes = Base64.decode(key.getBytes(), Base64.DEFAULT);
			// 還原金鑰物件
			SecretKey secretKey = new SecretKeySpec(keyBytes, AES);
			// 加密初始化例項
			Cipher cipher = Cipher.getInstance(AES_CBC_PKCS5_PADDING);
			// CBC模式需要新增一個引數IvParameterSpec,ECB模式則不需要
			cipher.init(Cipher.ENCRYPT_MODE, secretKey, new IvParameterSpec(new byte[cipher.getBlockSize()]));
			byte[] result = cipher.doFinal(plaintext.getBytes("UTF-8"));
			return Base64.encodeToString(result, Base64.DEFAULT);// 生成的密文轉換成Base64編碼出文本,解密時需要用Base64還原出密文
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (NoSuchPaddingException e) {
			e.printStackTrace();
		} catch (IllegalBlockSizeException e) {
			e.printStackTrace();
		} catch (BadPaddingException e) {
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (InvalidAlgorithmParameterException e) {
			e.printStackTrace();
		} catch (InvalidKeyException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 解密
	 * @param ciphertext 密文
	 * @param key  祕鑰
	 * @return 明文
	 */
	public static String decrypt(String ciphertext, String key) {

		try {
			byte[] keyBytes = Base64.decode(key.getBytes(), Base64.DEFAULT);// Base64還原祕鑰
			// 還原金鑰物件
			SecretKey secretKey = new SecretKeySpec(keyBytes, AES);
			// 加密初始化例項
			Cipher cipher = Cipher.getInstance(AES_CBC_PKCS5_PADDING);
			cipher.init(Cipher.DECRYPT_MODE, secretKey, new IvParameterSpec(new byte[cipher.getBlockSize()]));
			// Base64還原密文
			byte[] cipherBytes = Base64.decode(ciphertext, Base64.DEFAULT);
			byte[] result = cipher.doFinal(cipherBytes);
			return new String(result, "UTF-8");
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (NoSuchPaddingException e) {
			e.printStackTrace();
		} catch (InvalidKeyException e) {
			e.printStackTrace();
		} catch (IllegalBlockSizeException e) {
			e.printStackTrace();
		} catch (BadPaddingException e) {
			e.printStackTrace();
		} catch (InvalidAlgorithmParameterException e) {
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return null;
	}
}

         程式碼中有註釋,在加密中使用了android裡Base64工具類,對祕鑰,密文進行Base64轉碼修飾了一番,java中沒有該工具類,若需Base64轉碼需自行程式碼實現,當然也可以轉為16進位制字串,這裡不再贅述。

         由於因為美國對軟體出口的限制,我們日常開發使用的jdk(主要是說jre)版本加密能力受到限制,上述工具類實際執行時會丟擲:java.security.InvalidKeyException: Illegal key size 異常,當祕鑰長度超過128位時會報出此異常,128位及以下可以正常執行。好了,文章就嘮到這裡,下次再見,白白!

       一本正經說了那麼多,突然放了一個大坑,說好的JCE說明呢?坑不解決了?怎麼可以這麼坑?OK,繼續一本正經說下去:

        下面引用某度來的說明:

        Java幾乎各種常用加密演算法都能找到對應的實現。
        因為美國的出口限制,Sun通過許可權檔案(local_policy.jar、US_export_policy.jar)做了相應限制。
        因此存在一些問題:
        金鑰長度上不能滿足需求(如:java.security.InvalidKeyException: Illegal key size or default parameters);
        部分演算法未能支援,如MD4、SHA-224等演算法;

        API使用起來還不是很方便;一些常用的進位制轉換輔助工具未能提供,如Base64編碼轉換、十六進位制編碼轉換等工具。    Oracle在其官方網站上提供了無政策限制許可權檔案        (Unlimited Strength Jurisdiction Policy Files),我們只需要將其部署在JRE環境中,就可以解決限制問題。

       對於java便是Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files.

       這裡提供當前幾個主流jdk版本對應的JCE檔案下載:

      JDK6的下載地址:http://www.oracle.com/technetwork/java/javase/downloads/jce-6-download-429243.html

      JDK7的下載地址:http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html

      JDK8的下載地址:http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html

      下面繼續引用某度來的說明:

       下載的壓縮包中僅有一個目錄,也就是jce目錄。該目錄中包含了4個檔案:README.txt、COPYRIGHT.html、local_policy.jar和US_export_policy.jar。其中包含的兩個jar檔案正是此次配置中用到的檔案。
      我們可以檢視上述README.txt檔案,你需要在JDK的JRE環境中,或者是JRE環境中配置上述兩個jar檔案。
      切換到%JDK_Home%\jre\lib\security目錄下,對應覆蓋local_policy.jar和US_export_policy.jar兩個檔案。同時,你可能有必要在%JRE_Home%\lib\security目錄下,也需要對應覆蓋這兩個檔案。
      配置許可權檔案的最終目的是為了使應用在執行環境中獲得相應的許可權,可以加強應用的安全性。通常,我們在應用伺服器上安裝的是JRE,而不是JDK。因此,這就很有必要在應用伺服器的%JRE_Home%\lib\security目錄下,對應覆蓋這兩個許可權檔案。很多開發人員往往忽略了這一點,導致事故發生。

      OK,由於引用的說明寫得很詳細很徹底,我就不跟著扯了,文章到此就告一段落了,以後會繼續更新其他演算法,敬請關注!

相關推薦

Android加密演算法對稱加密AES

        作為一名developer,一些重要檔案存取,網路資料傳輸安全不可忽視,促使我們使用加密演算法手段保證資訊資料的安全。加密並不意味著絕對的安全,總有破解的時候,為了提高破解難度,在演算法要求和品位上也越來越高,常見的有SHA-256、MD5等的Hash

JAVA 常用的加密演算法對稱加密DES、3DES和AES

1、對稱加密演算法 1.1 定義 對稱加密演算法是應用較早的加密演算法,技術成熟。在對稱加密演算法中,資料發信方將明文(原始資料)和加密金鑰一起經過特殊加密演算法處理後,使其變成複雜的加密密文傳送出去。收信方收到密文後,若想解讀原文,則需要使用加密用過的金鑰

最全加密演算法對稱加密和非對稱加密

常見加密演算法 : DES(Data Encryption Standard):資料加密標準,速度較快,適用於加密大量資料的場合;  3DES(Triple DES):是基於DES,對一塊資料用三個不同的金鑰進行三次加密,強度更高; RC2和 RC4:用變長金鑰對大量資

go加密演算法:CBC對稱加密(一)--3DES/AES

其實對稱加密中的:DES\3DES\AES 採取的加解密步驟一致,只是小的細節不太一樣.大家多看看就能寫出來了 // rsao1.go package main import ( "bytes" "crypto/aes" "crypto/cipher" "c

Java 加密解密 對稱加密演算法對稱加密演算法 MD5 BASE64 AES RSA

【前言】 本文簡單的介紹了加密技術相關概念,最後總結了java中現有的加密技術以及使用方法和例子 【最簡單的加密】1.簡單的概念 明文:加密前的資訊 密文:機密後的資訊 演算法:加密或解密的演算法 金鑰:演算法使用的鑰匙(讀作miyao,正確應該是miyue,但是大家都讀m

Java加密解密對稱加密

採用單鑰密碼系統的加密方法,同一個金鑰可以同時用作資訊的加密和解密,這種加密方法稱為對稱加密,也稱為單金鑰加密。 其核心思想是,加密和解密都是同一個祕鑰 對稱加密常用的演算法有:DES、3DES、TDEA、Blowfish、RC2、RC4、RC5、IDEA、SKIPJAC

go加密演算法:非對稱加密(三)--Elliptic

看了2星期的區塊鏈原理與執行機制,加密這裡開始變得有些生疏,花了一天時間複習了一些;看到了之前忽略的,也學會了橢圓曲線加密。 package main //https://studygolang.com/articles/13228 //https://blog.csdn.net/teas

java加密演算法對稱加密演算法——數字信封 DH

類似數字簽名,數字信封是這樣描述的:  數字信封          數字信封用加密技術來保證只有特定的收信人才能閱讀信的內容。  流程:      資訊傳送方採用對稱金鑰來加密資訊,然後再用接收方的公鑰來加密此對稱金鑰(這部分稱為數字信封),再將它和資訊一

Java進階 八 Java加密技術對稱加密對稱加密 不可逆加密算法

歐洲 再次 div 數據安全 識別 交易 standard 計算 領域 對稱加密 非對稱加密 不可逆加密算法 根據密鑰類型不同可以將現代密碼技術分為兩類:對稱加密算法(私鑰密碼體系)和非對稱加密算法(公鑰密碼體系)。 1 對稱加密算法 原理 對稱加密算法中,數據

資料傳輸加密——非對稱加密演算法RSA+對稱演算法AES(適用於java,android和Web)

本篇文章已授權微信公眾號 guolin_blog (郭霖)獨家釋出 資料傳輸加密   在開發應用過程中,客戶端與服務端經常需要進行資料傳輸,涉及到重要隱私資訊時,開發者自然會想到對其進行加密,即使傳輸過程中被“有心人”擷取,也不會將資訊洩露。對於加密

java、android、ios、js資料傳遞加密演算法AES加密

場景描述 我們在做專案的時候,寫介面經常會遇到這樣的情況,就是和app端、web端互動的時候傳輸資料需要進行加密,不能用明文操作。資料傳輸加密最關鍵的就是前後端傳輸的資料最終能被正確的解密出來,今天就來講講使用AES加密傳輸的時候前後端使用的程式碼。 解

程式設計師網路安全系列(三):資料加密對稱加密演算法

系列目錄: 前文回顧 假如,明明和麗麗相互不認識,明明想給麗麗寫一封情書,讓隔壁老王送去 如何保證隔壁老王不能看到情書內容?(保密性) 如何保證隔壁老王不修改情書的內容?(完整性) 如何保證隔壁老王不冒充明明?(身份認證) 如何保證明明不能否認情書是自己寫的?(來源的不可否認) 上一節,我們使用了Ha

對稱加密演算法DH

一.概述   (1)非對稱加密演算法DH的加解密效率比較低,對要加密的資料長度有著苛刻的要求,這也就是效率換安全吧。   (2)雖然對稱加密效率高,但金鑰的傳輸需要另外的通道(方式),非對稱加密通過構建本地金鑰來解決金鑰的傳輸問題。 二.加解密過程簡析   1.傳送方A構建

java對稱加密演算法

對稱加密演算法是以一種使用頻率高的初等的加密演算法,如你所想,之所以稱之為對稱加密演算法,說明加密祕鑰是相同,加密過程可逆,而前面介紹的base64加密,和訊息摘要加密演算法是不可逆的.一般的對稱加密演算法有DES,DES祕鑰長度不夠,易被破解,進而衍生出了3D

.NET Core加解密實戰系列——對稱加密演算法

## 簡介 加解密現狀,編寫此係列文章的背景: - 需要考慮系統環境相容性問題(Linux、Windows) - 語言互通問題(如C#、Java等)(加解密本質上沒有語言之分,所以原則上不存在互通性問題) - 網上資料版本不一、或不全面 - .NET官方庫密碼演算法提供不全面,很難針對其他語言(Java)進

php openssl_sign() 語法+RSA公私鑰加密解密,非對稱加密演算法詳解

其實有時候覺得寫部落格好煩,就個函式就開篇部落格。很小的意見事情而已,知道的人看來多取一舉,或者說沒什麼必要,浪費時間,不知道的人就會很鬱悶。技術就是這樣的,懂的人覺得真的很簡單啊,不知道的人真的好難。。。 一般在跟第三方介面對接資料的時候,為了保證很多都使用的RSA簽名,沒性趣瞭解的同學只需要

JAVA密碼加密演算法.RSA演算法(非對稱加密演算法)和密碼加鹽MD5

密碼加鹽MD5 Message Digest Algorithm MD5(中文名為訊息摘要演算法第五版)為電腦保安領域廣泛使用的一種雜湊函式,用以提供訊息的完整性保護。 是計算機廣泛使用的雜湊演算法之一(又譯摘要演算法、雜湊演算法),主流程式語言普遍已有MD5實現。將資料(如漢字)運

AES對稱加密+RSA非對稱加密實現

</pre>AesEncrypt.h<pre name="code" class="cpp">//enum KeySize { Bits128, Bits192, Bits256 }; // key size, in bits, for construtor #define

常見的加密演算法DSA 演算法

DSA(Digital Signature Algorithm)是Schnorr和ElGamal簽名演算法的變種,被美國NIST作為DSS(DigitalSignature Standard)。 DSA是基於整數有限域離散對數難題的。DSA是一種更高階的驗證方式。一般用於數字

加密演算法C#相容PHP中MD5加密

C#常用的MD5加密演算法: public static string MD5(string password) { byte[] textBytes = System.Text.Encoding.Default.GetBytes(password); try