使用Java和JCEKS进行AES-256加密
總覽
由于最近愛德華·斯諾登 ( Edward Snowden)發布了文件以及針對JC Penny , Sony和Target等在線商業商店的黑客入侵,安全性已成為近年來討論的重要話題。 雖然本文不會為您提供幫助防止使用非法來源數據的所有工具,但本文將為構建一套工具和策略提供起點,以幫助防止其他方使用數據。
這篇文章將展示如何在Java環境中對字符串采用AES加密。 它將討論如何創建AES密鑰以及以JCEKS密鑰庫格式存儲AES密鑰。 此博客中的代碼的工作示例位于https://github.com/mike-ensor/aes-256-encryption-utility
建議按順序閱讀每個部分,因為每個部分都是上一個部分的基礎,但是,您可能希望快速跳轉到特定部分。
- 設置 –使用keytool設置和創建密鑰
- 加密 –使用byte []密鑰加密消息
- 解密 –使用相同的IV和加密密鑰解密郵件
- 從密鑰庫獲取密鑰 –通過別名從密鑰庫獲取密鑰
什么是JCEKS?
JCEKS代表的J ava?ryptography?xtension?EY 小號扯了下來,這是針對Java平臺的替代密鑰庫格式。 將密鑰存儲在KeyStore中可以作為一種措施,以防止暴露您的加密密鑰。 Java密鑰庫安全地包含可以由別名引用以在Java程序中使用的各個證書和密鑰。 Java KeyStore通常是使用Java JDK隨附的“ keytool ”創建的。
注意:強烈建議為KeyStore創建復雜的密碼,以確保內容安全。 KeyStore是一個被認為是公共文件,但是建議不要輕易訪問該文件。
設定
所有加密均受每個國家/地區的法律管轄,并且通常對加密強度有限制。 一個例子是在美國,如果數據在邊界外傳輸,則所有128位以上的加密都受到限制。 默認情況下,Java JCE實施強度策略以遵守這些規則。 如果首選更強的加密并遵守國家/地區的法律,則JCE需要訪問更強的加密策略。 簡而言之,如果您打算使用AES 256位加密,則必須安裝Unlimited Strength Jurisdiction Policy Files 。 如果沒有適當的策略,則無法進行256位加密。
安裝JCE無限強度政策
這篇文章的重點是按鍵,而不是JCE的安裝和設置。 安裝非常簡單, 可以在此處找到明確的說明(注意:這是針對JDK7的,如果使用其他JDK,則搜索適當的JCE策略文件)。
密鑰庫設置
使用KeyTool時,操作密鑰庫很簡單。 必須使用指向新密鑰的鏈接或在導入現有密鑰庫的過程中創建密鑰庫。 為了創建一個新的密鑰和密鑰庫,只需鍵入:
keytool -genseckey -keystore aes-keystore.jck -storetype jceks -storepass mystorepass -keyalg AES -keysize 256 -alias jceksaes -keypass mykeypass重要標志
在上面的示例中,這里是有關keytool參數的說明:
密鑰庫參數
genseckey :生成SecretKey。 這是表示創建同步密鑰的標志,它將成為我們的AES密鑰 keystore : 密鑰庫的位置。 如果密鑰庫不存在,該工具將創建一個新的存儲器。 路徑可以是相對的或絕對的,但必須是局部的 storetype :這是商店的類型(JCE,PK12,JCEKS等)。 JCEKS用于存儲證書中不包含的對稱密鑰(AES)。 storepass :與密鑰庫相關的密碼。 強烈建議為密鑰庫創建一個強大的密碼短語關鍵參數
keyalg :用于創建密鑰的算法(AES / DES / etc) keysize : 密鑰的大小(128、192、256等) alias :給新創建的密鑰的別名,使用該密鑰時要在其中引用 keypass :保護密鑰使用的密碼加密
由于它涉及Java中的數據,并且在最基本的級別上,加密是一種算法過程,該過程用于通過可逆過程以編程方式混淆數據,雙方都擁有與該數據有關的信息以及該算法的使用方式。 在Java加密中,這涉及使用密碼。 JCE中的Cipher對象是通常由算法選擇的加密提供程序的通用入口點。 此示例使用默認的Java提供程序,但也可以與Bouncy Castle一起使用。
生成密碼對象
獲得Cipher的實例非常容易,并且加密和解密都需要相同的過程。 (注意:加密和解密需要相同的算法,但不需要相同的對象實例)
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");一旦有了密碼實例,就可以根據算法對數據進行加密和解密。 通常,該算法將需要其他信息,以便對數據進行加密/解密。 在此示例中,我們將需要向算法傳遞包含密鑰和初始向量的字節(如下所述)。
初始化
為了使用密碼,我們必須首先初始化密碼。 此步驟是必需的,因此我們可以為算法提供其他信息,例如AES密鑰和Initial Vector(又名IV)。
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpecification, initialVector);參量
SecretKeySpecification是一個對象,其中包含對構成AES密鑰的字節的引用。 AES密鑰無非是由密鑰工具生成的(見上文)的特定大小的字節陣列(256位的AES 256或32個字節)。
替代參數
有多種創建密鑰的方法,例如包含鹽,用戶名和密碼(或類似名稱)的哈希。 此方法將利用連接字符串的SHA1哈希,轉換為字節,然后將結果截斷為所需大小。 這篇文章不會顯示使用此方法生成密鑰或使用使用密碼和密碼的PBE密鑰方法。 對于鍵輸入密碼和/或鹽的使用是通過創建新的密鑰的過程中使用的輸入密鑰工具處理。
初始化向量
AES算法還需要第二個參數,即I信息化V扇區。 該過程中使用IV來使加密的消息隨機化,并防止密鑰容易猜測。 IV被認為是公開共享的信息,但同樣,不建議公開共享該信息(例如,將其發布在您公司的網站上是不明智的)。 在加密消息時,通常會在消息前加上IV,因為基于算法,??IV的大小將為設定值/已知大小。 注意:如果使用相同的IV,密鑰和消息,則AES算法將輸出相同的結果。 建議每次加密時隨機創建IV。
使用新初始化的密碼,加密消息很簡單。 只需致電:
byte[] encryptedMessageInBytes = Cipher.doFinal((message.getBytes("UTF-8")); String base64EncodedEncryptedMsg = BaseEncoding.base64().encode(encryptedMessageInBytes); String base32EncodedEncryptedMsg = BaseEncoding.base32().encode(encryptedMessageInBytes);編碼結果
字節數組很難可視化,因為它們通常不會在任何字符集中形成字符。 解決此問題的最佳建議是用HEX(base-16) , Double HEX(base-32)或Base64格式表示字節。 如果將通過URL或POST參數傳遞消息,請確保使用網絡安全的Base64編碼。 Google Guava庫提供了出色的BaseEncoding實用程序 。 注意:請記住在解密之前對編碼的消息進行解碼。
解密
解密消息幾乎與加密過程相反,只有少數例外。 與生成隨機IV的加密過程不同,解密需要一個已知的初始化向量作為參數。
解密
解密時,請使用與加密方法相同的過程獲得一個密碼對象。 密碼對象將需要利用完全相同的算法,包括方法和填充選擇。 一旦代碼獲得對Cipher對象的引用,下一步就是初始化用于解密的密碼,并將對密鑰和初始化向量的引用傳遞給它。
// key is the same byte[] key used in encryption SecretKeySpec secretKeySpecification = new SecretKeySpec(key, "AES"); cipher.init(Cipher.DECRYPT_MODE, secretKeySpecification, initialVector);注意: 密鑰存儲在密鑰庫中,并通過使用別名獲得 。 有關從密鑰庫獲取密鑰的詳細信息,請參見下文
一旦提供了密鑰IV并為解密初始化了密碼,密碼就可以執行解密了。
byte[] encryptedTextBytes = BaseEncoding.base64().decode(message); byte[] decryptedTextBytes = cipher.doFinal(encryptedTextBytes); String origMessage = new String(decryptedTextBytes);保持靜脈輸液的策略
用于加密消息的IV對于解密消息很重要,因此提出了一個問題,即它們如何保持在一起。 一種解決方案是對IV進行基本編碼(請參見上文),并將其添加到加密和編碼的消息之前:Base64UrlSafe(myIv)+分隔符+ Base64UrlSafe(encryptedMessage)。 其他可能的解決方案可能是上下文相關的,例如,在具有IV的XML文件中包括一個屬性,并為所使用的密鑰提供別名。
從密鑰庫獲取密鑰
這篇文章的開頭顯示了創建引用密鑰庫數據庫內部別名的新AES-256密鑰有多么容易。 然后,該帖子繼續介紹如何在給定密鑰的情況下加密和解密消息,但是還顯示了如何在密鑰庫中獲取對該密鑰的引用。
解
// for clarity, ignoring exceptions and failures InputStream keystoreStream = new FileInputStream(keystoreLocation);KeyStore keystore = KeyStore.getInstance("JCEKS"); keystore.load(keystoreStream, keystorePass.toCharArray());if (!keystore.containsAlias(alias)) {throw new RuntimeException("Alias for key not found"); }Key key = keystore.getKey(alias, keyPass.toCharArray());參量
keystoreLocation :字符串–本地密鑰庫文件位置的位置 keypass :字符串–使用keytool創建或修改密鑰庫文件時使用的密碼(請參見上文) alias :String –使用keytool創建新密鑰時使用的別名(請參見上文)結論
這篇文章展示了如何使用AES-256加密算法對基于字符串的消息進行加密和解密。 加密和解密這些消息的密鑰保存在使用JDK提供的“ keytool”實用程序創建的JCEKS格式的KeyStore數據庫中。 這篇文章中的示例應被視為加密/解密對稱密鑰(例如AES)的堅實起點。 在加密消息(例如密鑰旋轉)時,這不應被視為唯一的防線。 密鑰輪換是一種減輕數據泄露風險的方法。 如果入侵者獲取數據并設法破解單個密鑰,則多個文件中包含的數據應已使用多個密鑰對數據進行加密,從而降低了總暴露損失的風險。
該博客文章中的所有示例都被濃縮為一個簡單的工具,允許查看密鑰庫中的密鑰,JDK密鑰工具不支持開箱即用的操作。 這篇文章中概述的步驟和主題的各個方面都可以從以下網址獲得: https : //github.com/mike-ensor/aes-256-encryption-utility 。 注意:示例,示例代碼和任何參考資料均由實施者自擔風險,沒有任何默示的保證或責任,您承擔所有風險。
翻譯自: https://www.javacodegeeks.com/2014/02/aes-256-encryption-with-java-and-jceks.html
總結
以上是生活随笔為你收集整理的使用Java和JCEKS进行AES-256加密的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 诺基亚1010手机(诺基亚1010手机参
- 下一篇: 开源JVM Sampling Profi