Html textarea changing the value of a encoded javascript string - javascript

I'm working on this Encryption Cipher using CryptoJS for people who want to encrypt their messages. Unfortunately, I've run into a problem decrypting any messages that is encrypted using "NoPadding" padding. After hours and hours of testing the program for bugs, I finally found out what the problem was. I turns out that, when I append the encrypted javascript string into the HTML textarea, it changed the value of the string. Therefore, when I tried to decrypt the value from the textarea, it didn't work.
<textarea id="textarea"></textarea>
<button onclick="encrypting_without_textarea()">encrypting without textarea</button>
<button onclick="encrypting_with_textarea()">encrypting with textarea</button>
HTML
function encrypting_without_textarea(){
var textarea_element = document.getElementById("textarea");
var encryptionKey = "fkjasdlfkdsanfknlasknflsjkanflnasjkfnjknskjnfnlsnf";
var key = CryptoJS.enc.Hex.stringify(encryptionKey);
var value = "Multi-stability is the tendency of ambiguous perceptual experiences to move unstably back and forth between alternative interpretations. Some objects can be perceived in more than one way. An example from below in the section of figure/ground.";
var paddingObject = CryptoJS.pad.NoPadding;
var encrypted = CryptoJS.AES.encrypt(value, key, {mode:CryptoJS.mode.ECB, padding:paddingObject});
var decrypted = CryptoJS.AES.decrypt(encrypted, key, {mode:CryptoJS.mode.ECB, padding:paddingObject});
var msg = decrypted.toString(CryptoJS.enc.Utf8);
alert(msg);
}
The one above is decrypted straight from the encrypted message and it works, and the one below is decrypted with the value from from the textarea but it returns an error.
function encrypting_with_textarea(){
var textarea_element = document.getElementById("textarea");
var encryptionKey = "fkjasdlfkdsanfknlasknflsjkanflnasjkfnjknskjnfnlsnf";
var key = CryptoJS.enc.Hex.stringify(encryptionKey);
var value = "Multi-stability is the tendency of ambiguous perceptual experiences to move unstably back and forth between alternative interpretations. Some objects can be perceived in more than one way. An example from below in the section of figure/ground.";
var paddingObject = CryptoJS.pad.NoPadding;
var encrypted = CryptoJS.AES.encrypt(value, key, {mode:CryptoJS.mode.ECB, padding:paddingObject});
textarea_element.value = encrypted;
var decrypted = CryptoJS.AES.decrypt(textarea_element.value, key, {mode:CryptoJS.mode.ECB, padding:paddingObject});
var msg = decrypted.toString(CryptoJS.enc.Utf8);
alert(msg);
//Error: Malformed UTF-8 data
}
Here is the plnkr link. I understand that the value append to the textarea has change, but how? And, how do I change/encode the string so that the code can be display in the textarea and copy so that the message can be paste/decode with out it being corrupted. I'm open to any solutions, simpler the better?

Related

Encrypting With CryptoJS

I am trying to use the CryptoJS library to get the same value as I'm getting from an encryption tool, but I'm not able to get the same encrypted value.
Result using encryption tool:
Base64 Encoded Key: SisBCd6mVzPzZP7cpl/HvjqdkCpnujnJKUu8iosq/Yc=
Value to Encrypt: 55554444
Encrypted (ECB) Base64 Encoded Value: MLnK8JOyp+J4CoaqcWTAnW==
Here is my code where I'm trying to get that same result:
var data = '55554444'
var key = 'SisBCd6mVzPzZP7cpl/HvjqdkCpnujnJKUu8iosq/Yc='
// encrypt with key
var encrypted_ecb = CryptoJS.AES.encrypt(data, key, {mode: CryptoJS.mode.ECB});
console.log('encrypted_ecb: ', encrypted_ecb.toString())
// to base64
var rawStr = encrypted_ecb;
var wordArray = CryptoJS.enc.Utf8.parse(rawStr);
var base64_ecb = CryptoJS.enc.Base64.stringify(wordArray);
console.log('encrypted_base64_ecb: ', base64_ecb);
// Console Result:
// encrypted_ecb: U2FsdGVkX196PQg/s6RPQr3V9GEjf/WP7qRXxVh5GEU=
// encrypted_base64_ecb: VTJGc2RHVmtYMTk2UFFnL3M2UlBRcjNWOUdFamYvV1A3cVJYeFZoNUdFVT0=
As you can see I am getting the result I get is far different than the result I'm getting with the tool. Can anyone point me in the right direction?
Thank you!
You'll need to parse the key as well. Change the following line
var key = 'SisBCd6mVzPzZP7cpl/HvjqdkCpnujnJKUu8iosq/Yc='
to
var key = CryptoJS.enc.Base64.parse('SisBCd6mVzPzZP7cpl/HvjqdkCpnujnJKUu8iosq/Yc=');

