Browser encrypting Server decrypting - javascript

In the browser on the client I encrypt a rand_key variable using jsencrypt.js and a public key.
The encrypted key is send via the body in a mail to the server. (This is the only way within my reach given the IT structure.)
In my browser I have:
<!DOCTYPE html>
<html lang="en">
<head>
<script type="application/javascript" src="jsencrypt.js"></script>
</head>
<body>
<script>
var pubkey = "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBALDjeFwFNhMCjMwcRVVKG1VvfsntEVPR3lNTujJnNk1+iSqZ4Tl5Lwq9GbwO+qlYVwXHNmeqG7rkEhL9uyDIZVECAwEAAQ=="
var rand_key = 'vpeq91mckhntgldi';
// Encrypt rand_key
var encrypt = new JSEncrypt();
//console.log('encrypt obj', encrypt);
encrypt.setPublicKey(pubkey);
var encrypted_rand_key = encrypt.encrypt(rand_key, 'base64');
console.log('encrypted_rand_key', encrypted_rand_key);
</script>
</body>
</html>
On my PC running node (where I receive the email):
var CryptoJS = require("crypto-js");
// encrypted string copied from browser console
var encrypted = 'IuRaUfDHDIJsO0JZbEj7RS/1Sw0iSZPB267MN9lmF5Fn/kuMMRyKlAjplwvUJ9qvirajOcAQNnRZs9A+gVcWLQ=='
IuRaUfDHDIJsO0JZbEj7RS/1Sw0iSZPB267MN9lmF5Fn/kuMMRyKlAjplwvUJ9qvirajOcAQNnRZs9A+gVcWLQ==
var key_pri = new NodeRSA('-----BEGIN RSA PRIVATE KEY-----MIIBPAIBAAJBALDjeFwFNhMCjMwcRVVKG1VvfsntEVPR3lNTujJnNk1+iSqZ4Tl5Lwq9GbwO+qlYVwXHNmeqG7rkEhL9uyDIZVECAwEAAQJBAIS8vYX4FyLex/8mu9SLvsU23KL0dgs7MqW+77uA/hvZt5eb/C0EfUekap3LBuAF3XqVkOwIjsDyj74adrB6J1ECIQDfxT74mqu+xZjdlrfNZcchu/MrrW631aMF4rsRZccTbQIhAMpdneTSAATCwE8vt4bS6BBnv8Y8ZceNO6wGOvcW30b1AiAY2MEGP75kP3Ka4Dpmfy+eSk1VAzvxA7LHW4akBuYU/QIhAMk7gtGSCjaxuy6DUssdW2tE4C0uzj87sIUFxQkEk48pAiEAkHxKin7tcB4pVU2yurSbGkB+TbaCOfkIzR4griXq00k=-----END RSA PRIVATE KEY-----');
var decrypted = key_pri.decrypt(encrypted, 'utf8');
console.log('decrypted: ', decrypted);
Unfortunately I get an error message:
Error: Error during decryption (probably incorrect key). Original error: Error: error:040A1079:rsa routines:RSA_padding_check_PKCS1_OAEP_mgf1:oaep decoding error
How can I fix the decription on the server (pc) side ?
Thanks !

The error gives you the information that the padding is wrong. JSencrypt is based on JSBN and only supports PKCS#1 v1.5 padding, but not OAEP. You have to configure NodeRSA to use the appropriate padding:
var key_pri = new NodeRSA(privateKeyString, {
encryptionScheme: 'pkcs1'
});
Then, you're passing a Base64-encoded string to key_pri.decrypt, but it expects the actual data as a Buffer, so you first need to parse that:
var decrypted = key_pri.decrypt(new Buffer(encrypted, 'base64'), 'utf8');

Related

Encrypt in JavaSscript with NaCl, Decrypt With PHP libsodium using KeyPair

