Javascript中的AES加密和Java中的解密
AES代表高級加密系統,它是一種對稱加密算法,很多時候我們需要在客戶端加密一些純文本(例如密碼)并將其發送到服務器,然后由服務器解密以進行進一步處理.AES加密和解密更加容易在相同的平臺(例如Android客戶端和Java服務器)中實現,但有時在跨平臺環境(例如Java客戶端和Java Server)(例如在Spring MVC框架中)中解密AES加密密碼變得頗具挑戰性,因為如果任何系統默認值都不匹配,那么解密將失敗。
在本文中,我們將使用spring mvc和angular js客戶端創建一個應用程序。 我們將有一個登錄頁面,其中包含用戶名和密碼的表單輸入。 在將密碼發送到服務器之前,將使用CryptoJS在javascript中對密碼進行加密,并且將在java中解密相同的加密密碼,并進行比較以匹配密碼。我們將在javascript中生成salt和IV,然后生成使用PBKDF2函數從密碼,鹽和密鑰大小中獲取密鑰,之后我們將使用key和IV對明文進行加密,并使用Java對其進行解密,因此基本上我們將開發一種與Java和Java互操作的AES加密機制。 Javascript。
在繼續進行之前,讓我們澄清一件事,即該機制僅在數據的有線傳輸過程中(最有可能)增加了一種額外的安全性,但沒有提供完全的證明安全性。 如果您不使用SSL,則攻擊者可以執行中間人攻擊,并通過為用戶提供其他密鑰來竊取數據。
項目結構
我們有一個彈簧靴和角度Js Web應用程序設置。以下是結構。
JavaScript中的Aes加密
對于javascript中的AES加密,我們導入了兩個js文件crypto.js和pbkdf2.js 。我們擁有AesUtil.js ,它們具有執行加密和解密的通用代碼。 這里的keySize是密鑰的大小,以4字節為單位。因此,要使用128位密鑰,我們將位數除以32得到了用于CryptoJS的密鑰大小。
AesUtil.js
var AesUtil = function(keySize, iterationCount) {this.keySize = keySize / 32;this.iterationCount = iterationCount; };AesUtil.prototype.generateKey = function(salt, passPhrase) {var key = CryptoJS.PBKDF2(passPhrase, CryptoJS.enc.Hex.parse(salt),{ keySize: this.keySize, iterations: this.iterationCount });return key; }AesUtil.prototype.encrypt = function(salt, iv, passPhrase, plainText) {var key = this.generateKey(salt, passPhrase);var encrypted = CryptoJS.AES.encrypt(plainText,key,{ iv: CryptoJS.enc.Hex.parse(iv) });return encrypted.ciphertext.toString(CryptoJS.enc.Base64); }AesUtil.prototype.decrypt = function(salt, iv, passPhrase, cipherText) {var key = this.generateKey(salt, passPhrase);var cipherParams = CryptoJS.lib.CipherParams.create({ciphertext: CryptoJS.enc.Base64.parse(cipherText)});var decrypted = CryptoJS.AES.decrypt(cipherParams,key,{ iv: CryptoJS.enc.Hex.parse(iv) });return decrypted.toString(CryptoJS.enc.Utf8); }JavaScript中的密碼加密
單擊提交按鈕后,將調用logMeIn()方法。 該方法將使用AesUtil.js定義的通用代碼來加密密碼并發出POST請求以驗證密碼。發送的密碼將以iv::salt::ciphertext的形式在服務器端,java將解密密碼并在響應中發送解密的密碼,該密碼將顯示在警報框中。
var app = angular.module('demoApp', []); app.controller('loginController', ['$scope', '$rootScope', '$http', function ($scope, $rootScope, $http) {$scope.logMeIn = function(){if(!$scope.userName || !$scope.password){$scope.showMessage("Missing required fields.", false);return;}var iv = CryptoJS.lib.WordArray.random(128/8).toString(CryptoJS.enc.Hex);var salt = CryptoJS.lib.WordArray.random(128/8).toString(CryptoJS.enc.Hex);var aesUtil = new AesUtil(128, 1000);var ciphertext = aesUtil.encrypt(salt, iv, $('#key').text(), $scope.password);var aesPassword = (iv + "::" + salt + "::" + ciphertext);var password = btoa(aesPassword);var data = {userName: $scope.userName,password: password}$http.post('/login',data).then(function (response){if(response.status === 200){alert("Password is " + response.data.password);}else {alert("Error occurred");}})};}]);Java中的AES解密
首先,讓我們實現將攔截登錄請求的控制器類。 這里我們已經對該密鑰進行了硬編碼,該密鑰將由服務器唯一生成,并針對每個登錄請求發送給客戶端。 客戶端將使用相同的密鑰,而加密和服務器將使用相同的密鑰進行解密。請確保密鑰長度為16,因為我們使用的是128位加密。 記住我們從客戶端發送的加密文本的格式– iv::salt::ciphertext 。 文本以相同格式解密。 我們已經有IV,salt和密文。
package com.example.demo.controller;import com.example.demo.model.Credentials; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody;import javax.servlet.http.HttpServletRequest; import java.util.HashMap; import java.util.Map; import java.util.UUID;@Controller public class WelcomeController {private static final Logger LOGGER = LoggerFactory.getLogger(WelcomeController.class);@RequestMapping(value={"/login"},method = RequestMethod.GET)public String loginPage(HttpServletRequest request){LOGGER.info("Received request for login page with id - " + request.getSession().getId());String randomKey = UUID.randomUUID().toString();//String uniqueKey = randomKey.substring(randomKey.length()-17, randomKey.length() -1);String uniqueKey = "1234567891234567";request.getSession().setAttribute("key", uniqueKey);return "index";}@RequestMapping(value={"/login"},method = RequestMethod.POST)public @ResponseBody ResponseEntity login(@RequestBody Credentials credentials, HttpServletRequest request) {String decryptedPassword = new String(java.util.Base64.getDecoder().decode(credentials.getPassword()));AesUtil aesUtil = new AesUtil(128, 1000);Map map = new HashMap<>();if (decryptedPassword != null && decryptedPassword.split("::").length == 3) {LOGGER.info("Password decrypted successfully for username - " + credentials.getUserName());String password = aesUtil.decrypt(decryptedPassword.split("::")[1], decryptedPassword.split("::")[0], "1234567891234567", decryptedPassword.split("::")[2]);map.put("password", password);}return new ResponseEntity<>(map, HttpStatus.OK);}}以下是用于AES加密和解密的java util類。您可以在java中遵循AES加密和解密,以獲取有關以下實現的更多詳細說明。
AesUtil.java package com.example.demo.controller;import org.apache.commons.codec.DecoderException; import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.binary.Hex;import javax.crypto.*; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.PBEKeySpec; import javax.crypto.spec.SecretKeySpec; import java.io.UnsupportedEncodingException; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.spec.InvalidKeySpecException; import java.security.spec.KeySpec;public class AesUtil {private final int keySize;private final int iterationCount;private final Cipher cipher;public AesUtil(int keySize, int iterationCount) {this.keySize = keySize;this.iterationCount = iterationCount;try {cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");}catch (NoSuchAlgorithmException | NoSuchPaddingException e) {throw fail(e);}}public String decrypt(String salt, String iv, String passphrase, String ciphertext) {try {SecretKey key = generateKey(salt, passphrase);byte[] decrypted = doFinal(Cipher.DECRYPT_MODE, key, iv, base64(ciphertext));return new String(decrypted, "UTF-8");}catch (UnsupportedEncodingException e) {return null;}catch (Exception e){return null;}}private byte[] doFinal(int encryptMode, SecretKey key, String iv, byte[] bytes) {try {cipher.init(encryptMode, key, new IvParameterSpec(hex(iv)));return cipher.doFinal(bytes);}catch (InvalidKeyException| InvalidAlgorithmParameterException| IllegalBlockSizeException| BadPaddingException e) {return null;}}private SecretKey generateKey(String salt, String passphrase) {try {SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");KeySpec spec = new PBEKeySpec(passphrase.toCharArray(), hex(salt), iterationCount, keySize);SecretKey key = new SecretKeySpec(factory.generateSecret(spec).getEncoded(), "AES");return key;}catch (NoSuchAlgorithmException | InvalidKeySpecException e) {return null;}}public static byte[] base64(String str) {return Base64.decodeBase64(str);}public static byte[] hex(String str) {try {return Hex.decodeHex(str.toCharArray());}catch (DecoderException e) {throw new IllegalStateException(e);}}private IllegalStateException fail(Exception e) {return null;}}測試AES加密和解密
作為Java應用程序運行DemoApplication.java并點擊http:// localhost:8080 。 登錄頁面出現后,您可以輸入用戶名和密碼,然后單擊“提交”按鈕,您可以在警報中看到解密的密碼。
/>
結論
在本文中,我們討論了可與Java和Javascript互操作的AES加密。 我們使用Crypto.js庫在javascript中執行此加密。 完整的源代碼可以在這里找到。如果您有任何要添加或共享的內容,請在下面的評論部分中共享。
翻譯自: https://www.javacodegeeks.com/2018/03/aes-encryption-in-javascript-and-decryption-in-java.html
總結
以上是生活随笔為你收集整理的Javascript中的AES加密和Java中的解密的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 英特尔酷睿 i9-14900KF 处理器
- 下一篇: AMD 针对《匹诺曹的谎言》发布专用驱动