Problem
I'm trying to create a simple trustless file sharing application. I'm using EasyRSA (https://github.com/paragonie/EasyRSA) to create a key-pair and then encrypt my data with the public key. I'm sending the private key to my JS wherein I'm using Node-RSA (https://github.com/rzcoder/node-rsa). Here, I try to decrypt using the previously created private key. But this happens:
Error
Uncaught Error: Error during decryption (probably incorrect key). Original error: Error: Incorrect data or key
at NodeRSA.module.exports.NodeRSA.$$decryptKey (drop.js:23265)
at NodeRSA.module.exports.NodeRSA.decrypt (drop.js:23213)
at window.onload (drop.js:22270)
My JS code looks something like this:
var NodeRSA = require('node-rsa');
window.onload = function() {
var key_val = $('#key').val();
var ciphertext = $('#encrypted').val();
var key = new NodeRSA();
key.importKey($('#key').val(), 'pkcs1');
var ciphertext_base = key.encrypt(ciphertext, 'base64');
var decrypted_base = key.decrypt(btoa(ciphertext));
console.log(decrypted);
}
I think this has got something to do with the incompatibility between the formats/key-sizes/algos used to create the keys. If someone could help me 'hack' this and make it work, I would be very grateful to you.
Related
I'm working on a project that uses an external API that is written in C#. In this API, I need to send some encrypted data while using their key that was provided when I started a session.
My project is built using NodeJS, so to do this encryption I am using the CryptoJS module. While talking with the API developer, he sent me a code showing how the encryption is made in C#. Here is the code with an example key and value to be encrypted.
TripleDESCryptoServiceProvider mDes = new TripleDESCryptoServiceProvider();
mDes.Key = Convert.FromBase64String("bv8czu/UPuZg6xNxnJAD/vRtbng9mQZX");
mDes.Mode = CipherMode.ECB;
mDes.Padding = PaddingMode.Zeros;
ICryptoTransform mDesEnc = mDes.CreateEncryptor();
byte[] data = Encoding.UTF8.GetBytes("1"); //value to encrypt
var crypto = Convert.ToBase64String(mDesEnc.TransformFinalBlock(data, 0, data.Length));
Console.WriteLine(crypto);
This results in the following encryption: 3EAaQjY2dgA=
As you can see in the code or running it, the encryption uses 3DES, mode ECB, Zero Padding and the key while in a byte array format has 24 bytes.
So I started to recreate this code in JavaScript and ended up with this:
var CryptoJS = require("crypto-js");
var encryptStringWith3DES = function(toEncrypt, key){
toEncrypt = "1";
key = "bv8czu/UPuZg6xNxnJAD/vRtbng9mQZX";
key = CryptoJS.enc.Utf8.parse(key);
console.log(toEncrypt + " " + key);
var encrypted = CryptoJS.TripleDES.encrypt(toEncrypt, key,{
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.ZeroPadding
}).toString();
console.log(encrypted);
}
And it results in the following encryption: dj1byXBV6ug=
I have searched for many answers and none worked. My suspicion is with how CryptoJS receives the key as a parameter and how the key and data are parsed.
Does any of you know how to make my JS code result in the same encrypted data as the C# one?
I am trying to use Forge.min.js encryption method to encrypt one of my key, the encryption look like this in Javascript
EncryptPassword: function (Password, exponent,modulus)
{
modulus = new forge.jsbn.BigInteger(modulus,16);
exponent = new forge.jsbn.BigInteger(exponent, 16);
var publicKey = forge.pki.setRsaPublicKey(modulus, exponent);
return publicKey.encrypt(Password);
}
This is the function that i used in forge.min.js. My problem is that i cant load the js file in c# console, whenever i load the Js file using the method below :
MSScriptControl.ScriptControlClass sc = new MSScriptControl.ScriptControlClass();
sc.Language = "javascript";
sc.AddCode(File.ReadAllText(#"C:\forge-min.js"));
when i load the forge-min.js file using the above method in c# console, it goes to exception with message "Expected Identifier". My question is is there a method to encrypt in c# that produce the same result. Or is there a method that is able to load forge-min.js
*Note: forge-min.js file is in here https://cdnjs.cloudflare.com/ajax/libs/forge/0.9.1/forge.min.js
EDIT
I found this:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays
Basically if I have something like this:
struct someStruct {
unsigned long id;
char username[16];
float amountDue;
};
on client side I can do:
var ws = new WebSocket("ws://URI");
ws.binaryType = "arraybuffer";
ws.onmessage = function (e) {
var buffer = e.data;
var data_view = new DataView(buffer);
// ... read the data into the buffer ...
var idView = data_view.getUint32(0);
var usernameView = data_view.getUint32(4);
var amountDueView = data_view.getFloat32(20);
};
The problem is that I want to convert them to normal Javascript objects (numbers, strings etc).
Original question
I would send data via websocket packed using a C struct, and unpack on browser using Javascript.
I know modules exists for node.js, but I can't find nothing client-side.
If you're familiar with Python struct, then you may like structjs. It's my attempt at porting Python struct to javascript. As it is, it's for Node, but a client port should be easy.
You won't have issues with alignment or padding (you can specify those explicitly though) for that structure, but you may need to indicate little-endian (by the '<' in the format string) if that's your flavour. You might do like so (I haven't tested this example in any way):
let struct = require("./struct") // Node specific, you need to wrap it.
let someStruct = struct('<I16sf') // This is your struct definition
let ws = new WebSocket("ws://URI");
ws.binaryType = "arraybuffer";
ws.onmessage = e => {
// Unpack using the structure definition. Unpack takes an ArrayBuffer.
let [id, username, amountDue] = someStruct.unpack(e.data);
// Use data...
};
Ok,
https://www.npmjs.com/package/c-struct looks like what you want.
Good luck!
Ok, after some researching, I finally decided this could not be a good idea:
https://justin.harmonize.fm/development/2013/04/28/a-slower-js-msgpack.html
Shortly: javascript is slow in decoding.
Probably it's just more simple to use JSON and Content-Encoding: gzip, if it does not slow down your web app.
for my website "moneyart.info" I want to generate ECC public and private keys with JavaScript library sjcl. I tried following code:
*
crypto_keys = sjcl.ecc.elGamal.generateKeys(256);
var public_key = crypto_keys.pub.get();
var secret_key = crypto_keys.sec.get();
var public_key_hex = sjcl.codec.hex.fromBits(public_key.x) + sjcl.codec.hex.fromBits(public_key.y);
var secret_key_hex = sjcl.codec.hex.fromBits(secret_key);
alert(secret_key_hex);*
I get the error message:
TypeError: sjcl.ecc is undefined
I think I have to construct a class with new, but I dont know which one.
I found the mistake: ecc.elGamal is no standard sjcl function. I have to compile the sjcl.js file manually with additional functionality included. blog.peramid.es
I am trying to verify an RSA signature in Javascript but I can't seem to get it to work. I think I have to do something with my key and signatures but I am very confused.
Here is a link to this library
var publicKey = "MIIBIjBNBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoPNkJzHqbY/6mAjJwb4zUbOiOjvmg3b8fvydYdGXdv04r6vzgn/FD5NPJM7bojAxi6sZ8vV+fYVIQey6HnrLSsdU/QXhT3p22a+kB4ym8SbKsOy2fWqL950nZCPYW/DC9txHy+ceFuKMAarFWAMJRe+MaVIbDIAAi8tMNjZ204GkmqveyAeA6JppzthAuiX69H8Zb3Hbs49CHNwLnSpKz5HBTfcgWqHkar2HlEFccvWC++Kq47MIkEcKScS/oneDb/TiL5ClOas1gMxfwiVtkFI6zNxxJOJDSTlY66oHCVCfTruk2pQbtOtwJEGrOwq6B536QL/EkeEKMgiqlpZJbQIDAQAB";
var stringToVerify = "aaa";
var signature = "hXyRmdQOCiVBNgDdGtiWF/gJwIk0Hs+MZtfEU4sFMEu05xsBjR9uymOJ/8FwhKCB0p+Kc1jqtsZxQqtxC0Du2EYyvjs0j5bbU9ZugZw0+9VHqKm0UA23djmZ1MT6nXt2ZEUEsS0La9yrfEnig/swAku1fQorsxG5FK5GFRjaacNIF+O0GOr0cbzEvlaAof6T6JFMueIw/iZykivs8XohSlghdPzoNmVueY9JF1XbtHZayau17jGhFTbeNNxbDBanPo593eZdgi5aTZMYHbxHx87cfU1sE5cjSioPQLsG9cQwVaWrrZa9BnB8IhR8Rv0NdRXYNTcVhc+sVHJN/QghNQ==";
var KJUR = require("cloud/jsrsasign-4.7.0/npm/lib/jsrsasign.js");
var verifier = new KJUR.crypto.Signature({alg: "SHA1withRSA", prov: "cryptojs/jsrsa"});
verifier.init(publicKey);
verifier.updateString(stringToVerify);
console.log(verifier.verify(signature));
Thanks in advance
You need to base 64 decode both the public key and the signature. They key and signature should then be re-encoded as hexadecimals. Then you hopefully should be able to use this method to generate a public RSAKey object.
I'm saying hopefully, as the the API description is just horrible. Personally I would not recommend to use such an API.