隨着對稱密碼的發展,DES數據加密標准算法由於密鑰長度較小(56位),已經不適應當今分布式開放網絡對數據加密安全性的要求,因此1997年NIST公開征集新的數據加密標准,即AES[1]。經過三輪的篩選,比利時Joan Daeman和Vincent Rijmen提交的Rijndael算法被提議為AES的最終算法。此算法將成為美國新的數據加密標准而被廣泛應用在各個領域中。盡管人們對AES還有不同的看法,但總體來說,AES作為新一代的數據加密標准匯聚了強安全性、高性能、高效率、易用和靈活等優點。AES設計有三個密鑰長度:128,192,256位,相對而言,AES的128密鑰比DES的56密鑰強1021倍[2]。AES算法主要包括三個方面:輪變化、圈數和密鑰擴展。本文以128為例,介紹算法的基本原理;結合AVR匯編語言,實現高級數據加密算法AES。
AES是分組密鑰,算法輸入128位數據,密鑰長度也是128位。用Nr表示對一個數據分組加密的輪數(加密輪數與密鑰長度的關系如表1所列)。每一輪都需要一個與輸入分組具有相同長度的擴展密鑰Expandedkey(i)的參與。由於外部輸入的加密密鑰K長度有限,所以在算法中要用一個密鑰擴展程序(Keyexpansion)把外部密鑰K擴展成更長的比特串,以生成各輪的加密和解密密鑰。
AES加密算法原理
.................................................................................................................................
加密前需要的參數encoding聲明為以哪種字符方式加密,AES對稱加密,KEY為密鑰
private final static String encoding = "UTF-8"; private final static String AES = "AES"; private final static String KEY = "xxxxsfddsfdsfsdfds"; /** * AES加密 * **/ public static String encryptAES(String content) { byte[] encryptResult = encrypt(content); String encryptResultStr = parseByte2HexStr(encryptResult); // BASE64位加密 encryptResultStr = ebotongEncrypto(encryptResultStr); return encryptResultStr; } /** * AES解密 * @param encryptResultStr * @return String * **/ public static String decryptAES(String encryptResultStr) { // BASE64位解密 String decrpt = ebotongDecrypto(encryptResultStr); byte[] decryptFrom = parseHexStr2Byte(decrpt); byte[] decryptResult = decrypt(decryptFrom); return new String(decryptResult); } /** * 加密字符串 * */ public static String ebotongEncrypto(String str) { BASE64Encoder base64encoder = new BASE64Encoder(); String result = str; if (str != null && str.length() > 0) { try { byte[] encodeByte = str.getBytes(encoding); result = base64encoder.encode(encodeByte); }catch (UnsupportedEncodingException e) { e.printStackTrace(); } } //base64加密超過一定長度會自動換行 需要去除換行符 return result.replaceAll("\r\n", "").replaceAll("\r", "").replaceAll("\n", ""); } /** * 解密字符串 * */ public static String ebotongDecrypto(String str) { BASE64Decoder base64decoder = new BASE64Decoder(); try { byte[] encodeByte = base64decoder.decodeBuffer(str); return new String(encodeByte); } catch (IOException e) { e.printStackTrace(); return str; } } /** * 加密 * * @param content 需要加密的內容 * @param password 加密密碼 * @return */ public static byte[] encrypt(String content) { try { KeyGenerator kgen = KeyGenerator.getInstance(AES); SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG"); secureRandom.setSeed(KEY.getBytes()); kgen.init(128, secureRandom); SecretKey secretKey = kgen.generateKey(); byte[] enCodeFormat = secretKey.getEncoded(); SecretKeySpec key = new SecretKeySpec(enCodeFormat, AES); Cipher cipher = Cipher.getInstance(AES);// 創建密碼器 byte[] byteContent = content.getBytes(); 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 (IllegalBlockSizeException e) { e.printStackTrace(); } catch (BadPaddingException e) { e.printStackTrace(); } return null; } /**解密 * @param content 待解密內容 * @param password 解密密鑰 * @return */ public static byte[] decrypt(byte[] content) { try { KeyGenerator kgen = KeyGenerator.getInstance(AES); //kgen.init(128, new SecureRandom(AESUtilsPassWordKey.PASSWORD_KEY.getBytes())); SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG"); secureRandom.setSeed(KEY.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; } /**將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; } /** * 將二進制轉換成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(); } public static void main(String[] args) { String content = "中文測試"; String encryptResultStr = encryptAES(content); System.out.println("加密前: "+content); System.out.println("加密后: "+encryptResultStr); System.out.println("解密后: "+decryptAES(encryptResultStr)); }