JSON.parse() - SyntaxError: Expected end of stream at char 2

In my project, I have written google spreadsheet script to decipher encrypted cell content using sjcl. But I failed.
function encryptCell() {
var masterKey = Browser.inputBox('Enter masterKey');
var spreadSheet = SpreadsheetApp.getActiveSpreadsheet();
var cell = spreadSheet.getActiveSheet().getActiveCell();
var input = cell.getValue();
var encJson = sjcl.encrypt(masterKey, input);
/*
{"iv":"4psT+LTIh/aT7WWv7Ye7qw==","v":1,"iter":1000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"PjSOiia9TCM=","ct":"3hwmBbwQ7y/fsjk="}
*/
var encStr = JSON.stringify(encJson);
/*
"{\"iv\":\"4psT+LTIh/aT7WWv7Ye7qw==\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"PjSOiia9TCM=\",\"ct\":\"3hwmBbwQ7y/fsjk=\"}"
*/
var encB64 = Utilities.base64Encode(encStr);
Browser.msgBox(encB64);
var rencStr = Utilities.base64Decode(encB64);
/*
34,123,92,34,105,118,92,34,58,92,34,52,112,115,84,43,76,84,73,104,47,97,84,55,87,87,118,55,89,101,55,113,119,61,61,92,34,44,92,34,118,92,34,58,49,44,92,34,105,116,101,114,92,34,58,49,48,48,48,44,92,34,107,115,92,34,58,49,50,56,44,92,34,116,115,92,34,58,54,52,44,92,34,109,111,100,101,92,34,58,92,34,99,99,109,92,34,44,92,34,97,100,97,116,97,92,34,58,92,34,92,34,44,92,34,99,105,112,104,101,114,92,34,58,92,34,97,101,115,92,34,44,92,34,115,97,108,116,92,34,58,92,34,80,106,83,79,105,105,97,57,84,67,77,61,92,34,44,92,34,99,116,92,34,58,92,34,51,104,119,109,66,98,119,81,55,121,47,102,115,106,107,61,92,34,125,34
*/
var rencJson = JSON.parse(rencStr);
var rinput = sjcl.decrypt(masterKey, rencJson);
Browser.msgBox(rinput);
}
Encryption is fine, which I can decrypt using this tool. Something is wrong with JSON.parse().
var rencStr = Utilities.base64Decode(encB64);
/*
34,123,92,34,105,118,92,34,58,92,34,52,112,115,84,43,76,84,73,104,47,97,84,55,87,87,118,55,89,101,55,113,119,61,61,92,34,44,92,34,118,92,34,58,49,44,92,34,105,116,101,114,92,34,58,49,48,48,48,44,92,34,107,115,92,34,58,49,50,56,44,92,34,116,115,92,34,58,54,52,44,92,34,109,111,100,101,92,34,58,92,34,99,99,109,92,34,44,92,34,97,100,97,116,97,92,34,58,92,34,92,34,44,92,34,99,105,112,104,101,114,92,34,58,92,34,97,101,115,92,34,44,92,34,115,97,108,116,92,34,58,92,34,80,106,83,79,105,105,97,57,84,67,77,61,92,34,44,92,34,99,116,92,34,58,92,34,51,104,119,109,66,98,119,81,55,121,47,102,115,106,107,61,92,34,125,34
*/
If you take a look, that's not JSON. did you possibly miss the JSON.stringify(); step for that one?
You can't parse it if it's not JSON.
When decoding with Utilities.base64Decode() you have one extra step to follow if you want to get a string back. If you look at the Google Scripts reference it says that base64Decode returns a byte array and not a string. Looking at your code, your decode returns
var rencStr = Utilities.base64Decode(encB64);
/*34,123,92,34,105,118,92,34,58,92,34,52,112,115,84,43,76,84,73,104,47,97,84...*/
which is a numeric representation of your string in Unicode. If you run your return value through Utilities.newBlob(rencStr).getDataAsString() as the reference recommends, you will have your JSON that you can parse back into your encrypted string.

Encrypt/decrypt with two different keys

