如何解密 javascript 中由 JAVA 使用 AES 加密的文件
How to decrypt a file in javascript which is encrypted by JAVA with AES
我已经用 AES256 加密了 Java 中的 JPG 文件,但不知道如何解密 javascript 中的 JPG 文件。有人有更好的主意吗?我为此苦苦挣扎了 4 天。
byte[] ivBytes = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
String key = "1234567890123456789012345678901d";
AlgorithmParameterSpec ivSpec = new IvParameterSpec(ivBytes);
SecretKeySpec newKey = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(mode, newKey, ivSpec);
InputStream input = null;
OutputStream output = null;
try {
input = new BufferedInputStream(new FileInputStream(new File("/home/java/test/aaa.JPG")));
output = new BufferedOutputStream(new FileOutputStream(new File("/home/java/test/bbb.JPG")));
byte[] buffer = new byte[1024];
int read = -1;
while((read = input.read(buffer)) != -1){
output.write(cipher.update(buffer, 0, read));
}
output.write(cipher.doFinal());
}
finally {
if(output != null){
try {
output.close();
} catch(IOException ie){
logger.info(ie.getMessage());
}
}
if(input != null){
try {
input.close();
} catch(IOException ie){
logger.info(ie.getMessage());
}
}
}
这是我目前试过的代码。我用过 CryptoJS,而 Decrypt 没有 return 任何东西。
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="./CryptoJS v3.1.2/rollups/aes.js"></script>
<script type="text/javascript" src="jquery-3.2.1.min.js"></script>
<meta charset=utf-8 />
<title>JS Bin</title>
<style>
article, aside, figure, footer, header, hgroup,
menu, nav, section { display: block; }
</style>
</head>
<body>
<input type='file' onchange="readURL(this);" />
<img id="blah" src="#" alt="your image" />
<a class="download" href="">Download</a>
<script>
var a = $('.download');
var key = CryptoJS.enc.Hex.parse("1234567890123456789012345678901d");
var iv = CryptoJS.enc.Hex.parse("00000000000000000000000000000000");
function readURL(input) {
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
/////////
var decrypted = CryptoJS.AES.decrypt(e.target.result, key,
{
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
}
).toString(CryptoJS.enc.Latin1);
if(!/^data:/.test(decrypted)){
alert("Invalid pass phrase or file! Please try again.");
return false;
}
a.attr('href', decrypted);
a.attr('download', input.files[0].name.replace('.enc',''));
};
//reader.readAsDataURL(input.files[0]);
reader.readAsText(input.files[0]);
}
}
</script>
</body>
</html>
您的密钥有误,Java(错误地)使用了密钥的 ASCII 表示形式:
String key = "1234567890123456789012345678901d";
...
SecretKeySpec newKey = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
这会生成 AES-256 的 32 字节密钥。但是您的Java脚本使用密钥的十六进制解码:
var key = CryptoJS.enc.Hex.parse("1234567890123456789012345678901d");
生成 AES-128 的 16 字节密钥。
使用错误的键显然不会得到正确的结果。
因此,您要么必须像在 Java 中对 IV 进行编码一样对密钥进行编码,要么使用十六进制解码器(默认情况下 Java 中不存在),或者您应该 "fix" 您的 Java脚本执行与 Java 中相同的操作,并使用密钥字符串的 ASCII 编码。
键,一般来说,不应该是字符串。
我已经用 AES256 加密了 Java 中的 JPG 文件,但不知道如何解密 javascript 中的 JPG 文件。有人有更好的主意吗?我为此苦苦挣扎了 4 天。
byte[] ivBytes = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
String key = "1234567890123456789012345678901d";
AlgorithmParameterSpec ivSpec = new IvParameterSpec(ivBytes);
SecretKeySpec newKey = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(mode, newKey, ivSpec);
InputStream input = null;
OutputStream output = null;
try {
input = new BufferedInputStream(new FileInputStream(new File("/home/java/test/aaa.JPG")));
output = new BufferedOutputStream(new FileOutputStream(new File("/home/java/test/bbb.JPG")));
byte[] buffer = new byte[1024];
int read = -1;
while((read = input.read(buffer)) != -1){
output.write(cipher.update(buffer, 0, read));
}
output.write(cipher.doFinal());
}
finally {
if(output != null){
try {
output.close();
} catch(IOException ie){
logger.info(ie.getMessage());
}
}
if(input != null){
try {
input.close();
} catch(IOException ie){
logger.info(ie.getMessage());
}
}
}
这是我目前试过的代码。我用过 CryptoJS,而 Decrypt 没有 return 任何东西。
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="./CryptoJS v3.1.2/rollups/aes.js"></script>
<script type="text/javascript" src="jquery-3.2.1.min.js"></script>
<meta charset=utf-8 />
<title>JS Bin</title>
<style>
article, aside, figure, footer, header, hgroup,
menu, nav, section { display: block; }
</style>
</head>
<body>
<input type='file' onchange="readURL(this);" />
<img id="blah" src="#" alt="your image" />
<a class="download" href="">Download</a>
<script>
var a = $('.download');
var key = CryptoJS.enc.Hex.parse("1234567890123456789012345678901d");
var iv = CryptoJS.enc.Hex.parse("00000000000000000000000000000000");
function readURL(input) {
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
/////////
var decrypted = CryptoJS.AES.decrypt(e.target.result, key,
{
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
}
).toString(CryptoJS.enc.Latin1);
if(!/^data:/.test(decrypted)){
alert("Invalid pass phrase or file! Please try again.");
return false;
}
a.attr('href', decrypted);
a.attr('download', input.files[0].name.replace('.enc',''));
};
//reader.readAsDataURL(input.files[0]);
reader.readAsText(input.files[0]);
}
}
</script>
</body>
</html>
您的密钥有误,Java(错误地)使用了密钥的 ASCII 表示形式:
String key = "1234567890123456789012345678901d";
...
SecretKeySpec newKey = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
这会生成 AES-256 的 32 字节密钥。但是您的Java脚本使用密钥的十六进制解码:
var key = CryptoJS.enc.Hex.parse("1234567890123456789012345678901d");
生成 AES-128 的 16 字节密钥。
使用错误的键显然不会得到正确的结果。
因此,您要么必须像在 Java 中对 IV 进行编码一样对密钥进行编码,要么使用十六进制解码器(默认情况下 Java 中不存在),或者您应该 "fix" 您的 Java脚本执行与 Java 中相同的操作,并使用密钥字符串的 ASCII 编码。
键,一般来说,不应该是字符串。