i want to use NaCl library in the client side and libsodium in php to encrypt/decrypt messages between the client and the server using keypair(public,private).
When i encrypt with libsodium and decrypt with NaCl everything works, But when i try to encrypt with NaCl and decrypt with libsodium i get no result.
Encrypting with NaCl in the client side
var message = "Sample Message";
var bytes = nacl.util.decodeUTF8(message);
var client_public = nacl.util.hex2bytearray('35e9f8477b60f61747722698d98791c4e0818ff75da3943a30e13dc0a457d402');
var client_private = nacl.util.hex2bytearray('6382cd5ef713375b6fe3835a763c72dfdc7ddcade7b8bcb9640065582708ef2c');
var server_public = nacl.util.hex2bytearray('1f348bac3b60d3076fc1a32d4e205df67356a9ef16d4b3f391c0e4817f3b987f');
var sharedkey = nacl.box.before(server_public, client_private);
var nonce = nacl.util.hex2bytearray('c031122a5f57e253686d9f6082d1061a1546e5567290c7f0'); // 24 bytes
var cipher = nacl.box.after(bytes, nonce, sharedkey );
var cihper_with_nonce = nacl.util.bytearray2hex(nonce) + bytearray2hex(cipher); // will be sent to the server
//c031122a5f57e253686d9f6082d1061a1546e5567290c7f0b2c05c9fb1483fe9b1bd2d4ae261832a54569748dd7925511b3d236e23e8
nacl.util.hex2bytearray = hexString => new Uint8Array(hexString.match(/.{1,2}/g).map(byte => parseInt(byte, 16)));
nacl.util.bytearray2hex = bytes => bytes.reduce((str, byte) => str + byte.toString(16).padStart(2, '0'), '');
nacl.util.decodeUTF8=function(e){;var n,r=unescape(encodeURIComponent(e)),t=new Uint8Array(r.length);for(n=0;n<r.length;n++)t[n]=r.charCodeAt(n);return t}
Decrypting with libsodium in PHP
$cihper_with_nonce = 'c031122a5f57e253686d9f6082d1061a1546e5567290c7f0b2c05c9fb1483fe9b1bd2d4ae261832a54569748dd7925511b3d236e23e8';// received from the client
$server_public = hex2bin('1f348bac3b60d3076fc1a32d4e205df67356a9ef16d4b3f391c0e4817f3b987f');// generated with libsodium
$server_private = hex2bin('cea48d3c14bc9ad26bf3f62932db5d7336b8212866c14dec64670f295ec89d5d');// generated with libsodium
$client_public = hex2bin('35e9f8477b60f61747722698d98791c4e0818ff75da3943a30e13dc0a457d402');// generated with NaCl
$sharedkey = sodium_crypto_box_keypair_from_secretkey_and_publickey($server_private, $client_public );
$nonce = hex2bin(substr($cihper_with_nonce, 0, 48));//24 bytes
$cihper = hex2bin(substr($cihper_with_nonce, 48));
$message = sodium_crypto_box_open($cihper , $nonce, $sharedkey );
var_dump($message);// bool(false)
Am i using the Library the Wrong way or there is something i am doing it wrong?
Because when i encrypt with php and decrypt with NaCl everything works and i did the same way in reverse for the Decryption.
all the bytes(hex) used are generated with the same library.
NaCl Source nacl util
libsodium Source libsodium

How to decode in PHP RSA OAEP encoded in Javascript

