为了账号安全,请及时绑定邮箱和手机立即绑定

通过 javascript 加密并通过 Java 解密

通过 javascript 加密并通过 Java 解密

慕尼黑8549860 2024-01-17 16:50:35
我在我的反应本机应用程序中使用 AES 加密,如下所示import CryptoJS from 'crypto-js' ;encryptFun() {    var data = "123456";    var key  = CryptoJS.enc.Latin1.parse('1234567812345678');    var iv   = CryptoJS.enc.Latin1.parse('1234567812345678');      var encrypted = CryptoJS.AES.encrypt(      data,      key,      {iv:iv,mode:CryptoJS.mode.CBC,padding:CryptoJS.pad.ZeroPadding    });    console.log('encrypted: ' + encrypted) ;    var decrypted = CryptoJS.AES.decrypt(encrypted,key,{iv:iv,padding:CryptoJS.pad.ZeroPadding});    console.log('decrypted: '+decrypted.toString(CryptoJS.enc.Utf8));  }结果=加密:aK7+UX24ttBgfTnAndz9aQ==以下是我在后端使用 java 进行解密的代码 public static String desEncrypt() throws Exception {        try        {            String data = "aK7+UX24ttBgfTnAndz9aQ==" ;            String key = "1234567812345678";            String iv = "1234567812345678";            byte[] encrypted1 = new BASE64Decoder().decodeBuffer(data);            Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");            SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");            IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());            cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);            byte[] original = cipher.doFinal(encrypted1);            String originalString = new String(original);            return originalString;        }        catch (Exception e) {            e.printStackTrace();            return null;        }    }输出=解密:= 123456[][][][][][][][][][]我将其设置为 16 位,如上所述。我想要的是输出应该只有 123456。
查看完整描述

3 回答

?
ibeautiful

TA贡献1993条经验 获得超5个赞

我建议你使用java.util.Base64解码。以下结果正确。我还建议使用修剪功能return originalString,看看是否有效。


public class Decrypt {


    public static void main(String[] args) {

        try

        {

            String data = "aK7+UX24ttBgfTnAndz9aQ==" ;

            String key = "1234567812345678";

            String iv = "1234567812345678";


            Decoder decoder = Base64.getDecoder();   

             byte[] encrypted1 = decoder.decode(data);


            Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");

            SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");

            IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());


            cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);


            byte[] original = cipher.doFinal(encrypted1);

            String originalString = new String(original);

            System.out.println(originalString.trim());

        }

        catch (Exception e) {

            e.printStackTrace();

        }

    }

}


查看完整回答
反对 回复 2024-01-17
?
摇曳的蔷薇

TA贡献1793条经验 获得超6个赞

控制器部分生成 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;



@RestController

public 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;

@Service

public 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;

    }


}

遵循的步骤

  1. 使用 RSA 密钥

  2. 生成随机 AES(密钥、iv、盐)- 使用 crypto.js

  3. 使用 AES 并加密易受攻击的数据

  4. 使用RSA公钥加密AES密钥

  5. 通过网络发送加密数据和密钥

  6. 服务使用 AES 数据解密密钥

  7. 使用AES密钥解密数据

  8. 将数据发送回前端

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.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);

}

其余的是


JSEncrypt v2.3.1 https://npmcdn.com/jsencrypt@2.3.1/LICENSE.txt

最后是 crypto-js.min.js


谢谢,我希望这会有用


查看完整回答
反对 回复 2024-01-17
?
HUH函数

TA贡献1836条经验 获得超4个赞

当您在 JS 中填充时,zeros您无法使用 解密NoPadding,解决方案是对数组或字符串进行操作

  • 修剪数组

    int i = original .length - 1;
    while (i >= 0 && original [i] == 0) {
        --i;
    }
    return new String(Arrays.copyOf(original , i + 1));
  • 修剪字符串

    return new String(original).trim();
  • 手动删除zero

    return new String(original).replace("\0", "");

ZeroPAdding或者,因为Java 中似乎没有实现 ( Cipher Documentation),建议使用CryptoJS.pad.Pkcs


查看完整回答
反对 回复 2024-01-17
  • 3 回答
  • 0 关注
  • 76 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信