Java AES 密碼編譯演算法__編碼

來源:互聯網
上載者:User

轉載地址:JAVA版AES密碼編譯演算法

  密碼學中的進階加密標準(Advanced Encryption Standard,AES),又稱Rijndael加密法,是美國聯邦政府採用的一種區塊加密標準。這個標準用來替代原先的DES,已經被多方分析且廣為全世界所使用。經過五年的甄選流程,進階加密標準由美國國家標準與技術研究院 (NIST)於2001年11月26日發佈於FIPS PUB 197,並在2002年5月26日成為有效標準。2006年,進階加密標準已然成為對稱金鑰密碼編譯中最流行的演算法之一。
  
  該演算法為比利時密碼學家Joan Daemen和Vincent Rijmen所設計,結合兩位作者的名字,以Rijndael之命名之,投稿進階加密標準的甄選流程。(Rijdael的發音近於 “Rhinedoll”)

  AES 是一個新的可以用於保護電子資料的密碼編譯演算法。明確地說,AES 是一個迭代的、對稱金鑰分組的密碼,它可以使用128、192 和 256 位密鑰,並且用 128 位(16位元組)區塊編碼器和解密資料。與公用密鑰密碼使用金鑰組不同,對稱金鑰密碼使用相同的祕密金鑰加密和解密資料。通過分組密碼返回的加密資料的位元與輸入資料相同。迭代加密使用一個迴圈結構,在該迴圈中重複置換(permutations )和替換(substitutions)輸入資料。Figure 1 顯示了 AES 用192位金鑰組一個16位位元組資料區塊進行加密和解密的情形。

  對稱密碼體制的發展趨勢將以分組密碼為重點。分組密碼演算法通常由密鑰擴充演算法和加密(解密)演算法兩部分組成。密鑰擴充演算法將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.
  
  AES加密資料塊大小最大是256bit,但是密鑰大小在理論上沒有上限。AES加密有很多輪的重複和變換。大致步驟如下:
   
1. 密鑰擴充(KeyExpansion)
2. 初始輪(Initial Round)
3. 重複輪(Rounds),每一輪又包括:SubBytes、ShiftRows、MixColumns、AddRoundKey
4. 最終輪(Final Round),最終輪沒有MixColumns。

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.SecretKeySpec;import java.io.UnsupportedEncodingException;import java.security.InvalidKeyException;import java.security.NoSuchAlgorithmException;import java.security.SecureRandom;public abstract class AesHelper {    /**     * 加密     *     * @param content 需要加密的內容     * @param salt    加密密碼     * @return     */    public static byte[] encrypt(String content, String salt) {        try {            SecureRandom random = SecureRandom.getInstance("SHA1PRNG");            random.setSeed(salt.getBytes());            KeyGenerator kgen = KeyGenerator.getInstance("AES");            kgen.init(128, random);            SecretKey secretKey = kgen.generateKey();            byte[] enCodeFormat = secretKey.getEncoded();            SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");            Cipher cipher = Cipher.getInstance("AES");// 建立密碼器            byte[] byteContent = content.getBytes("utf-8");            cipher.init(Cipher.ENCRYPT_MODE, key);// 初始化            byte[] result = cipher.doFinal(byteContent);            return result; // 加密        } catch (NoSuchAlgorithmException e) {            e.printStackTrace();        } catch (NoSuchPaddingException e) {            e.printStackTrace();        } catch (InvalidKeyException e) {            e.printStackTrace();        } catch (UnsupportedEncodingException e) {            e.printStackTrace();        } catch (IllegalBlockSizeException e) {            e.printStackTrace();        } catch (BadPaddingException e) {            e.printStackTrace();        }        return null;    }    /**     * 解密     *     * @param content 待解密內容     * @param salt    解密密鑰     * @return     */    public static byte[] decrypt(byte[] content, String salt) {        try {            KeyGenerator kgen = KeyGenerator.getInstance("AES");            SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");            secureRandom.setSeed(salt.getBytes());            kgen.init(128, secureRandom);            SecretKey secretKey = kgen.generateKey();            byte[] enCodeFormat = secretKey.getEncoded();            SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");            Cipher cipher = Cipher.getInstance("AES");// 建立密碼器            cipher.init(Cipher.DECRYPT_MODE, key);// 初始化            byte[] result = cipher.doFinal(content);            return result; // 加密        } 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();        }        return null;    }    public static String bytesToHexString(byte[] src) {        StringBuffer sb = new StringBuffer();        for (int i = 0; i < src.length; i++) {            String hex = Integer.toHexString(src[i] & 0xFF);            if (hex.length() == 1) {                hex = '0' + hex;            }            sb.append(hex.toUpperCase());        }        return sb.toString();    }    public static String encryptToStr(String content, String password){        return bytesToHexString(encrypt(content,password));    }    public static byte[] decrypt(String content, String keyWord) {        return decrypt(hexStringToBytes(content), keyWord);    }    public static byte[] hexStringToBytes(String hexString) {        if (hexString.length() < 1)            return null;        byte[] result = new byte[hexString.length() / 2];        for (int i = 0; i < hexString.length() / 2; i++) {            int high = Integer.parseInt(hexString.substring(i * 2, i * 2 + 1), 16);            int low = Integer.parseInt(hexString.substring(i * 2 + 1, i * 2 + 2), 16);            result[i] = (byte) (high * 16 + low);        }        return result;    }}

以下是TestCase:

public class AesTest {    @Test    public void testAes(){        String content = "carl.zhao";        String Key = "http://www.csdn.net";        //加密        String encryptResult = AesHelper.encryptToStr(content, Key);        //解密        byte[] decryptResult = AesHelper.decrypt(encryptResult,Key);        Assert.assertEquals(content, new String(decryptResult));    }}

以上代碼是正確的,我之前再使用其它代碼的時候遇到了下面的問題:在Windows上運行沒有問題,但是在Linux上運行時提示如下錯誤:

javax.crypto.BadPaddingException: Given final block not properly padded

這個是因為 : SecureRandom實現完全隨作業系統本身的內部狀態。該實現在 windows 上每次產生的 key 都相同。但是在 solaris 或部分 linux 系統上則不同。大家可以通過日誌列印來確認一這點。

我之前的代碼如下:

secureRandom = new SecureRandom(seed.getBytes());

修改後的正確代碼如下:

 SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG"); secureRandom.setSeed(seed.getBytes());

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.