How to pass encripted data pass by url in angular 8 - node.js

Tried to pass encripted data by url in angular 8 but not working because encripted data containing / so that url is not opening properly.So How to pass encripted data by url in angular 8.Please help anyone if know.
Can we encript the data without special chatacters.Is it possible?
Example: U2FsdGVkX18+ijuMYTf/b2jVWBRoAGWMJ+AnFlwodjE= this data have / so url will not open. How to resolve this issue.
Encription like this:
let encriptionData = CryptoJS.AES.encrypt("test#gmail.com", 'secret key 123').toString();
I am passing encripted data like this
var url = "http://localhost:4200/content/" + encriptionData;
router.module.ts:
{ path : 'content/:id' , component : contentComponent },
content.component.ts:
//url is http://localhost:4200/content/U2FsdGVkX18+ijuMYTf/b2jVWBRoAGWMJ+AnFlwodjE=
this._Activatedroute.paramMap.subscribe(params => {
var bytes = CryptoJS.AES.decrypt(params.get('id'), 'secret key 123');
this.decryptedMailid = bytes.toString(CryptoJS.enc.Utf8);
console.log(this.decryptedMailid);
});

You can encode your encrypted string, and then decode it before decrypting it.
let encryptedData = encodeURIComponent(CryptoJS.AES.encrypt("test#gmail.com", 'secret key 123').toString());
Now, instead of http://localhost:4200/content/U2FsdGVkX18+ijuMYTf/b2jVWBRoAGWMJ+AnFlwodjE=, your url will be http://localhost:4200/content/U2FsdGVkX18%2BijuMYTf%2Fb2jVWBRoAGWMJ%2BAnFlwodjE%3D
In content.component.ts, you do the following to reverse the operations:
this._Activatedroute.paramMap.subscribe(params => {
var bytes = CryptoJS.AES.decrypt(params.get('id'), 'secret key 123');
this.decryptedMailid = decodeURIComponent(bytes.toString(CryptoJS.enc.Utf8));
console.log(this.decryptedMailid);
});

Related

core.js:478 Uncaught Error: Malformed UTF-8 Data When Decrypting Url Query Param in Angular

I have a crypto encrypt and decrypt service below and I use it throughout my application to encrypt and decrypt localstorage items. While it works perfectly fine for the localstorage items, when I try to decrypt an encrypted object sent through queryparams, I get the following error:
core.js:478 Uncaught Error: Malformed UTF-8 data
my encrypt/decrypt service is:
export class AESEncryptDecryptService {
secretKey = 'My secret string';
constructor() { }
encrypt(value? : string) : string{
if(!isNil(value)) {
return CryptoJS.AES.encrypt(value, this.secretKey.trim()).toString();
}
}
decrypt(textToDecrypt?){
if(!isNil(textToDecrypt)) {
return CryptoJS.AES.decrypt(textToDecrypt, this.secretKey.trim()).toString(CryptoJS.enc.Utf8);
}
}
}
How I encrypt the object before I sent it:
const user= new User();
this.qrUrl = `${environment.someurl}` +'currentUser=' +this._AESEncryptDecryptService.encrypt(JSON.stringify(user).toString()).toString();
How I decrypt the object:
const url_string = window.location.href;
const url = new URL(url_string);
if(url.searchParams.get('user')) {
this.qrDevice = JSON.parse(this._AESEncryptDecryptService.decrypt(url.searchParams.get('user')));
}
I tried it without the string and by debugging. The same code works fine for other uses but gives this error on url query decrypt.
One thing I noticed is that the query string is replacing the + in the string with a space. How can I fix this and preserve the + sign? the expected and actual of the encrypted objects are posted below.
Expected after object parse from url:
U2FsdGVkX1+8y4FZ0cDq5ikapUndRA+tE5BAVqYPH9NnhBWeea1asYo5zCU80s/6FWKnFU8FghXv7JxPWwnPpJtCR+eXIGpiGBWq4gpq00PoeIuU2jPsDeifSu8aDrFr+D8abcdkIil5WmsHiND5TwVfWHhaBDSSlYMSXbiUXx9DQgRipEAtXXgMEO/r7G5wpuJ9ekEzUfkgXIO3eM/tP6dMu2iWZwbXTDvBZl93J8XZ259YRtIkRXgolSGS2t9yvQOn9I7fobRI1NSCIAftQtGdj/k9pu4B9reicnw9wiNR4dmp8+cpI/3TQSevhwp
Actual after object parse from url:
U2FsdGVkX1 8y4FZ0cDq5ikapUndRA tE5BAVqYPH9NnhBWeea1asYo5zCU80s/6FWKnFU8FghXv7JxPWwnPpJtCR eXIGpiGBWq4gpq00PoeIuU2jPsDeifSu8aDrFr D8abcdkIil5WmsHiND5TwVfWHhaBDSSlYMSXbiUXx9DQgRipEAtXXgMEO/r7G5wpuJ9ekEzUfkgXIO3eM/tP6dMu2iWZwbXTDvBZl93J8XZ259YRtIkRXgolSGS2t9yvQOn9I7fobRI1NSCIAftQtGdj/k9pu4B9reicnw9wiNR4dmp8 cpI/3TQSevhwp
Issue was resolved by changing the qrurl to the following:
this.qrUrl = `${environment.qrOrderURL}user=`+encodeURIComponent(this._AESEncryptDecryptService.encrypt(JSON.stringify(user)));