So, I have some encryption/decryption issues …
I encrypt data in javascript thanks to node-forge and I try to decrypt it into PHP thanks to openssl_private_decrypt.
On the PHP side, I use the «OPENSSL_PKCS1_OAEP_PADDING» padding. So, on the javascript side I tried to configure forge to encrypt data with RSA-OAEP.
And when I try to decsypt the message on the PHP side, I have these errors :
error:04099079:rsa routines:RSA_padding_check_PKCS1_OAEP_mgf1:oaep decoding error
error:04065072:rsa routines:rsa_ossl_private_decrypt:padding check failed
I've tried to configure the encryption with sha1 message digest and sha1 for mgf1 option. I've also tried without any option (if I remember, forge use SHA256 by default). But there is nothing to do, I always have the same error …
javascript
const pubkey = `-----BEGIN PUBLIC KEY-----
...
-----END PUBLIC KEY-----
`;
const privkey = `-----BEGIN PRIVATE KEY-----
...
-----END PRIVATE KEY-----
`;
let publicKey = forge.pki.publicKeyFromPem(pubkey);
let key = forge.random.getBytesSync(32);
let encKey = publicKey.encrypt(key, 'RSA-OAEP', {
md: forge.md.sha1.create(),
mgf1: {
md: forge.md.sha1.create()
}
});
let b64Key = encodeURIComponent(btoa(enckey));
Next, I send the key in url with the "xcem" param, thanks to HttpClient. And I receive it in PHP.
php
$privKey = "";
$b64Key = urldecode($_GET['xcem']);
$encKey = base64_decode($b64Key);
$key = null;
if (!openssl_private_decrypt($encKey, $key, file_get_contents('/keys/openssl_private.key'), OPENSSL_PKCS1_OAEP_PADDING))
{
$errorssl = [];
while ($error = openssl_error_string()) {
$errorssl[] = $error;
}
throw new Exception("Erreur lors du décryptage du message ! " . json_encode($errorssl));
}
When I send Data between 2 PHP servers, there is no problem …
But I can't make it work between JS and PHP … I need some help ^^
Sooo …
After some tests, and headaches I found the problem … In my original code (not the one here) I sent the key, the init vector, the signature and the encrypted data …
But in my PHP, I tried to decode the signature … I didn't send data in the right order …
My bad …

Can not Read CyrptoJS Generated JWT using JwtSecurityTokenHandler().ValidateToken()

I am generating a token using CyrptoJS which correctly encodes and decodes in jwt.io test form. Using HMACSha256.
The process throws the exception:
IDX12709: CanReadToken() returned false. JWT is not well formed: '[PII is hidden]'.
The token needs to be in JWS or JWE Compact Serialization Format.
(JWS): 'EncodedHeader.EndcodedPayload.EncodedSignature'.
(JWE): 'EncodedProtectedHeader.EncodedEncryptedKey.EncodedInitializationVector.EncodedCiphertext.EncodedAuthenticationTag'.
Token received in api is :
eyAiYWxnIjogIkhTMjU2IiwgInR5cGUiOiJKV1QifQ==.eyAiYWN0b3IiOiAiam9uZXMiLCAibmFtZSI6ICJDYXNlRWRpdCJ9.JRi5hfqItl2gne1dUJxq1dfgdgJ1zD9xn2aUJopglbI=
The code I am using to Validate the token is:
public static Boolean ValidateToken(string jwtToken, string key)
{
var securityKey = new SymmetricSecurityKey(Convert.FromBase64String(key));
var validationParameters = new TokenValidationParameters()
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = securityKey
};
SecurityToken validatedToken;
var claimPrincipal = new JwtSecurityTokenHandler().ValidateToken(jwtToken, validationParameters, out validatedToken);
return validatedToken.ValidFrom <= DateTime.Now;
}
Issue was with the encoding from CryptoJS this helped me sort it out https://www.jonathan-petitcolas.com/2014/11/27/creating-json-web-token-in-javascript.html I was not url encoding the values. removing the =

Decrypting File In Node.js Throws Error But Able To Decrypt Using Bouncy Castle In C#

