Not returning anything base64 decode - javascript

I try to decrypt a file with crypto-js (in this file there is a long string of encrypted base64).
but I don't get anything back the file is empty and the log too.
const fs = require("fs");
const CryptoJS = require("crypto-js");
fs.writeFile("2pac.txt", decode(), (err) => {
if (err) throw err;
// success case, the file was saved
console.log("Lyric saved!");
});
function decode() {
// INIT
const encoded = fs.readFileSync("./base64.txt", { encoding: "base64" });
// PROCESS
const decoded = CryptoJS.enc.Utf8.stringify(encoded); // decode encodedWord via Utf8.stringify() '75322541'
console.log(decoded);
return decoded;
}
In the console.log I get the test but I don't get anything(even undefined).

Replace this line:
const decoded = CryptoJS.enc.Utf8.stringify(encoded);
with:
const decoded = CryptoJS.enc.Utf8.stringify(CryptoJS.enc.Base64.parse(encoded));
EDIT:
Reading base64 data from file is another problem. The data imported from the file with the encoding option set to base64 does guarantee a string instead of a buffer but it expects the input to be utf-8 encoding the base64 string again (double encoding).
To fix this, change the following:
const encoded = fs.readFileSync("./base64.txt", { encoding: "base64" });
to:
const encoded = fs.readFileSync("./base64.txt").toString();

Related

Base64 to Image File Convertion in JS

I am working on a project where I have to upload an image as form data along with other text fields. I have my file in Base64 string at first, then I convert it into a file before uploading it to the server.
const data = await fetch(base64String);
const blob = await data.blob();
const file = await new File([blob], 'avatar', { type: 'image/png' });
I logged the base64String in the client side before uploading it to the server. Then I upload file to the server as a File. Before saving it to MongoDB when I log it as a base64 string again in the server side, I see my string is not the same as before. I feel like while converting the base64 to file in the client side I am doing something wrong. Help me out please.
I have figured out my problem. When I take image file input from my computer I get a base64 string like below -
dataimage/jpegbase64/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAA...
But, when I convert it back into a file it expects a string like below -
/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAA....
So, basically, I had to trim the string accordingly to match the expected format and wrote a base64 to file conversion function following this answer.
Here is my function to convert a base64 string to an image file
export function getFileFromBase64(string64:string, fileName:string) {
const trimmedString = string64.replace('dataimage/jpegbase64', '');
const imageContent = atob(trimmedString);
const buffer = new ArrayBuffer(imageContent.length);
const view = new Uint8Array(buffer);
for (let n = 0; n < imageContent.length; n++) {
view[n] = imageContent.charCodeAt(n);
}
const type = 'image/jpeg';
const blob = new Blob([buffer], { type });
return new File([blob], fileName, { lastModified: new Date().getTime(), type });
}

PublicKeyCredential not possible to serialize

I am implementing FIDO2(WebAuthn) in a Angular application.
I have gotten the PublicKeyCredentialCreationOptions object and seccessfullt register.
But after calling
let response = await navigator.credentials.create({'publicKey': myPublicKeyCredentialCreationOption })
I try to send the response to the server.. But this fails.
When I tried to look at the object in the browser using
console.log(JSON.stringify(response))
I get
{}
as output (?..) but when doing
console.log(response)
I get a object with values in the console...
How should the object get serialized to send to the server?
PublicKeyCredential objects contains ArrayBuffer objects that cannot be serialized as JSON. You could base64 encode these values in your Angular app and decode on the server to get the same byte array back. A helper library to do exactly that for WebAuthn exists: https://github.com/github/webauthn-json
Here's a very simple example for anyone who needs it:
function bufferToBase64url (buffer) {
// modified from https://github.com/github/webauthn-json/blob/main/src/webauthn-json/base64url.ts
const byteView = new Uint8Array(buffer);
let str = "";
for (const charCode of byteView) {
str += String.fromCharCode(charCode);
}
// Binary string to base64
const base64String = btoa(str);
// Base64 to base64url
// We assume that the base64url string is well-formed.
const base64urlString = base64String.replace(/\+/g, "-").replace(
/\//g,
"_",
).replace(/=/g, "");
return base64urlString;
}
...
create publicKeyCredentialCreationOptions
...
navigator.credentials.create({
publicKey: publicKeyCredentialCreationOptions
}).then(credential => {
// credential created
// console.log(credential); <-- check what is output to see what you need to call bufferToBase64url(credential.<...>) on down below
// convert credential to json serializeable
const serializeable = {
authenticatorAttachment: credential.authenticatorAttachment,
id: credential.id,
rawId: bufferToBase64url(credential.rawId),
response: {
attestationObject: bufferToBase64url(credential.response.attestationObject),
clientDataJSON: bufferToBase64url(credential.response.clientDataJSON)
},
type: credential.type
};
const serialized = JSON.stringify(serializeable);
console.log(serialized);
}).catch(err => {
// an error occurred
console.error(err);
});

