 
					摇曳的蔷薇
					控制器部分生成 RSA 密钥(公共和私有)package com.secure.encryption.decryption.controller;import java.io.UnsupportedEncodingException;import java.nio.charset.StandardCharsets;import java.util.Base64;import java.util.Date;import java.util.HashMap;import java.util.Map;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.CrossOrigin;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.RequestBody;import org.springframework.web.bind.annotation.RestController;import com.secure.encryption.decryption.rsa.keystore.KeyStore;import com.secure.encryption.decryption.rsa.service.RSAKeyPairGenerator;import com.secure.encryption.decryption.util.AesUtil;@RestControllerpublic class EncryptDecryptController {        @Autowired    RSAKeyPairGenerator rsa;        @Autowired    KeyStore keystore;            @CrossOrigin    @GetMapping(value = "get/rsa/public")    public Map<String, Object> generateRSA_PUBLIC_PRIVATE_KEY()    {        Map<String, Object> response = new HashMap<>();        /**         * Below function creates rsa public & private key         * While this api only share PUBLICKEY         * Whereas PRIVATEKEY is stored in bean/model         */        String public_KEY = null;        public_KEY = rsa.KeyPairGenerator();        response.put("public", public_KEY);        return response;    }        @CrossOrigin    @PostMapping(value = "/decrypt/AES_encyptedKEY/with/RSA_privateKEY/decryptdata/with/aes")    public Map<String, Object> decrypt(@RequestBody Map<String, Object> req) throws UnsupportedEncodingException    {        /**         * First decrypt AES-Key which is encrypted with RSA Public Key         * Use RSA privateKey for decryption         */        String Decrypted_AES_Key = rsa.decrypt(req.get("phrase").toString(),keystore.getPrivateKey());                byte[] decoded = Base64.getDecoder().decode(req.get("data").toString());        String encryptedAES_Data = new String(decoded, StandardCharsets.UTF_8);                 /**         * Decode data to base 64         * Use AES key to decrypt the data         */        AesUtil aesUtil = new AesUtil(128, 1000);        String decryptedAES_Data = aesUtil.decrypt(                req.get("salt").toString(),                req.get("iv").toString(),                 Decrypted_AES_Key,                encryptedAES_Data);                /**         * Map actual data as response         */        req.put("data", decryptedAES_Data);            return req;    }        @CrossOrigin    @GetMapping(value = "/decryptfrom/backend/aes/plain/decrypt/frontend")    public Map<String, Object> sendAESencryptedData()    {        /**         * Generate random key           * Encrypt data using same         * pass key to UI         * Decrypt using same key, iv and salt         */        Map<String, Object> response = new HashMap<>();        int i = (int) (new Date().getTime()/1000);        //String iv = generateIv().toString();        AesUtil aesUtil = new AesUtil(128, 1000);        String phrase = String.valueOf(i);//"my secret key 123";        //String salt =  new String(generateSalt(32));        String iv = "bb6a69ace7a11a38fba164238e000c7c";        String salt = "6c3674b6469467ab0b9f2b57ce36e78d";        String encryptedAES_Data =                 Base64.getEncoder().encodeToString(                aesUtil.encrypt(                salt,                iv,                 phrase,                "ganesha")                );                response.put("data", encryptedAES_Data);        response.put("salt", salt);        response.put("iv", iv);        response.put("key", phrase);        return response;    }        /*    public IvParameterSpec generateIv() {        byte[] iv = new byte[16];        new SecureRandom().nextBytes(iv);        return new IvParameterSpec(iv);    }        private byte[] generateSalt(int size) {        try {             byte[] salt = new byte[size];                SecureRandom rand = SecureRandom.getInstance("SHA1PRNG");                rand.nextBytes(salt);                return salt;        } catch (Exception e) {            System.err.println(e);        }        return null;           }    */    }生成 RSA 随机密钥的服务package com.secure.encryption.decryption.rsa.service;public interface RSAKeyPairGenerator {    public String KeyPairGenerator();    public byte[] encrypt(String data, String publicKey);    public String decrypt(String data, String base64PrivateKey);}实现类package com.secure.encryption.decryption.rsa.service;import java.security.InvalidKeyException;import java.security.KeyFactory;import java.security.KeyPair;import java.security.KeyPairGenerator;import java.security.NoSuchAlgorithmException;import java.security.PrivateKey;import java.security.PublicKey;import java.security.spec.InvalidKeySpecException;import java.security.spec.PKCS8EncodedKeySpec;import java.security.spec.X509EncodedKeySpec;import java.util.Base64;import java.util.HashMap;import java.util.Map;import javax.crypto.BadPaddingException;import javax.crypto.Cipher;import javax.crypto.IllegalBlockSizeException;import javax.crypto.NoSuchPaddingException;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import com.secure.encryption.decryption.rsa.keystore.KeyStore;@Servicepublic class RSAKeyPairGeneratorImpl implements RSAKeyPairGenerator{    @Autowired    KeyStore keystore;    @Override    public String KeyPairGenerator() {        Map<String, Object> keypair = new HashMap<String, Object>();        try {            KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");            keyGen.initialize(1024);            KeyPair pair = keyGen.generateKeyPair();            final String privatestring = Base64.getEncoder().encodeToString(pair.getPrivate().getEncoded());            final String publicstring = Base64.getEncoder().encodeToString(pair.getPublic().getEncoded());            keystore.setPrivateKey(privatestring);            return publicstring;        } catch (Exception e) {            System.err.println(e);        }        return null;    }        private static PublicKey getPublicKey(String base64PublicKey){            PublicKey publicKey = null;            try{                X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(base64PublicKey.getBytes()));                KeyFactory keyFactory = KeyFactory.getInstance("RSA");                publicKey = keyFactory.generatePublic(keySpec);                return publicKey;            } catch (NoSuchAlgorithmException e) {                e.printStackTrace();            } catch (InvalidKeySpecException e) {                e.printStackTrace();            }            return publicKey;        }        private static PrivateKey getPrivateKey(String base64PrivateKey){            PrivateKey privateKey = null;            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(base64PrivateKey.getBytes()));            KeyFactory keyFactory = null;            try {                keyFactory = KeyFactory.getInstance("RSA");            } catch (NoSuchAlgorithmException e) {                e.printStackTrace();            }            try {                privateKey = keyFactory.generatePrivate(keySpec);            } catch (InvalidKeySpecException e) {                e.printStackTrace();            }            return privateKey;        }    public byte[] encrypt(String data, String publicKey) {//throws BadPaddingException, IllegalBlockSizeException, InvalidKeyException, NoSuchPaddingException, NoSuchAlgorithmException {       try {            //AES/CBC/PKCS5Padding            //RSA/ECB/PKCS1Padding            Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");            cipher.init(Cipher.ENCRYPT_MODE, getPublicKey(publicKey));            return cipher.doFinal(data.getBytes());        } catch (Exception e) {            System.err.println(e);        }       return null;    }    private static String decrypt(byte[] data, PrivateKey privateKey) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");        cipher.init(Cipher.DECRYPT_MODE, privateKey);        return new String(cipher.doFinal(data));    }    public String decrypt(String data, String base64PrivateKey) {//throws IllegalBlockSizeException, InvalidKeyException, BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException {        try {            return decrypt(Base64.getDecoder().decode(data.getBytes()), getPrivateKey(base64PrivateKey));        } catch (InvalidKeyException e) {            // TODO Auto-generated catch block            e.printStackTrace();        } catch (NoSuchPaddingException e) {            // TODO Auto-generated catch block            e.printStackTrace();        } catch (NoSuchAlgorithmException e) {            // TODO Auto-generated catch block            e.printStackTrace();        } catch (BadPaddingException e) {            // TODO Auto-generated catch block            e.printStackTrace();        } catch (IllegalBlockSizeException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }        return null;    }}AesUtil 类package com.secure.encryption.decryption.util;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;import javax.crypto.BadPaddingException;import javax.crypto.Cipher;import javax.crypto.IllegalBlockSizeException;import javax.crypto.NoSuchPaddingException;import javax.crypto.SecretKey;import javax.crypto.SecretKeyFactory;import javax.crypto.spec.IvParameterSpec;import javax.crypto.spec.PBEKeySpec;import javax.crypto.spec.SecretKeySpec;import org.apache.commons.codec.DecoderException;import org.apache.commons.codec.binary.Hex;import org.apache.tomcat.util.codec.binary.Base64;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 byte[] encrypt(String salt, String iv, String passphrase, String plaintext) {        try {            SecretKey key = generateKey(salt, passphrase);            byte[] encrypted = doFinal(Cipher.ENCRYPT_MODE, key, iv, plaintext.getBytes("UTF-8"));            System.out.println(encrypted);            return encrypted;//Base64.getEncoder().encodeToString(encrypted);            //String s = Base64.getEncoder().encodeToString(encrypted);        }        catch (UnsupportedEncodingException 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;    }}遵循的步骤使用 RSA 密钥生成随机 AES(密钥、iv、盐)- 使用 crypto.js使用 AES 并加密易受攻击的数据使用RSA公钥加密AES密钥通过网络发送加密数据和密钥服务使用 AES 数据解密密钥使用AES密钥解密数据将数据发送回前端Html页面供参考<!DOCTYPE html><html><body>    <script src="jquery.min.js"></script>        <script src="jsencrypt.min.js"></script><script type="text/javascript" src="crypto-js.min.js"></script><script type="text/javascript" src="aes.js"></script><script type="text/javascript">const payloadsample = {                "addressLine1": "301,Kamala Mills Compound",        "addressLine2": "Gr Flr, Tulsi Pipe Rd, Lower Parel ",        "addressLine4": "Mumbai, Maharashtra",        "zipcode": 400071};/**Step 1 ) - get data**//**Step 2 ) - get RSA pub Key**/function hybridEncryption(){            $.ajax({        type: 'GET',//post        url: 'http://localhost:1818/get/rsa/public',         success: function(res) {                        let RSAEncrypt = new JSEncrypt();                RSAEncrypt.setPublicKey(res.public);//set RSA public key                            const key = Math.random().toString(36).slice(2);//Generate random AES key                console.log("key ", key);                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);                debugger                console.log(key)                var data = JSON.stringify({ payloadsample });                var ciphertext = aesUtil.encrypt(salt, iv, key, data);/**Step 3 ) - generate key **/                senData(RSAEncrypt, iv, salt, key, btoa(ciphertext))            },         error:function(e) {            console.error(e);        },        contentType: "application/json",        dataType: 'json'    });    }function senData(RSAEncrypt, iv, salt, key, base64Content){        const payload = {            "phrase":RSAEncrypt.encrypt(key),//encrypt with RSA            "data":base64Content,            "iv":iv,            "salt":salt        }        console.log("sending : ", payload);        $.ajax({            type: 'POST',            url: 'http://localhost:1818/decrypt/AES_encyptedKEY/with/RSA_privateKEY/decryptdata/with/aes',            data: JSON.stringify (payload), // or JSON.stringify ({name: 'jonas'}),            success: function(data) {                 console.log(data);                 },             error:function(e) {                console.error(e);            },            contentType: "application/json",            dataType: 'json'        });}   hybridEncryption();/** * Incase of Backend encryption to Front end Decryption * decryptBE() - will get AES encrypted data with associated data * */function decryptBE(){      $.ajax({        type: 'GET',//post        url: 'http://localhost:1818/decryptfrom/backend/aes/plain/decrypt/frontend',         success: function(res) {        debugger        var aesUtil = new AesUtil(128, 1000);        var ciphertext = aesUtil.decrypt(res.salt, res.iv, res.key, res.data);      console.log(ciphertext);            },         error:function(e) {            console.error(e);        },        contentType: "application/json",        dataType: 'json'    });}</script></body></html> 这是一个使用参考的工作示例使用的其他库是 aes.jsvar 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);}其余的是JSEncrypt v2.3.1 https://npmcdn.com/jsencrypt@2.3.1/LICENSE.txt最后是 crypto-js.min.js谢谢,我希望这会有用