服务器(Java – Cipher)和客户端之间的AES(Javascript – CryptoJS)

我必须在JS中创建一个应用程序,它使用AES对消息进行编码,并通过AJAX将其传递给服务器。 然后服务器使用Java解码消息。

我的问题是: 如何在JS中加密消息并能够使用AES在Java中解密它? 知道java和js之间的通信已经通过webservices建立

客户端,我使用Crypto JS库( http://code.google.com/p/crypto-js/ )。 服务器端我使用Java提供的Cipher类(我使用的是Java Play框架,但这里并不重要)。

我对密码学完全不熟悉。 我整天都在研究,仍然无法完成这项工作。

问题是用于加密和解密消息的密钥必须相同,我不知道如何做到这一点。

从我的搜索中,我了解使用AES有不同的模式。 默认情况下,Java使用ECB而CryptoJS使用CBC这是一个问题,但通过告诉CryptoJS也使用ECB模式,这似乎不太难修复。 但是有一个填充问题,似乎Java中唯一可用的填充和CryptoJS根本没有填充。 但是当我在Java中使用NoPadding时,我得到了一个例外。

但即使我设法解决这个问题,最大的问题是CryptoJS生成的密钥和Java生成的密钥不一样。 如果我用Java加密消息,结果总是相同的,用hex表示。 但是在加密JS中它是在Base64中它永远不会相同….

我知道这是由密钥生成引起的,这在Java和CryptoJS中是不一样的(然后进入IV和Salt的概念,这对我来说是模糊的)。

不要在浏览器JS中进行加密; 安全做不可能 。

使用SSL。 其目的是加密浏览器和服务器之间的通信。

如果成本是您的问题,则有免费的SSL证书 。

我最近在这个问题上投入了很多天。 我在java和javascript方面尝试了很多库。 这个博客节省了我的一天: http : //watchitlater.com/blog/tag/aes/ 。

所以它可以做到! 只需使用Gibberish AES( https://github.com/mdp/gibberish-aes )和java端的javascript端和bouncycastle。

Java端加密可能看起来像这样(在上面提到的博客上倾斜):

import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.Provider; import java.security.spec.InvalidKeySpecException; import java.util.Random; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.PBEKeySpec; import javax.crypto.spec.PBEParameterSpec; import org.bouncycastle.jce.provider.BouncyCastleProvider; import sun.misc.BASE64Encoder; public class OpenSSLEncryption { private static final String CIPHER_ALG = "PBEWITHMD5AND256BITAES-CBC-OPENSSL"; private static final Provider CIPHER_PROVIDER = new BouncyCastleProvider(); private static final String PREFIX = "Salted__"; private static final String UTF_8 = "UTF-8"; private String password; private PBEKeySpec pbeSpec; private SecretKeyFactory keyFact; private Cipher cipher; private Random rand = new Random(); private BASE64Encoder encoder = new BASE64Encoder(); public OpenSSLEncryption(String password) throws NoSuchAlgorithmException, NoSuchPaddingException { this.password = password; pbeSpec = new PBEKeySpec(password.toCharArray()); keyFact = SecretKeyFactory.getInstance(CIPHER_ALG, CIPHER_PROVIDER); cipher = Cipher.getInstance(CIPHER_ALG, CIPHER_PROVIDER); } public synchronized String encrypt(String toEncrypt) throws InvalidKeySpecException, InvalidKeyException, InvalidAlgorithmParameterException, UnsupportedEncodingException, IllegalBlockSizeException, BadPaddingException, IOException { byte[] salt = new byte[8]; rand.nextBytes(salt); PBEParameterSpec defParams = new PBEParameterSpec(salt, 0); cipher.init(Cipher.ENCRYPT_MODE, keyFact.generateSecret(pbeSpec), defParams); byte[] cipherText = cipher.doFinal(toEncrypt.getBytes(UTF_8)); ByteArrayOutputStream baos = new ByteArrayOutputStream(cipherText.length + 16); baos.write(PREFIX.getBytes(UTF_8)); baos.write(salt); baos.write(cipherText); baos.close(); return encoder.encode(baos.toByteArray()); } }