I have large text which i want to save as BLOB in SQLite DB. I learned in other posts that the string needs to be converted into ByteArray before being saved as BLOB. Below is my function that converts string into ByteArray But when inserting this ArrayBuffer into DB,its being saved as Object string [object ArrayBuffer]. That is because I am assuming Javascript ArrayBuffer is incompatible with SQLite. Can you help me as to how can I store this ArrayBuffer as BLOB without it being getting converted to string?
function str2ab(str) {
var buf = new ArrayBuffer(str.length*2); // 2 bytes for each char
var bufView = new Uint16Array(buf);
for (var i=0, strLen=str.length; i < strLen; i++) {
bufView[i] = str.charCodeAt(i);
}
return bufView;
}
Related
I'm trying to create SHA-1 hash on the client-side. I'm trying to do this with Web Crypto API but when I'm comparing the output to what various online tools give me, the result is completely different. I think the problem is in ArrayBuffer to Hex conversion. Here is my code:
function generateHash() {
var value = "mypassword";
var crypto = window.crypto;
var buffer = new ArrayBuffer(value);
var hash_bytes = crypto.subtle.digest("SHA-1", buffer);
hash_bytes.then(value => document.write([...new Uint8Array(value)].map(x => x.toString(16).padStart(2, '0')).join('')));
}
Output of document.write should be:
91dfd9ddb4198affc5c194cd8ce6d338fde470e2
But it's not, I get a completely different hash of different length (should be 40). Could I have some advise on the problem? Thanks.
The problem seems to be more the input conversion from a string to an ArrayBuffer. E.g. with str2ab() the code works:
generateHash();
function generateHash() {
var value = "mypassword";
var crypto = window.crypto;
var buffer = str2ab(value); // Fix
var hash_bytes = crypto.subtle.digest("SHA-1", buffer);
hash_bytes.then(value => document.write([...new Uint8Array(value)].map(x => x.toString(16).padStart(2, '0')).join('')));
}
// https://stackoverflow.com/a/11058858
function str2ab(str) {
const buf = new ArrayBuffer(str.length);
const bufView = new Uint8Array(buf);
for (let i = 0, strLen = str.length; i < strLen; i++) {
bufView[i] = str.charCodeAt(i);
}
return buf;
}
with the expected output:
91dfd9ddb4198affc5c194cd8ce6d338fde470e2
Using the debugger, it looks like var buffer = new ArrayBuffer(value); results in buffer being an empty ArrayBuffer. The text string stored in value must be utf-8 encoded in order to be correctly converted to bytes, which can then by passed as an input to the crypto.subtle.digest() function.
Try changing:
var buffer = new ArrayBuffer(value);
to:
var buffer = new TextEncoder("utf-8").encode(value);
This creates a Uint8Array (as expected by crypto.subtle.digest()) consisting of the bytes resulting from utf-8 encoding the text string in 'value'. This should solve the problem and produce the result that you are expecting.
i'm using Web Crypto API. i'm getting from the encrypt/decrypt an ArrayBuffer.
to store the ArrayBuffer, i need to stringify it. i found this example for this job:
function ab2str(buf) {
return String.fromCharCode.apply(null, new Uint16Array(buf));
}
function str2ab(str) {
var buf = new ArrayBuffer(str.length*2); // 2 bytes for each char
var bufView = new Uint16Array(buf);
for (var i=0, strLen=str.length; i < strLen; i++) {
bufView[i] = str.charCodeAt(i);
}
return buf;
}
but i'm getting not the original string. abstract example workflow:
var encryptedArrayBuffer = webcryapto.encrypt("someLongString");
var encryptedString = ab2str(encryptedArrayBuffer);
now i get a string with chinese or japanese characters.
var decryptedArrayBuffer = webcryapto.decrypt(someKey);
var decryptedString = ab2str(encryptedString);
after conversion the depcrypted string isn't like the original. in my array of data some values are decrypted correctly. the others have chinese/japanese characters included like the encrypted value.
is there any good solution to get not unexpected characters?
UPDATE
i'm using "AES-CBC" of the web crypto examples above.
working value
plain = "{"Key":"Outbuildings#58dc9e89-cbf6-4b06-ae9d-3380803ae995","Value":"Sonstiges Nebengebäude"}"
encryptedAB = webcrypto.encrypt(plain)
encrypted = ab2str(encryptedAB)
encrypted => "鷨捍⩆ኅ읲☹많ᦞ㙝芾⟷㾌㴵꾂큹锩凉㚣䬶⁐薈Ⴞ舢ử揼߱泏넸붛蚔缍䌩턂煮铈氁覞⺛鱂髽ؠ읰픡忧㣑鎜ㆅ鍏ᾪ莍庉떹Ẋ昭婚篥.矧ㇴ⒕ࡹ텾᧫ᲈﺍ⮣䋅"
decryptedArrayBuffer = webcrypto.decrypt(encrypted)
decrypted = ab2str(decryptedArrayBuffer)
decrypted = > "{"Key":"Outbuildings#58dc9e89-cbf6-4b06-ae9d-3380803ae995","Value":"Sonstiges Nebengebäude"}"
after decrypting , i get my plain.
not working value
plainString = "{"Key": "Outbuildings#d24857bc-5dee-4236-835d-8e3b91567a91", "Value": "Werkstatt"}"
encryptedArrayBuffer = webcrypto.encrypt(plainString)
encrypted => ab2str(encryptedArrayBuffer )
encrypted = "鷨捍⩆ኅ읲☹많ᦞ㙝芾⟷㾌㴵꾂큹곙㤴njǃ⻲︽㙙郬쵸납餵逳䣊ᯗ퇟姛쏱阵巍旿柀⤏뙡뷇劺泴姲娯趱ៜ쪉轮댼롲ᾕ鱁ᬩ㩋䄅ᖯ苊脭䚛뮖ꡞಅ₨ፂ쑱眈盼갚⊙媌콠ᕥ䲵뺜왶輄繆緸䜁ꓳ镉⎇繆催ᥤⴸ㗻"
decryptedAB = webcrypto.decrypt(encrypted)
decrypted = ab2st(decryptedAB)
decrypted => "{"Key":"Outbuildings#d24∲姅�㉍猨씁�熢ᅍ攄稲짷业鯌㰸35d-иe3ꑢ專䫚︙绬ோᲬ㎂1","V偡lue":"Werkstatt"}"
in this example, the GUID and the word "Value" is destroyed, after ab2str(decryptedArrayBuffer). but it's not on all values the same corrupted characters. one part of values are ok, the others destroyed on different characters.
I want to process an image and make it secure by adding a watermark to it using transloadit. But the source of image I have is base64 encoded string rather than asking user to upload it to a form. Can I pass this base64 encoded string to form and process it to get watermark on it?
Any help is appreciated. Thanks!
It seems like you need to convert the base64 data uri to a Blob object, then manually set the blob as a parameter in FormData, as suggested in this SO question
function dataURItoBlob(dataURI) {
// convert base64/URLEncoded data component to raw binary data held in a string
var byteString;
if (dataURI.split(',')[0].indexOf('base64') >= 0)
byteString = atob(dataURI.split(',')[1]);
else
byteString = unescape(dataURI.split(',')[1]);
// separate out the mime component
var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
// write the bytes of the string to a typed array
var ia = new Uint8Array(byteString.length);
for (var i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
return new Blob([ia], {type:mimeString});
}
Then set it using:
var dataURL = canvas.toDataURL('image/jpeg', 0.5);
var blob = dataURItoBlob(dataURL);
var fd = new FormData(document.forms[0]);
fd.append("canvasImage", blob);
credit to #Stoive for the code
I have a bunch of hex values and I have to convert it into binary data before write them into a file.
I trasformed the hex string in an array of integers, then I convert each integer to a char:
// bytes contains the integers
str = String.fromCharCode.apply(String, bytes);
now I create the blob file and download it:
var blob = new Blob([str], {type: "application/octet-stream"});
saveAs(blob, "file.bin");
but something goes wrong: if I print the length of bytes and the length of str I have the same value (512), but the file contains 684 chars, and of course it isn't how I expect it.
So I have:
512 pairs of hex values ->
512 integers ->
512 chars ->
I save the file ->
684 chars inside the file.
What am I doing wrong? I even tried to add the charset to the blob file, ie:
var blob = new Blob([str], {type: "application/octet-stream;charset=UTF-8,"});
but with no success.
EDIT:
Original HEX:
Saved file:
Thanks to Andrey I found the solution:
I have to write in binary mode, so:
var ab = new ArrayBuffer(bytes.length); //bytes is the array with the integer
var ia = new Uint8Array(ab);
for (var i = 0; i < bytes.length; i++) {
ia[i] = bytes[i];
}
var blob = new Blob([ia], {type: "application/octet-stream"});
saveAs(blob, id + "_<?php echo $report['md5']; ?>.bin");
My web app receives data in the form of a base64 encoded string, which is decodes using atob, and stores via URL.createObjectURL(). This data is then downloaded via the right-click save-as dialog. The downloaded filed always matches the source file when the source file is ascii encoded. However this isn't the case when the source file is just plain binary data. A diff of a non ascii encoded downloaded file vs its source file appears to show that the downloaded file is UTF-8 encoded. How can this problem be fixed? Please note, I'm locked into using firefox 10.
Convert the string to a Arraybuffer and it should work. If there is any way that you can get the data into an array buffer directly without passing a sting that would be the best solution.
The following code is tested in FF10, and are using the now obsolete MozBlobBuilder.
fiddle
var str="",
idx, len,
buf, view, blobbuild, blob, url,
elem;
// create a test string
for (var idx = 0; idx < 256; ++idx) {
str += String.fromCharCode(idx);
}
// create a buffer
buf = new ArrayBuffer(str.length);
view = new Uint8Array(buf);
// convert string to buffer
for (idx = 0, len = str.length; idx < len; ++idx) {
view[idx] = str.charCodeAt(idx);
}
blobbuild = new MozBlobBuilder();
blobbuild.append(buf);
blob = blobbuild.getBlob('application/octet-stream');
url = URL.createObjectURL(blob);
elem = document.createElement('a');
elem.href = url;
elem.textContent = 'Test';
document.body.appendChild(elem);