admin管理员组文章数量:1201801
I'm trying to decrypt data on the browser using the AES-CTR algo. The WebCrypto API requires the counter to be passed as a BufferSource. How do I convert the counter (a number) to the expected input (a byte array)?
I'm using an all zero IV, so the counter starts at 0. Let's say I'm trying to decrypt data where counter = 445566. How do I convert 445566 into an ArrayBuffer?
const key = // retrieve decryption key
const encrypted = // retrieve encrypted data
const iv = new ArrayBuffer(16)
// iv is all zeros. I need it to represent 445566, how?
const algo = {
name: 'AES-CTR',
counter: iv,
length: 128
}
const decrypted = await crypto.subtle.decrypt(algo, key, encrypted)
EDIT: After digging around some crypto libraries, I ended up using this. It seems to do what I want, but no idea on correctness, performance, etc.
function numberToArrayBuffer(value) {
const view = new DataView(new ArrayBuffer(16))
for (var index = 15; index >= 0; --index) {
view.setUint8(index, value % 256)
value = value >> 8;
}
return view.buffer
}
I'm trying to decrypt data on the browser using the AES-CTR algo. The WebCrypto API requires the counter to be passed as a BufferSource. How do I convert the counter (a number) to the expected input (a byte array)?
I'm using an all zero IV, so the counter starts at 0. Let's say I'm trying to decrypt data where counter = 445566. How do I convert 445566 into an ArrayBuffer?
const key = // retrieve decryption key
const encrypted = // retrieve encrypted data
const iv = new ArrayBuffer(16)
// iv is all zeros. I need it to represent 445566, how?
const algo = {
name: 'AES-CTR',
counter: iv,
length: 128
}
const decrypted = await crypto.subtle.decrypt(algo, key, encrypted)
EDIT: After digging around some crypto libraries, I ended up using this. It seems to do what I want, but no idea on correctness, performance, etc.
function numberToArrayBuffer(value) {
const view = new DataView(new ArrayBuffer(16))
for (var index = 15; index >= 0; --index) {
view.setUint8(index, value % 256)
value = value >> 8;
}
return view.buffer
}
Share
Improve this question
edited Apr 9, 2019 at 0:02
Eric Guan
asked Apr 8, 2019 at 23:16
Eric GuanEric Guan
16k10 gold badges51 silver badges62 bronze badges
3
|
5 Answers
Reset to default 12There is a one-liner solution for IE10+ :)
new Int32Array([n]).buffer
This is what I use:
const bytesArray = (n) => {
if (!n) return new ArrayBuffer(0)
const a = []
a.unshift(n & 255)
while (n >= 256) {
n = n >>> 8
a.unshift(n & 255)
}
return new Uint8Array(a).buffer
}
Not sure if this is helpful. But just to cross check the authenticity of the code.
I wrote some test case to first convert the number to array buffer and use the array buffer value to decode it to the same.
var hex = 445566..toString(16);
var buffer = new ArrayBuffer(16);
var dataView = new DataView(buffer);
dataView.setInt32(0, '0x'+ hex);
console.log(dataView.getInt32(0)); //445566
//Using the uint16array data generated by the above code
var data = [0, 6, 204, 126, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
var buf = new ArrayBuffer(16);
var view = new DataView(buf);
data.forEach(function (b, i) {
view.setUint8(i, b % 256);
});
var num = view.getInt32(0);
console.log(num);//445566
function numberToArrayBuffer(value) {
const view = new DataView(new ArrayBuffer(16))
for (var index = 15; index >= 0; --index) {
view.setUint8(index, value % 256)
value = value >> 8;
}
return view.buffer
}
console.log(numberToArrayBuffer(445566)) // Uint8Array(16) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 204, 126]
Both the results are same. It's just that your code is producing the result in big endian format and mine in little endian.
So the approach you have followed is correct. As for the performance i don't think there is much impact
You don't need to do anything, the ArrayBuffer
is initialized to bytes all with value zero, which of course also represents the number value zero using in statically unsigned, big endian encoding - which is the common way of representing the counter in CTR mode.
Here is the description of the return value of ArrayBuffer
with just a specified size:
A new
ArrayBuffer
object of the specified size. Its contents are initialized to 0.
so there you go, you were ready without knowing it. The only thing I would certainly do is to comment that the counter in the buffer has been initialized to zero for the next developer (which may actually be you in a couple of years).
Note that CTR mode is secure if the counter is never repeated for the same key. For this, the nonce (which takes an unknown number of bytes to the left hand, most significant side) is commonly set to a random value, usually by simply initializing the first 8 bytes to random values. So you don't need to do any number encoding for that either.
You only need to encode the nonce if it consists of a 32 or 64 bit counter itself.
const uIntToBytes = (num, size, method) => {
const arr = new ArrayBuffer(size)
const view = new DataView(arr)
view[method + (size * 8)](0, num)
return arr
}
const toBytes = (data, type) =>
type == "u8" ? uIntToBytes(data, 1, "setUint") :
type == "u16" ? uIntToBytes(data, 2, "setUint") :
type == "u32" ? uIntToBytes(data, 4, "setUint") :
type == "u64" ? uIntToBytes(BigInt(data), 8, "setBigUint")
: `Not Sure about type - ${type}`
Usage:
toBytes(5, "u8")
本文标签: javascriptConvert number to ArrayBufferStack Overflow
版权声明:本文标题:javascript - Convert number to ArrayBuffer - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1738635931a2104032.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
const iv = Buffer.alloc(16)
. I was told an all-zero iv was okay if the key is used to encrypt only a single message. – Eric Guan Commented Apr 8, 2019 at 23:58