我必须在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加密消息,结果总是相同的,用十六进制表示。但是在加密JS中,它在Base64中,它永远不会相同......
据我所知,这是由Java和CryptoJS中的密钥生成引起的(然后输入IV和Salt的概念对我来说很模糊)。
答案 0 :(得分:2)
答案 1 :(得分:1)
我最近在这个问题上投入了很多时间。我在java和javascript方面尝试了很多库。这个博客节省了我的一天:http://watchitlater.com/blog/tag/aes/。
所以可以做到!只需使用Gibberish AES(https://github.com/mdp/gibberish-aes)作为javascript端,并在java端使用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());
}
}