How do I readFileSync audio as a string and then writeFileSync it back as audio?

I have the following:
const fileAsString = fs.readFileSync('speech.mp3', { encoding: 'utf-8' })
const encryptedString = encrypt(fileAsString)
const decryptedString = decrypt(encryptedString)
console.log(fileAsString === decryptedString) // this returns true
fs.writeFileSync('speech_copy.mp3', decryptedString, { encoding: 'utf-8' })
speech_copy.mp3 is created but it's no longer playable because I have messed up its encoding.
What am I doing wrong in the process? The only reason I'm originally reading the file using { encoding: 'utf-8' } is so that I may encrypt it and then decrypt it again. Should I use a different encoding when I write it back as a new file?
Using a base64 representation of the binary data is usually a better way:
const fs = require('fs');
// binary -> base64
const fileAsString = fs.readFileSync('speech.mp3').toString('base64');
const encryptedString = encrypt(fileAsString);
const decryptedString = decrypt(encryptedString);
// base64 -> binary
fs.writeFileSync('speech_copy.mp3', Buffer.from(decryptedString , 'base64'));

how to decode base64 to image in Nodejs?

I'm sending an image encoded as base64 through sockets and decoding is not working. The file that must contain the new image is written as base64 instead of a jpg file.
encoding socket:
function encode_base64(filename) {
fs.readFile(path.join(__dirname, filename), function (error, data) {
if (error) {
throw error;
} else {
console.log(data);
var dataBase64 = data.toString('base64');
console.log(dataBase64);
client.write(dataBase64);
}
});
}
rl.on('line', (data) => {
encode_base64('../image.jpg')
})
decoding socket:
function base64_decode(base64str, file) {
var bitmap = new Buffer(base64str, 'base64');
fs.writeFileSync(file, bitmap);
console.log('****** File created from base64 encoded string ******');
}
client.on('data', (data) => {
base64_decode(data,'copy.jpg')
});
// the first few characters in the new file
//k1NRWuGwBGJpmHDTI9VcgOcRgIT0ftMsldCjFJ43whvppjV48NGq3eeOIeeur
Change encode function like below. Also, keep in mind new Buffer() has been deprecated so use Buffer.from() method.
function encode_base64(filename) {
fs.readFile(path.join(__dirname, filename), function (error, data) {
if (error) {
throw error;
} else {
//console.log(data);
var dataBase64 = Buffer.from(data).toString('base64');
console.log(dataBase64);
client.write(dataBase64);
}
});
}
And decode as Below :
function base64_decode(base64Image, file) {
fs.writeFileSync(file,base64Image);
console.log('******** File created from base64 encoded string ********');
}
client.on('data', (data) => {
base64_decode(data,'copy.jpg')
});
You can decode the base64 image using following method .
EDITED
To strip off the header
let base64String = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgA'; // Not a real image
// Remove header
let base64Image = base64String.split(';base64,').pop();
To write to a file
import fs from 'fs';
fs.writeFile('image.png', base64Image, {encoding: 'base64'}, function(err) {
console.log('File created');
});
Note :- Don’t forget the {encoding: 'base64'} here and you will be good to go.
You can use a Buffer.from to decode the Base64, and write it to a file using fs.writeFileSync
const { writeFileSync } = require("fs")
const base64 = "iVBORw0KGgoA..."
const image = Buffer.from(base64, "base64")
writeFileSync("image.png", image)
If you have the Base64 string inside a file, you need to decode it into string first, like:
const { writeFileSync, readFileSync } = require("fs")
const base64 = readFileSync(path, "ascii")
const image = Buffer.from(base64, "base64")
writeFileSync("image.png", image)
It seems that the decoding function base64_decode gets the data as a buffer.
Thus, the encoding argument in new Buffer(base64str, 'base64') is ignored.
(Compare the docs of Buffer.from(buffer) vs Buffer.from(string[, encoding])).
I suggest to convert to a string first
function base64_decode(base64str, file) {
var bitmap = new Buffer(base64str.toString(), 'base64');
fs.writeFileSync(file, bitmap);
console.log('******** File created from base64 encoded string ********');
}

Node.js - assign writable stream to a variable

As in below code, I can write base64 encoded stream into a file but I want to assign the base64 encoded string to a variable rather than creating a file so that I can use it for the purpose I want. How can I assign response.pipe(base64.encode()); to a variable as base64 encoded string ? I am using base64-stream to encode incoming stream.
const request = xero.call('GET', `/Invoices/${invoiceId}`);
request.setHeader('Accept', 'application/pdf');
request.on('response', async (response) => {
const data = response.pipe(base64.encode());
const file = fs.createWriteStream(`${invoiceId}.txt`);
data.pipe(file);
});
request.end();
To store the contents of the stream as a string you need to concatenate the base64 stream and then store that buffer as a variable. For that I like to use concat-stream.
keep the stream around with const data = response.pipe(base64.encode());
but then
data.pipe(concat(buf => {
const str = buf.toString('base64')
})

Categories

Resources