- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在编写一个 Chrome 扩展程序,它使用 CryptoJS 进行一些 Apache Thrift 工作。我目前正在尝试让 CryptoJS 工作。我在使用 CryptoJS 解密由 CryptoJS 加密的数据时遇到问题。我在下面附上一个测试用例,在问题描述之后。
发生的事情如下,我有一个“字节”数组:
var bArr = [11,0,1,0,0,0,6,100,105,103,101,115,116,11,0,2,0,0,0,152,67,119,65,66,65,65,65,65,69,109,78,111,99,109,57,116,90,83,49,48,90,88,78,48,76,87,78,115,97,87,86,117,100,65,103,65,65,103,65,65,49,68,69,75,65,65,77,65,65,65,65,65,86,75,102,66,85,103,115,65,66,65,65,65,65,67,81,49,90,68,99,119,77,71,73,120,78,67,48,121,78,84,90,107,76,84,81,119,77,109,81,116,79,84,65,48,90,105,48,52,79,84,86,105,78,68,73,50,89,109,78,108,78,84,99,76,65,65,85,65,65,65,65,85,89,50,104,121,98,50,49,108,76,87,78,115,97,87,86,117,100,67,49,122,90,87,78,121,90,88,81,65,11,0,3,0,0,0,36,52,51,52,55,54,56,98,53,45,50,48,102,102,45,52,99,100,102,45,56,53,97,50,45,57,49,49,56,50,98,55,98,51,102,57,53,0];
var stringToEncode = String.fromCharCode.apply(null, bArr);
我用 CryptoJS 加密然后解密。加密前的前 25 个字节:
11,0,1,0,0,0,6,100,105,103,101,115,116,11,0,2,0,0,0,152,67,119,65,66,65
解密后:
11,0,1,0,0,0,6,100,105,103,101,115,116,11,0,2,0,0,0,194,152,67,119,65,66
唯一的区别是在位置 20 处多了一个 194。显然,除了填充之外,所有其他字节都完全相同。我试图了解这是从哪里来的。
关于帽子的更多信息是这些字节。这是一个包含 3 个字段的 Thrift 结构,字段 2 包含另一个嵌入式 Thrift 结构的 Base64 表示。输入示例的前 20 个字节:
由于解密问题,Thrift 解析器错误地识别了 fid 2 值的长度。
我相信我在带有 PKCS7 填充的 OpenSSL 模式下使用带有 32 字节 key (SHA256) 和 16 字节 IV 的 AES256 CBC。
这是我的 qunit 测试。
test("Decryption", function() {
var bArr = [11,0,1,0,0,0,6,100,105,103,101,115,116,11,0,2,0,0,0,152,67,119,65,66,65,65,65,65,69,109,78,111,99,109,57,116,90,83,49,48,90,88,78,48,76,87,78,115,97,87,86,117,100,65,103,65,65,103,65,65,49,68,69,75,65,65,77,65,65,65,65,65,86,75,102,66,85,103,115,65,66,65,65,65,65,67,81,49,90,68,99,119,77,71,73,120,78,67,48,121,78,84,90,107,76,84,81,119,77,109,81,116,79,84,65,48,90,105,48,52,79,84,86,105,78,68,73,50,89,109,78,108,78,84,99,76,65,65,85,65,65,65,65,85,89,50,104,121,98,50,49,108,76,87,78,115,97,87,86,117,100,67,49,122,90,87,78,121,90,88,81,65,11,0,3,0,0,0,36,52,51,52,55,54,56,98,53,45,50,48,102,102,45,52,99,100,102,45,56,53,97,50,45,57,49,49,56,50,98,55,98,51,102,57,53,0];
var stringToEncode = String.fromCharCode.apply(null, bArr);
var symmetricKey = "v3JElaRswYgxOt4b";
var key = CryptoJS.enc.Latin1.parse( CryptoJS.enc.Latin1.stringify( CryptoJS.SHA256( symmetricKey ) ) );
var iv = CryptoJS.lib.WordArray.random( 16 );
var encrypted = CryptoJS.AES.encrypt( stringToEncode,
key,
{ iv: iv, format: CryptoJS.format.OpenSSL }
).ciphertext.toString(CryptoJS.enc.Latin1);
var decrypted = CryptoJS.AES.decrypt( { ciphertext: CryptoJS.enc.Latin1.parse(encrypted) },
key,
{ iv: iv, padding: CryptoJS.pad.NoPadding }
).toString(CryptoJS.enc.Latin1);
var buf = [];
for (var i=0; i<decrypted.length; i++) {
buf.push( decrypted.charCodeAt(i) );
}
var bstr1 = "";
for (var i=0; i<bArr.length; i++) {
bstr1 += (i>0) ? ","+bArr[i] : bArr[i]+"";
}
var bstr2 = "";
for (var i=0; i<buf.length; i++) {
bstr2 += (i>0) ? ","+buf[i] : buf[i]+"";
}
console.log("------------------------------------------");
console.log(bstr1);
console.log(bstr2);
console.log("------------------------------------------");
equal( stringToEncode.slice(0,200), decrypted.slice(0,200) );
});
我的测试 HTML 包装器加载了这些:
<script src="../bower_components/jquery/dist/jquery.min.js"></script>
<script src="../bower_components/js-base64/base64.js"></script>
<script src="../bower_components/thrift/lib/js/src/thrift.js"></script>
<script src="../bower_components/underscore/underscore-min.js"></script>
<script src="../bower_components/qunit/qunit/qunit.js"></script>
<script src="../bower_components/browserify-cryptojs/components/core.js"></script>
<script src="../bower_components/browserify-cryptojs/components/sha256.js"></script>
<script src="../bower_components/browserify-cryptojs/components/enc-base64.js"></script>
<script src="../bower_components/browserify-cryptojs/components/cipher-core.js"></script>
<script src="../bower_components/browserify-cryptojs/components/format-hex.js"></script>
<script src="../bower_components/browserify-cryptojs/components/aes.js"></script>
<script src="../bower_components/browserify-cryptojs/components/pad-nopadding.js"></script>
<!-- the Test Suite-->
<script type="text/javascript" src="test-client.js" charset="utf-8"></script>
<!-- CSS-->
<link rel="stylesheet" href="../bower_components/qunit/qunit/qunit.css" type="text/css" media="screen" />
我的 bower.json 是:
{
"name": "gossiperl-client-chrome",
"version": "0.1.0",
"main": "manifest.json",
"dependencies": {
"jquery": "~1.11.0",
"underscore": "~1.7.0",
"thrift": "radekg/thrift#js-binary-protocol",
"js-base64": "~2.1.5",
"qunit": "~1.14.0",
"browserify-cryptojs": "~0.3.1"
},
"authors": [
"radekg <...@....com>"
],
"description": "Gossiperl Chrome client with a sample application",
"keywords": [
"gossiperl",
"client"
],
"license": "MIT",
"homepage": "http://....com",
"private": true
}
最佳答案
问题是 CryptoJS 将输入视为 UTF-8 输入字符串,除非它已经是 WordArray
。如果您的输入不是 UTF-8,这当然是个问题。您看到的是 0x80 (128) 以上的值被转换为两个字节以修复 UTF-8 编码。
只要 WordArray
不支持从数组到 WordArray
的直接转换,您就可以直接转换为十六进制,然后再转换为 WordArray
。缺少此功能有点奇怪。
以下将具有无符号字节值的数组转换为十六进制(对无效字节值有一点警惕):
function tohex(unsignedByteArray) {
var hex = "";
for (var i = 0; i < unsignedByteArray.length; i++) {
var c = unsignedByteArray[i];
if (c < 0 || c > 255) {
throw "Value not an unsigned byte in array";
}
var h = c.toString(16);
if (h.length == 1) {
hex += "0" + h;
} else {
hex += h;
}
}
return hex;
}
function fromhex(hex) {
if (hex.length % 2 !== 0) {
throw "Hex string should contain even number of hex digits, one per byte";
}
var unsignedByteArray = [];
for (var i = 0; i < hex.length; i = i + 2) {
var h = hex.substring(i, i + 2);
if (!/^[0-9a-f]{2}$/i.test(h)) {
throw "Invalid hexdigit at offset " + i;
}
var c = parseInt(h, 16);
unsignedByteArray[unsignedByteArray.length] = c;
}
return unsignedByteArray;
}
所以你可以像这样使用这些函数:
var bArr = [11, 0, 1, 0, 0, 0, 6, 100, 105, 103, 101, 115, 116, 11, 0, 2, 0, 0, 0, 152, 67, 119, 65, 66, 65, 65, 65, 65, 69, 109, 78, 111, 99, 109, 57, 116, 90, 83, 49, 48, 90, 88, 78, 48, 76, 87, 78, 115, 97, 87, 86, 117, 100, 65, 103, 65, 65, 103, 65, 65, 49, 68, 69, 75, 65, 65, 77, 65, 65, 65, 65, 65, 86, 75, 102, 66, 85, 103, 115, 65, 66, 65, 65, 65, 65, 67, 81, 49, 90, 68, 99, 119, 77, 71, 73, 120, 78, 67, 48, 121, 78, 84, 90, 107, 76, 84, 81, 119, 77, 109, 81, 116, 79, 84, 65, 48, 90, 105, 48, 52, 79, 84, 86, 105, 78, 68, 73, 50, 89, 109, 78, 108, 78, 84, 99, 76, 65, 65, 85, 65, 65, 65, 65, 85, 89, 50, 104, 121, 98, 50, 49, 108, 76, 87, 78, 115, 97, 87, 86, 117, 100, 67, 49, 122, 90, 87, 78, 121, 90, 88, 81, 65, 11, 0, 3, 0, 0, 0, 36, 52, 51, 52, 55, 54, 56, 98, 53, 45, 50, 48, 102, 102, 45, 52, 99, 100, 102, 45, 56, 53, 97, 50, 45, 57, 49, 49, 56, 50, 98, 55, 98, 51, 102, 57, 53, 0];
var bArrHex = tohex(bArr);
var stringToEncode = CryptoJS.enc.Hex.parse(bArrHex);
var symmetricKey = "v3JElaRswYgxOt4b";
var key = CryptoJS.enc.Latin1.parse(CryptoJS.enc.Latin1.stringify(CryptoJS.SHA256(symmetricKey)));
var iv = CryptoJS.lib.WordArray.random(16);
var encrypted = CryptoJS.AES.encrypt(stringToEncode, key, { iv: iv, format: CryptoJS.format.OpenSSL });
var decrypted = CryptoJS.AES.decrypt(encrypted, key, { iv: iv, format: CryptoJS.format.OpenSSL });
var result = fromhex(decrypted.toString(CryptoJS.enc.Hex));
console.log(result);
if (bArr.toString() == result.toString()) {
console.log("success");
}
请注意,encrypted
在用作字符串时会自动编码为 base64。您不能对密文使用 Latin1 编码。请注意,您的 key 还应包含随机字节,而不仅仅是现在的可打印字符。
最后请注意,在没有 MAC 的情况下发送 AES 加密文本本质上是不安全的,例如因为填充 oracle 攻击以及任何人都可以更改传输中的数据这一事实。
关于javascript - CryptoJS AES CBC 256 解密在明文中间添加额外的字节,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27756579/
根据 Android docs ,activity生命周期如下: onCreate() onStart() onResume() onPause() onStop() onDestroy() 问题是,
我有一门类(class)有很多专栏,但这个问题只需要其中三个: ---------------------------------------- | start_date | start_time
给定在同一个 Tomcat 6 上运行的两个 Web 应用程序。如果您从一个应用程序到另一个应用程序进行 http 调用,Tomcat 是否会“短路”此调用,或者它会在调用之前一直在 interweb
我是一名优秀的程序员,十分优秀!