How to decrypt a value in frontend which is encrypted in the backend (nodejs)?

Backend developers have encrypted a value in nodejs using crypto module. The code is shown below:
const _encrypt = async function(text){
var cipher = crypto.createCipher('aes-256-cbc','123|a123123123123123#&12')
var crypted = cipher.update(text,'utf8','hex')
crypted += cipher.final('hex');
console.log("in generic function....encrpted val", crypted)
return crypted;
}
I need to decrypt this value in the front end (Angular). So I tried decrypting like below:
let bytes = CryptoJS.AES.decrypt("e0912c26238f29604f5998fa1fbc78f6",'123|a123123123123123#&12');
if(bytes.toString()){
let m = JSON.parse(bytes.toString(CryptoJS.enc.Utf8));
console.log("data ",m);
}
using hardcoded value. But Im getting Error: Malformed UTF-8 data error. Can anybody please tell me how to decrypt this in angular side?
This is a tricky enough one.. the crypto.createCipher function creates a key and IV from the password you provide (See the createCipher documentation for details).
This is implemented using the OpenSSL function EVP_BytesToKey.
A JavaScript implementation is available here: openssl-file.. we'll use this to get a key and IV from the password.
So there are two steps here:
Get a key and IV from your password.
Use these with Crypto.js to decode your encoded string.
Step 1: Get key and IV (Run in Node.js )
const EVP_BytesToKey = require('openssl-file').EVP_BytesToKey;
const result = EVP_BytesToKey(
'123|a123123123123123#&12',
null,
32,
'MD5',
16
);
console.log('key:', result.key.toString('hex'));
console.log('iv:', result.iv.toString('hex'));
Step 2: Decrypt string:
const encryptedValues = ['e0912c26238f29604f5998fa1fbc78f6', '0888e0558c3bce328cd7cda17e045769'];
// The results of putting the password '123|a123123123123123#&12' through EVP_BytesToKey
const key = '18bcd0b950de300fb873788958fde988fec9b478a936a3061575b16f79977d5b';
const IV = '2e11075e7b38fa20e192bc7089ccf32b';
for(let encrypted of encryptedValues) {
const decrypted = CryptoJS.AES.decrypt({ ciphertext: CryptoJS.enc.Hex.parse(encrypted) }, CryptoJS.enc.Hex.parse(key), {
iv: CryptoJS.enc.Hex.parse(IV),
mode: CryptoJS.mode.CBC
});
console.log('Ciphertext:', encrypted);
console.log('Plain text:', decrypted.toString(CryptoJS.enc.Utf8));
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9-1/crypto-js.min.js"></script>
Note that if you change the password you need to generate a new key and iv using EVP_BytesToKey.
I should note that createCipher is now deprecated, so use with caution. The same applies to EVP_BytesToKey.

Use nlapiRequestURL to make a request to a Service

How do you use nlapiRequestURL to make a request to a service? My attempt below is failing with the error: UNEXPECTED_ERROR (output from NetSuites script execution log).
My service is set to run without login and works correctly when I directly access it through a browser using its url. Its just the request through nlapiRequestURL thats failing.
Any idea what could be going wrong?
// This code executes in Account.Model.js (register function)
// I am using my own netsuite user credential here
var cred = {
email: "MY_NETSUITE_EMAIL"
, account: "EXXXXX" // My account id
, role: "3" // Administrator
, password: "MY_NETSUITE_PASSWORD"
};
var headers = {"User-Agent-x": "SuiteScript-Call",
"Authorization": "NLAuth nlauth_account=" + cred.account + ", nlauth_email=" + cred.email +
", nlauth_signature= " + cred.password + ", nlauth_role=" + cred.role,
"Content-Type": "application/json"};
var payload = {
type: 'is_email_valid'
, email: 'spt015#foo.com'
};
// A raw request to the service works fine:
// http://mywebsite.com/services/foo.ss?type=is_email_valid&email=spt015#foo.com
// Error occurs on next line
var response = nlapiRequestURL(url, payload, headers);
You are attempting to call a non-Netsuite url with Netsuite authentication headers. You do not need that unless for some reason of your own you have implemented NS-style authorization on your service.
nlapiRequestURL does not automatically format a payload into a query string. If your service takes a posted JSON body then you need to call JSON.stringify(payload) e.g
var response = nlapiRequestURL(url, JSON.stringify(payload), headers);
If your service needs a query string like in your example then you need to construct a query string and append it to your service url. e.g.
var qs = '';
for(var k in payload) qs += k +'='+ uriEncodeComponent(payload[k]) +'&';
var response = nlapRequestURL(url +'?'+ qs.slice(0,-1), null, headers);
I would suggest changing your nlapiRequestURL to a GET instead of POST, and add the parameters to the url instead. Your function call will look like this instead.
nlapiRequestURL(url, null, headers, "GET")

Can't get HMAC Authentication working with API

I'm trying to authenticate using HMAC with the LocalBitcoins API.
Here is the authentication written in Python:
message = str(nonce) + hmac_auth_key + relative_path + get_or_post_params_urlencoded
signature = hmac.new(hmac_auth_secret, msg=message, digestmod=hashlib.sha256).hexdigest().upper()
And the parameters to create the HMAC message:
Nonce. A 63 bit positive integer, for example unix timestamp as milliseconds.
HMAC authentication key. This is the first one of a key/secret pair.
Relative path, for example /api/wallet/.
GET or POST parameters in their URL encoded format, for example foo=bar&baz=quux.
Here is how I am building the HMAC:
var milliseconds = (new Date).getTime();
var key = config.key;
var secret = config.secret;
var nonce = milliseconds.toString()
var message = nonce + key + 'api/myself';
var hmac_digest = crypto.createHmac("sha256", secret).update(message).digest('hex').toUpperCase();
The signature is sent via 3 HTTP Headers. The options for the call to the api/myself method looks like such (using request):
{ url: 'https://localbitcoins.com/api/myself',
method: 'GET',
headers:
{ 'Apiauth-Key': 'my api key',
'Apiauth-Nonce': 1439925212276,
'Apiauth-Signature': 'the created signature' },
timeout: 5000 }
And the request:
var req = request.get(options, function(error, response, body) {
console.log(body);
});
But everytime I get the following error message:
{ error:
{ message: 'HMAC authentication key and signature was given, but they are invalid.',
error_code: 41 } }
I've tried lots of different combinations in testing but can't get anything to work. What am I missing?
It turns out that my path was wrong.
/path needed to be /path/, which I found out through working with a working Python implementation.
The package is up and running now here: https://github.com/mrmayfield/localbitcoins-node
I think that (new Date).getTime(); is not creating a 63 bit integer. Per Dr. Axel's post. JavaScript has 53 bit integers plus a sign.

How do I parse a data URL in Node?

I've got a data URL like this:
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...
What's the easiest way to get this as binary data (say, a Buffer) so I can write it to a file?
Put the data into a Buffer using the 'base64' encoding, then write this to a file:
var fs = require('fs');
var string = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==";
var regex = /^data:.+\/(.+);base64,(.*)$/;
var matches = string.match(regex);
var ext = matches[1];
var data = matches[2];
var buffer = Buffer.from(data, 'base64');
fs.writeFileSync('data.' + ext, buffer);
Try this
const dataUrl = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==";
const buffer = Buffer.from(dataUrl.split(",")[1], 'base64');
I also met such questions (parsing and validating data URL) recently and found the following workaround: https://gist.github.com/bgrins/6194623
I created 2 packages to make working with data URL easier in the code. Here they are:
https://github.com/killmenot/valid-data-url
https://github.com/killmenot/parse-data-url
Check out examples
I was looking into the sources of Node.js and stumbled upon this code that decodes a data URL into a Buffer. Although the function is not public and exclusively intended to parse encoded ES modules, it sheds light on aspects of data URLs that are apparently not considered by some other answers: the content of data URLs must not be base64 encoded and may be URL encoded, and it may even be unencoded.
Essentially, the Node.js logic boils down to something like the code below plus error handling:
const parsed = new URL(url);
const match = /^[^/]+\/[^,;]+(?:[^,]*?)(;base64)?,([\s\S]*)$/.exec(parsed.pathname);
const { 1: base64, 2: body } = match;
const buffer = Buffer.from(decodeURIComponent(body), base64 ? 'base64' : 'utf8');
This will correctly handle different encodings of a Javascript file with the content console.log("Node.js");:
data:text/javascript,console.log("Node.js");
data:text/javascript,console.log(%22Node.js%22)%3B
data:text/javascript;base64,Y29uc29sZS5sb2coIk5vZGUuanMiKTs=
The resulting buffer can be converted into a string if required with buffer.toString().
This method works for me
function dataURItoBlob(dataURI) {
// convert base64 to raw binary data held in a string
var data = dataURI.split(',')[1];
var byteString = Buffer.from(data, "base64");
// separate out the mime component
var mimeString = dataURI.split(",")[0].split(":")[1].split(";")[0];
// write the ArrayBuffer to a blob, and you're done
var blob = new Blob([byteString], { type: mimeString });
return blob;
}
to use
var uri = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==';
dataURItoBlob(uri)

Resources