I'm having an issue where I was given a file to decrypt along with the Key, IV and encryption method (aes-256-ctr). I have been struggling to decrypt this using node.js and keep running into an error saying the IV length is invalid. I was also given the method to decrypt the file using the BouncyCaste library in C#. The C# method seems to work fine with no issues with the IV. What do I need to do differently in node than what is being done here in C# to avoid this error?
Working C# Decryption (Note: IV is in the filename)
using System;
using System.IO;
using System.Text;
using System.Security.Cryptography;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
namespace c_app
{
class Program
{
static void Main(string[] args)
{
var baseFolder = Directory.GetCurrentDirectory();
// Create parameters
var myDi = new DirectoryInfo(baseFolder);
string keyString = "xxxxxxxxxxxxx32BitKeyxxxxxxxxxxx";
byte[] keyBytes = ASCIIEncoding.UTF8.GetBytes(keyString);
var c = CipherUtilities.GetCipher("AES/CTR/NoPadding");
KeyParameter sk = ParameterUtilities.CreateKeyParameter("AES", keyBytes);
// Get the IV
var files = myDi.GetFiles("001398.20180823.000_1966151284357350418");
var fileInfo = files[0];
var pathSplit = fileInfo.FullName.Split('_');
var filePath = pathSplit[0];
var iv = long.Parse(pathSplit[1]);
// Decrypt the file
var base64String = File.ReadAllText(fileInfo.FullName);
c.Init(false, new ParametersWithIV(sk, BitConverter.GetBytes(iv)));
var inputBytesToDecrypt = Convert.FromBase64String(base64String);
var decryptedBytes = c.DoFinal(inputBytesToDecrypt);
var decryptedText = ASCIIEncoding.UTF8.GetString(decryptedBytes);
// Write file back to current directory
File.WriteAllBytes(string.Format(#"{0}/decrypted.csv", myDi.FullName), decryptedBytes);
}
}
}
My attempt in Node.js
var crypto = require('crypto');
var fs = require('fs');
var iv = Buffer.from('1966151284357350418', 'base64'); // Experimenting with encoding types like base64
var key = Buffer.from('xxxxxxxxxxxxx32BitKeyxxxxxxxxxxx');
fs.readFile('./001398.20180823.000_1966151284357350418', (err, encryptedText) => {
if (err) throw err;
var decipher = crypto.createDecipheriv('aes-256-ctr', key, iv); // <--- Error thrown here
decrypted = decipher.update(encryptedText, 'binary', 'utf8');
decrypted += decipher.final('utf8');
console.log(decrypted);
});
In case it is helpful I was also given the method for encrypting the file using BouncyCastle, which can be found here: https://pastebin.com/PWNzDum3

node-rsa errors when trying to decrypt message with private key

So I've been trying to use node with node-rsa and javascript with jsencrypt to create a website (for an assignment) where the javascript client gets the public key generated by the server (node-rsa), encrypts the message (jsencrypt) that the user has entered, sends it to the server and gets the server to decrypt it (node-rsa). The generation of the keys works, the encryption works however the decryption doesn't. When I start the node script I do the following for the encryption...
var NodeRSA = require('node-rsa');
var myDecrypter = new NodeRSA({b: 512});
When the client requests the key (I am using express) the following is ran.
app.get('/getPublicKey', function(req, res){
var publicKeyJson = {"Key": ""};
console.log(myDecrypter.exportKey('public'));
publicKeyJson.Key = myDecrypter.exportKey('public');
res.json(JSON.stringify(publicKeyJson));
});
The client then saves that key like this...
var myEncrypter = new JSEncrypt();
var myJson = "";
$.getJSON( "getPublicKey", function( data ) {
myJson = JSON.parse(data).Key;
setKey();
});
function setKey() {
myEncrypter.setPublicKey(myJson);
}
When I got to encrypt and send the message on the client I do this...
function messageEncrypt() {
message = document.getElementById("message").value;
var encrypted = myEncrypter.encrypt(message);
myMessage = {"username": "", "userId": 0.0, "message": ""};
myMessage.username = me.username;
myMessage.userId = me.userId;
myMessage.message = encrypted;
console.log(encrypted);
$.post("sendMessage", myMessage);
}
When the server receives a message this is what happens, this is where I get the errors.
app.post('/sendMessage', function(req, res){
var message = req.body;
var user = message.username;
var id = message.userId;
console.log("What a mess, " + user + " said " + message.message + " what on earth does that mean");
//This line below errors
var clearMessage = myDecrypter.decrypt(message.message, 'utf8');
console.log(user + " said " + clearMessage);
});
The error I get is ...
Error: Error during decryption (probably incorrect key). Original error: Error: error:040A1079:rsa routines:RSA_padding_check_PKCS1_OAEP_mgf1:oaep decoding error
at Error (native)
at NodeRSA.module.exports.NodeRSA.$$decryptKey (/home/node_modules/node-rsa/src/NodeRSA.js:295:19)
at NodeRSA.module.exports.NodeRSA.decrypt (/home/node_modules/node-rsa/src/NodeRSA.js:243:21)
at /home/securechat/securechat.js:36:36
at Layer.handle [as handle_request] (/home/node_modules/express/lib/router/layer.js:95:5)
at next (/home/node_modules/express/lib/router/route.js:131:13)
at Route.dispatch (/home/node_modules/express/lib/router/route.js:112:3)
at Layer.handle [as handle_request] (/home/node_modules/express/lib/router/layer.js:95:5)
at /home/node_modules/express/lib/router/index.js:277:22
at Function.process_params (/home/node_modules/express/lib/router/index.js:330:12)
Here however is where it gets interesting, to get that error message above I had a private key of...
-----BEGIN RSA PRIVATE KEY-----
MIIBOgIBAAJBAIhdx31QICGN1LKRW4WngeL3RtzPh7cEHmhFJB8m4bQUSTcSi4eg
sUvMeZkWyaF9gOxtZKzk5TI6q+8hg8TY6S8CAwEAAQJASds423cVH/c4NsqhXh8e
KvYwjBFeeNIjQegIq1KctbHmKNM5MMb4jnDqdY/S5XHHS22EGvLNheLgV8tlRjwG
UQIhANpNmbl215eOsGPJ0jqz1XPMBrO35V6I3P04kvr66R1JAiEAn+oL0jtAFETR
4PRfenye5MAu9US3V5MoDN8xUoEvKrcCIQDQT2ZWNNIrHAyzXB2QyJPxqInoqp1j
5QPDWl3ewtj5iQIgY3E1nKw/stsA8LTGUvMAFBv2l4r9wDXAaBC7KSUwYY0CIAj4
0gA9etDbPm3H/XDwK4WXs9mXkKroyxewkWoOoAw/
-----END RSA PRIVATE KEY-----
and the public key sent to the client was...
-----BEGIN PUBLIC KEY-----
MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAIhdx31QICGN1LKRW4WngeL3RtzPh7cE
HmhFJB8m4bQUSTcSi4egsUvMeZkWyaF9gOxtZKzk5TI6q+8hg8TY6S8CAwEAAQ==
-----END PUBLIC KEY-----
The encrypted messages (stackoverflow) was ...
XDViV0InCSnpyBxbNu5Herut0JYSsp87buvhzM4g2f9z3khIx2zA8Ou0Uq0TtmqtvBBVtZi5wZbcS6em/vB78g==
The interesting thing is that when I used the demo on jsencrypt website and enter my private key as well as the encrypted message I get the correct decrypted message.
So my question is...
What am I doing wrong with my node-rsa decryption???
If you need anymore information/code please put it in the comments below.
To answer your question #Curious_Programmer be default node-rsa uses pkcs1_oaep for encryption and decryption while jsencrypt uses pkcs1. Thankfully node lets you change the encryptionScheme, what you need to do is add ...
myDecrypter.setOptions({encryptionScheme: 'pkcs1'});
under
var myDecrypter = new NodeRSA({b: 512});
and all will work like a charm, I hoped I helped you ;)
It seems that the ciphertext is a buffer, i.e. binary data. Then it is transported using JSON, which consists of text. You need to use a text encoding over the binary data to transport it over a text based interface.
Check the following definition of the encrypt method:
key.encrypt(buffer, [encoding], [source_encoding]);
with the reminder that the default is 'buffer' for [encoding].
So you should be using:
var encrypted = myEncrypter.encrypt(message, 'base64', 'utf-8');
where 'base64' is for the ciphertext encoding and 'utf-8' is for the plaintext encoding.
The decryption routine should automatically use base64 decoding of the ciphertext:
var clearMessage = myDecrypter.decrypt(message.message, 'utf8');
should be just fine.
I had the same issue.
encrypt.setOptions({encryptingScheme:'pkcs1'}); //Can be 'pkcs1_oaep' or 'pkcs1'. Default 'pkcs1_oaep'.
But, it still failed.
I have changed the lib from node-rsa to ursa, like this:
privateKey.decrypt(thirdEncrypted, 'base64', 'utf8',ursa.RSA_PKCS1_PADDING);
The problem has been resolved in ursa.

Categories