My code
I'm encrypting a string with two different keys with CryptoJS:
var password = "testpassword";
var serverkey = "randomkey";
var text = document.getElementById("new_note").value;
var encrypted1 = CryptoJS.AES.encrypt(text, password);
encrypted1 = encrypted1.toString();
var encrypted = CryptoJS.AES.encrypt(encrypted1,serverkey);
And trying to decrypt it with this code:
var password = "testpassword";
var serverkey = "randomkey";
var encrypted_text = localStorage.getItem("encrypted");
var decrypted1 = CryptoJS.AES.decrypt(encrypted_text,serverkey);
decrypted1 = decrypted.toString();
var decrypted = CryptoJS.AES.decrypt(decrypted1,password);
decrypted = decrypted.toString(CryptoJS.enc.Utf8);
document.getElementById("decrypted").innerHTML = decrypted;
What isn't working
While the encryption seems to work fine, when I try to convert decrypted1 to a string in order to decrypt it the second time, I get Cannot read property 'toString' of undefined on the chrome console. This should mean that the first decryption process returns an empty string.
My question
How can I fix this problem?
There is a typo in your variable names. Check where you define decrypted and where you use it. You meant to use decrypted1.
Additionally, you have a problem with the encoding. The first decrypted1.toString(); will encode the string into Hex, but earlier you called encrypted1.toString(); which does not encode to Hex, but a special Base64 encoding (OpenSSL compatible). You will need to encode to UTF-8 in order to get to the same encoding that you had before during encryption.
Here is the working code:
document.getElementById("enc_button").onclick = function(){
var password = "testpassword";
var serverkey = "randomkey";
var text = document.getElementById("new_note").value;
var encrypted1 = CryptoJS.AES.encrypt(text, password);
encrypted1 = encrypted1.toString();
var encrypted = CryptoJS.AES.encrypt(encrypted1, serverkey);
var decrypted1 = CryptoJS.AES.decrypt(encrypted,serverkey);
decrypted1 = decrypted1.toString(CryptoJS.enc.Utf8);
var decrypted = CryptoJS.AES.decrypt(decrypted1,password);
decrypted = decrypted.toString(CryptoJS.enc.Utf8);
document.getElementById("decrypted").innerHTML = decrypted;
}
<script src="https://cdn.rawgit.com/CryptoStore/crypto-js/3.1.2/build/rollups/aes.js"></script>
<div id="decrypted">Please wait...</div>
<div>
Insert new note:
<input type="text" id="new_note">
<input type="button" id="enc_button" value="Encrypt & Decrypt">
</div>
It looks like decripted IS empty.
you have initialized decripted1
var decrypted1 = CryptoJS.AES.decrypt(encrypted_text,serverkey);
and then tryed to "toString()" the uninitialized decrypted var
decrypted1 = decrypted.toString();
Although I think you don't need this line... (?).

combined RC4 RSA encrypt/decrypt for long messages Javascript

NOTE: Yes, I understand there is a lot of code in this message, but you do encourage us to show prior research and how we've been trying.
Let me preface this by saying, I am not interested in the security of this function. All I want is to encrypt and decrypt arbitrarily long messages using RSA. Usually to do this, the message is encrypted using a block cipher (such as AES) and encrypting the key with the RSA cipher. However, I am just trying to find the easiest way to encrypt/decrypt long messages, irregardless of security. Hence why I am using RC4 in place of the block cipher.
Now, I can encrypt properly using the following code:
function encryptLong(signedCert, msg) {
var key256Bits = CryptoJS.SHA256("password");
var ciphertext = CryptoJS.RC4.encrypt(msg, key256Bits);
key = new RSAKey();
var m = CryptoJS.SHA256("password").toString(CryptoJS.enc.Hex);
m = new BigInteger(m, 16);
key.setPublic(signedCert.msg.subject.pk.n, signedCert.msg.subject.pk.e);
var ctxt = key.doPublic(m).toString(16);
var cipherstring = ciphertext + ":" + ctxt;
var obj = { "type": "CTXT-LONG", "encrypted": cipherstring };
return JSON.stringify(obj);
}
The message and the key are encrypted properly. I tested them individually using these functions.
function encryptRSA(signedCert, msg) {
//create a new RSA key object
var key = new RSAKey();
//convert ASCII message to hex
var m = asciiToHex(msg);
// create new BigInterger from m
m = new BigInteger(m, 16);
// set the values for the public key
key.setPublic(signedCert.msg.subject.pk.n, signedCert.msg.subject.pk.e);
// compute the RSA public key operation, and convert to a hex value
var ctxt = key.doPublic(m).toString(16);
//enter ctxt into the JSON obj
var obj = { "type": "CTXT-SHORT", "c": ctxt };
return JSON.stringify(obj);
}
And...
function encryptRSA(password, message) {
var key256Bits = CryptoJS.SHA256(password);
var ciphertext = CryptoJS.RC4.encrypt(CryptoJS.enc.Utf8.parse(message), key256Bits);
return ciphertext;
}
Now, here is our decryption code:
function decryptLong(sk, ctxt) {
key = new RSAKey();
encryptedStuff = JSON.stringify(ctxt.encrypted);
log(encryptedStuff);
splitEncryptedstuff = encryptedStuff.split(":");
rsaencryption = splitEncryptedstuff[1];
log(rsaencryption);
rc4encryption = splitEncryptedstuff[0];
log(rc4encryption);
c = new BigInteger(rsaencryption, 16);
key.setPrivate(sk.n, sk.e, sk.d);
var key256Bits = key.doPrivate(c).toString(16);
log(key256Bits);
// RC4 decryption
var message = CryptoJS.RC4.decrypt(rc4encryption, key224Bits);
// var ptxt = CryptoJS.enc.Utf8.stringify(message);
// log(ptxt);
return CryptoJS.enc.Utf8.stringify(message);
}
This code doesn't decrypt properly, but I know parts of it work. For example, where I have
log(key356Bits);
it returns the key exactly. So I know that at least the RSA decryption works. What I don't understand is, I followed the decryption function that I have exactly. Which is as follows.
function decryptRC4(password, ciphertext) {
var key256Bits = CryptoJS.SHA256(password);
var message = CryptoJS.RC4.decrypt(ciphertext, key256Bits);
return CryptoJS.enc.Utf8.stringify(message);
}
Well not exactly, I don't have to take the Hash of the password to get the key, as I already have the key. But, I still don't understand what is not working. When we decrypt our ciphertext using this individual function, the plaintext is correct.
Any assistance in this matter would be greatly appreciated.
Knowing my luck, it's probably just something annoying like it's in the wrong encoding type thing.

