问题描述
我需要从客户端(JavaScript)加密肯定字符串并从服务器端(Java)解密,所以我找到了CryptoJS,我用mi Java Code的相同params /配置编写代码,但输出总是不同,你有什么想法或发生了什么?
I need to encrypt certainly string from client-side (JavaScript) and decrypt from server-side (Java), so I found CryptoJS and I write the code with the same params/configuration of mi Java Code but the output is always different, do you have any idea or what happen?
我正在使用 CBC与NoPadding
CryptoJS
<script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/aes.js">
</script>
<script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/components/pad-nopadding-min.js"></script>
<script>
function padString(source) {
var paddingChar = ' ';
var size = 16;
var x = source.length % size;
var padLength = size - x;
for (var i = 0; i < padLength; i++) source += paddingChar;
return source;
}
var key = CryptoJS.enc.Hex.parse('0123456789abcdef');
var iv = CryptoJS.enc.Hex.parse('fedcba9876543210');
var message = "soldier";
var padMsg = padString(message);
var encrypted = CryptoJS.AES.encrypt(padMsg, key, { iv: iv, padding: CryptoJS.pad.NoPadding, mode: CryptoJS.mode.CBC});
console.log("Encrypted: "+encrypted);
console.log("Encrypted text: "+encrypted.ciphertext);
</script>
Java代码
import java.security.Key;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import sun.misc.*;
public class AesCipher {
private static final String algorithm = "AES/CBC/NoPadding";
private static final byte[] keyValue = new byte[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
private static final byte[] ivValue = new byte[] { 'f', 'e', 'd', 'c', 'b', 'a', '9', '8', '7', '6', '5', '4', '3', '2', '1', '0' };
private static final IvParameterSpec ivspec = new IvParameterSpec(ivValue);
private static final SecretKeySpec keyspec = new SecretKeySpec(keyValue, "AES");
final protected static char[] hexArray = "0123456789ABCDEF".toCharArray();
public static String encrypt(String Data) throws Exception {
Cipher c = Cipher.getInstance(algorithm);
c.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
byte[] encVal = c.doFinal(Data.getBytes());
String encryptedValue = new BASE64Encoder().encode(encVal);
return encryptedValue;
}
public static String decrypt(String encryptedData) throws Exception {
Cipher c = Cipher.getInstance(algorithm);
c.init(Cipher.DECRYPT_MODE, keyspec, ivspec);
byte[] decordedValue = new BASE64Decoder().decodeBuffer(encryptedData);
byte[] decValue = c.doFinal(decordedValue);
String decryptedValue = new String(decValue);
return decryptedValue;
}
public static String bytesToHex(byte[] bytes) {
char[] hexChars = new char[bytes.length * 2];
int v;
for ( int j = 0; j < bytes.length; j++ ) {
v = bytes[j] & 0xFF;
hexChars[j * 2] = hexArray[v >>> 4];
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
}
return new String(hexChars);
}
private static String padString(String source) {
char paddingChar = ' ';
int size = 16;
int x = source.length() % size;
int padLength = size - x;
for (int i = 0; i < padLength; i++)
{
source += paddingChar;
}
return source;
}
public static void main(String[] args) throws Exception {
String password = "soldier";
String passwordEnc = AesCipher.encrypt(padString(password));
String passwordDec = AesCipher.decrypt(passwordEnc);
System.out.println("Plain Text : " + password);
System.out.println("Encrypted Text : " + passwordEnc);
System.out.println("Decrypted Text : " + passwordDec);
}
}
原始字符串:
soldier
CryptoJS的输出:
Output from CryptoJS:
Encrypted: VNzZNKJTqfRbM7zO/M4cDQ==
Encrypted Hex: 54dcd934a253a9f45b33bccefcce1c0d
Java代码的输出:
Output from Java Code:
Encrypted: j6dSmg2lfjY2RpN91GNgNw==
Encrypted Hex: 6a3664536d67326c666a593252704e3931474e674e773d3d
加密的base64字符串具有相同的长度但不是十六进制。
如果我将CryptoJS的输出结果放在Java代码中,则解密不正确。
The base64 string encrypted has same length but not the hex.If I put the output result of CryptoJS in Java Code, the decryption is incorrect.
问候,
推荐答案
这里的一个问题是你使用64位密钥和iv。
One problem here is that you're using 64 bit keys and iv's.
CryptoJS支持AES-128,AES-192和AES-256,AFAIK Java支持AES-128,因此您应该指定128位密钥和IV。这可能是整个问题 - 我肯定使用错误的密钥大小是未定义的行为。
CryptoJS supports AES-128, AES-192, and AES-256, and AFAIK Java supports AES-128, so you should probably be specifying 128 bit keys and IVs. That might be the whole problem - I'm sure using the wrong key size is undefined behavior.
至于输出长度的差异,22 base64字符是132位的信息,所以这是一个128位的答案(没有唯一的128位长度,21个字符太少)。 CryptoJS输出32个十六进制字符,即128位信息。这似乎是正确的。
As for the difference in output lengths, 22 base64 characters is 132 bits of information, so it's a 128 bit answer (There isn't a unique 128 bit length, 21 characters would have been too few). CryptoJS is outputting 32 hex characters, which is 128 bits of information. This seems correct.
Java代码输出48个十六进制字符,即192位信息。所以这是java代码错了。不过,我不确定为什么输出更多。
The Java code is outputting 48 hex characters which is 192 bits of information. So it's the java code that's wrong. I'm not sure why it's outputting more, though.
这篇关于不同的输出加密CryptoJS和Java代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!