当然,我需要从客户端(JavaScript)加密字符串,并从服务器端( Java )解密,所以我找到了CryptoJS,我用相同的params/配置( mi Java代码)编写了代码,但是输出总是不同的,您知道吗?
我使用CBC和NoPadding
CryptoJS
http://jsfiddle.net/Soldier/gCHAG/
<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的输出:
Encrypted: VNzZNKJTqfRbM7zO/M4cDQ==
Encrypted Hex: 54dcd934a253a9f45b33bccefcce1c0d来自Java代码的输出:
Encrypted: j6dSmg2lfjY2RpN91GNgNw==
Encrypted Hex: 6a3664536d67326c666a593252704e3931474e674e773d3d加密的base64字符串具有相同的长度,但不具有十六进制。如果我将CryptoJS的输出结果放入Java中,则解密是不正确的。
致以敬意,
发布于 2013-10-18 20:23:29
这里的问题是您的键输入不一致。
CryptoJS.enc.Hex.parse('0123456789abcdef')将输入读入为一系列字节,表示为两位十六进制值:01、23、45等。30 (十进制48,'0'的ASCII代码),然后是31 (十进制49,'1'的ASCII代码)等等。您可以通过使用JavaScript (将读取单个字符值并将其用作字节值:http://jsfiddle.net/gCHAG/1/ (这将产生相同的j6dSm...输出)的CryptoJS.enc.Latin1.parse使其与j6dSm...实现相一致。
但是,您可能希望每个数字都是它自己的字节。要做到这一点,您需要更改这两个实现。
Java:
// use hex literals, not characters
byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F };
// array values: 0x00, 0x01, 0x02, etcJavaScript:
// remember each bytes is two digits wide
CryptoJS.enc.Hex.parse('000102030405060708090a0b0c0d0e0f')
// array values: 0x00, 0x01, 0x02, etc发布于 2013-10-17 21:48:41
字符' 0‘与十六进制值0不相同。CryptoJS键很可能与Java不同,因为您将它们实例化为不同的对象类型。创建后,用两种语言打印出键/IV并进行比较。
编辑:也就是说,这可能会被移到StackOverflow,因为关于特定密码库的问题在这里并不是主题。
发布于 2015-01-09 09:35:26
非常有用的例子SoldierCorp,谢谢!
有几样东西可以改进你的例子:
在javascript中替换on
padding: CryptoJS.pad.Pkcs7在java中替换on
algorithm = "AES/CBC/PKCS5Padding"在javascript中替换on
var key = CryptoJS.MD5("Secret Passphrase");在java中替换on
byte[] keyValue = org.apache.commons.codec.digest.DigestUtils.md5("Secret Passphrase");https://stackoverflow.com/questions/19455054
复制相似问题