how to get Hmac code with javascript

I can get a hmac sing using Python as following:
import hmac, base64, hashlib
def make_sign():
hash_data = "data"
secret = "this is secret"
sha512 = hashlib.sha512
hmac_obj = hmac.new(secret, hash_data, sha512)
str_hash = hmac_obj.digest()
sign = base64.b64encode(str_hash)
hex_hash = hmac_obj.hexdigest()
hex_sign = base64.b64encode(hex_hash)
print "correct_sign:",sign
print "hex_digest_sign:",hex_sign
make_sign()
output:
correct_sign: Lg4pXNCIpitNQt2DLU19qWb+FxdsYZlK4LLncfkTzSidrYoFJLNolUziRqh09B5HyRdCTEP7enZp6/Te34FK1g==
hex_digest_sign: MmUwZTI5NWNkMDg4YTYyYjRkNDJkZDgzMmQ0ZDdkYTk2NmZlMTcxNzZjNjE5OTRhZTBiMmU3NzFmOTEzY2QyODlkYWQ4YTA1MjRiMzY4OTU0Y2UyNDZhODc0ZjQxZTQ3YzkxNzQyNGM0M2ZiN2E3NjY5ZWJmNGRlZGY4MTRhZDY=
but with js, I can get hex_digest_sign, but I need to get correct_sign for web request.
function make_request() {
hash_data = "data"
secret = "this is secret"
hmac = hmac_512(hash_data, secret)
var sign = $.base64.encode(hmac),
console.log("js_sign="+sign);
}
function hmac_512(message, secret) {
var hmac = CryptoJS.algo.HMAC.create(CryptoJS.algo.SHA512, secret);
hmac.update(message);
var hash = hmac.finalize();
return hash;
}
js output:
js_sign="MmUwZTI5NWNkMDg4YTYyYjRkNDJkZDgzMmQ0ZDdkYTk2NmZlMTcxNzZjNjE5OTRhZTBiMmU3NzFmOTEzY2QyODlkYWQ4YTA1MjRiMzY4OTU0Y2UyNDZhODc0ZjQxZTQ3YzkxNzQyNGM0M2ZiN2E3NjY5ZWJmNGRlZGY4MTRhZDY="
the correct sign is correct_sign: Lg4pXNCIpitNQt2DLU19qWb+FxdsYZlK4LLncfkTzSidrYoFJLNolUziRqh09B5HyRdCTEP7enZp6/Te34FK1g==
how to get it in js?
I suspect that you are running into trouble with types and encoding. According to the CryptoJS source, the iterative hashing style that you are using returns a WordArray once you call finalize().
With that, once you go to print the results, you are printing the contents of the WordArray.
The purpose for itterative hashing is typically if you have a large input, you can break it into chunks to work on one piece at a time. Try the below edit I made that removes this as it does not look like you need to iterate.
function hmac_512(message, secret) {
var newHMAC = CryptoJS.HmacSHA256(message, secret);
return newHMAC;
}
The above will simply return the HMAC in string form which, once Base64 encoded, should match the result you see in Python.
Hope this helps!

Categories