Decrypt AES 256 CBC javascript - javascript

I am a newbie angular front end developer and now I need to access to a Java spring REST api of the other developer team.
In order to get api http://apps.api.com/api/user/login , I need to send that request with Headers : Authorization : Bearer b517241b-e81d-430e-afb6-773527989b47 and Content-Type : application/json.
To get the token b517241b-e81d-430e-afb6-773527989b47 , I have to request to another api http://apps.api.com/api/auth/token, then the result that I get from that api is something like :
{ "token": "eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE0NTQwMzI5MDk2NzYsInN1YiI6InRva2VuIiwidG9rZW4iOiIrbjZEd1NDUGVMbXd0SGpCT2ZzZUhVRlwvS2NOMzBBTDRkXC9sWDlSVlI1UWxnXC9wV2M1VVNNREpCVDVSUnNWNHpadUFtNExWc3BIeDl1SmtESGhvZTI0dWhMcUNzeUFmZklYMTBkalVqVzFnOSt5QTN4eEg4TElQbzBoTDR5V0JhNnplWm9lVFcrZFE0dzd3MVhCazhLZFZwWGFmRmJMZ3RoXC9OdVE5REM1c3QxTllnSDB2aHRWZ0lha3VnZVlhOEFPU1c3eWVsOWFHcXhJN1hHM1FrbVwvYUE9PSIsImlzcyI6Imh0dHBzOlwvXC93d3cud2luZ21vbmV5LmNvbSJ9.uBQYvfTwadTG2QZ76tQN6-ETT1M8X72ltDe7xBCvEhA"
}
What I need to do is, decode that token using jwt then decrypt it using AES 256 CBC (I got stuck here).
I got the code of decryption from back-end developer and the code is in java :
private static final String AES_KEY = "HG47YZ3CR8";
public static String decrypt(String orignalText) throws ApplicationException {
try {
final MessageDigest md = MessageDigest.getInstance("SHA-256");
final byte[] digestOfPassword = md.digest(AES_KEY.getBytes("utf-8"));
final SecretKey key = new SecretKeySpec(digestOfPassword, "AES");
final Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(new byte[16]));
final byte[] plainTextBytes = Base64.decodeBase64(orignalText);
final byte[] encodeTextBytes = cipher.doFinal(plainTextBytes);
return new String(encodeTextBytes);
} catch (NoSuchAlgorithmException |
UnsupportedEncodingException |
IllegalBlockSizeException |
InvalidKeyException |
BadPaddingException |
NoSuchPaddingException | InvalidAlgorithmParameterException e) {
throw new ApplicationException(ErrorCode.GENERAL_FAIL, e);
}
}
I've been trying to search for javascript library to write the decryption same as that java code but I could not find the right one.
I appreciate if any one has any idea about which javascript library that is similar to this java code.

I'm not sure I'd really recommend using your front end to decrypt anything since this would require your key to be in the javascript library which would essentially allow EVERYONE to decrypt your token. Which would beg the question why are you encrypting to begin with. But if you really need to do this in javascript you can check out the SO answers here.

Related

Encoding the data to JWT token with NodeJS getting error PEM routines:PEM_read_bio:no start line

I tried to encode the data with the secret key using the jsonwebtoken package in nodejs and getting the following error:
error:0906D06C:PEM routines:PEM_read_bio:no start line
The code that I used to encode the data using the secret key and algorithm is mention below:
var data = {
sub: "1234567890",
name: "John Doe"
};
var secretKey = "secret123";
var algorithm = { algorithm: "RS384" };
getJWTToken(data, secretKey, algorithm);
let getJWTToken = function(data, secretKey, algorithm) {
console.log(token: jsonwebtoken.sign(data, secretKey, algorithm));
};
It seems the problem is the algorithm. When I use the algorithm HS256, HS384 and HS512 it's working fine but when I used the algorithm RS256,RS384 and RS512 I am getting this error.
Can anyone help me out how to solve this issue?
For the RSA-algorithms you need to provide a private RSA key in PEM format to sign the token, and a public RSA key to verify it. You can't just pass a simple string like you do it for the HSxxx algorithms.
You can generate a public/private key pair with an online tool, or with openssl as described under that link or also down below.
And then read the key an sign the token like this (examples taken from the documentation):
// sign with RSA SHA256
var privateKey = fs.readFileSync('private.key');
var token = jwt.sign({ foo: 'bar' }, privateKey, { algorithm: 'RS256' });
and to verify with the public key:
// verify a token asymmetric
var cert = fs.readFileSync('public.pem'); // get public key
jwt.verify(token, cert, function(err, decoded) {
console.log(decoded.foo) // bar
});
For ESxxx and PSxxx algorithms it's basically the same as for RSxxx algorithms.
According to this you can generate and use the same key pair for RSxxx and Psxxx algorithms like this:
openssl genrsa 2048 -out rsa-2048bit-key-pair.pem
For ES256 the keypair is different and would be generated like this:
openssl ecparam -genkey -name prime256v1 -noout -out ec256-key-pair.pem

Encrypt in nodeJS and Decrypt in Javascript

I am encrypting text in node JS by using node-RSA and passing it to client(javascript), in which JSEncrypt library is using,but all the time the decrypted message is coming null. Public key and private Key is developing on nodeJS server, encrypting with Public key and decrypting on javascript side with Private Key .
This is not happening right!!!!
Can anyone tell which library i should use in javascript to decrypt the message coming from nodejs(using Node-RSA).OR any other IDEA!!
We are already using HTTPS but our use case is such that we have a broker between it.. and its not trusted broker, and we are forced to use it.. so we would like to use encryption decryption.. Although we have trusted people in our client side, so we are decrypting at client side.
I used CryptoBrowserify to encrypt at javascript (client side)
import CryptoBrowserify from 'crypto-browserify';
public encryptStringWithRsaPublicKey(data: string, publicKey: string): string {
var encrypted = CryptoBrowserify.publicEncrypt( publicKey,new Buffer(data));
return encrypted.toString('Base64');
}
And crypto to dedcrypt at Nodejs
decrypt = function(privateKey, data) {
var crypto = require('crypto');
var buffer = new Buffer(data, 'base64');
var decrypted = crypto.privateDecrypt(privateKey, buffer);
return decrypted.toString('utf8')
};
Nodejs has its builtin cryto library,it is optimized and tested, recommend to use that: https://nodejs.org/api/crypto.html

Connecting to websocket using C# (I can connect using JavaScript, but C# gives Status code 200 error)

I am new in the area of websocket.
I can connect to websocket server using JavaScript using this code:
var webSocket = new WebSocket(url);
But for my application, I need to connect to the same server using c#. The code I am using is:
ClientWebSocket webSocket = null;
webSocket = new ClientWebSocket();
await webSocket.ConnectAsync(new Uri(url), CancellationToken.None);
3rd line of the code results following error:
"Server returned status code 200 when status code 101 was expected"
After little bit of survey, I realised that somehow server can't switch http protocol to websocket protocol during connection process.
Am I doing anything stupid in my C# code or there is something going wrong with the server. I don't have any access to the server, as the url I am using is a third party one .
Could you please give me any suggestion regarding the issue?
TL; DR:
Use ReceiveAsync() in loop until Close frame is received or CancellationToken is canceled. That's how you get your messages. Sending is straightworward, just SendAsync(). Do not use CloseAsync() before CloseOutputAsync() - because you want to stop your receiving loop first. Otherwise - either the CloseAsync() would hang, or if you use CancellationToken to quit ReceiveAsync() - the CloseAsync() would throw.
I learned a lot from https://mcguirev10.com/2019/08/17/how-to-close-websocket-correctly.html .
Full answer:
Use Dotnet client, here, have an example cut out from my real life code, that illustrate how the handshaking is made. The most important thing most people don't understand about how the thing operates is that there is no magic event when a message is received. You create it yourself. How?
You just perform ReceiveAsync() in a loop that ends, when a special Close frame is received. So when you want to disconnect you have to tell the server you close with CloseOutputAsync, so it would reply with a similar Close frame to your client, so it would be able to end receiving.
My code example illustrates only the most basic, outer transmission mechanism. So you send and receive raw binary messages. At this point you cannot tell the specific server response is related to the specific request you've sent. You have to match them yourself after coding / decoding messages. Use any serialization tool for that, but many crypto currency markets use Protocol Buffers from Google. The name says it all ;)
For matching any unique random data can be used. You need tokens, in C# I use Guid class for that.
Then I use request / response matching to make request work without dependency on events. The SendRequest() methods awaits until matching response arrives, or... the connection is closed. Very handy and allows to make way more readable code than in event-based approach. Of course you can still invoke events on messages received, just make sure they are not matched to any requests that require response.
Oh, and for waiting in my async method I use SemaphoreSlim. Each request puts its own semaphore in a special dictionary, when I get the response, I find the entry by the response token, release the semaphore, dispose it, remove from the dictionary. Seems complicated, but it's actually pretty simple.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.WebSockets;
using System.Threading;
using System.Threading.Tasks;
namespace Example {
public class WsClient : IDisposable {
public int ReceiveBufferSize { get; set; } = 8192;
public async Task ConnectAsync(string url) {
if (WS != null) {
if (WS.State == WebSocketState.Open) return;
else WS.Dispose();
}
WS = new ClientWebSocket();
if (CTS != null) CTS.Dispose();
CTS = new CancellationTokenSource();
await WS.ConnectAsync(new Uri(url), CTS.Token);
await Task.Factory.StartNew(ReceiveLoop, CTS.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default);
}
public async Task DisconnectAsync() {
if (WS is null) return;
// TODO: requests cleanup code, sub-protocol dependent.
if (WS.State == WebSocketState.Open) {
CTS.CancelAfter(TimeSpan.FromSeconds(2));
await WS.CloseOutputAsync(WebSocketCloseStatus.Empty, "", CancellationToken.None);
await WS.CloseAsync(WebSocketCloseStatus.NormalClosure, "", CancellationToken.None);
}
WS.Dispose();
WS = null;
CTS.Dispose();
CTS = null;
}
private async Task ReceiveLoop() {
var loopToken = CTS.Token;
MemoryStream outputStream = null;
WebSocketReceiveResult receiveResult = null;
var buffer = new byte[ReceiveBufferSize];
try {
while (!loopToken.IsCancellationRequested) {
outputStream = new MemoryStream(ReceiveBufferSize);
do {
receiveResult = await WS.ReceiveAsync(buffer, CTS.Token);
if (receiveResult.MessageType != WebSocketMessageType.Close)
outputStream.Write(buffer, 0, receiveResult.Count);
}
while (!receiveResult.EndOfMessage);
if (receiveResult.MessageType == WebSocketMessageType.Close) break;
outputStream.Position = 0;
ResponseReceived(outputStream);
}
}
catch (TaskCanceledException) { }
finally {
outputStream?.Dispose();
}
}
private async Task<ResponseType> SendMessageAsync<RequestType>(RequestType message) {
// TODO: handle serializing requests and deserializing responses, handle matching responses to the requests.
}
private void ResponseReceived(Stream inputStream) {
// TODO: handle deserializing responses and matching them to the requests.
// IMPORTANT: DON'T FORGET TO DISPOSE THE inputStream!
}
public void Dispose() => DisconnectAsync().Wait();
private ClientWebSocket WS;
private CancellationTokenSource CTS;
}
}
BTW, why use other libraries than the .NET built in? I can't find any reason other than maybe poor documentation of the Microsoft's classes. Maybe - if for some really weird reason you would want to use modern WebSocket transport with an ancient .NET Framework ;)
Oh, and I haven't tested the example. It's taken from the tested code, but all inner protocol parts were removed to leave only the transport part.
Since WebsocketSharp is not .NET Core compatible I suggest using websocket-client instead.
Here's some sample code
static async Task Main(string[] args)
{
var url = new Uri("wss://echo.websocket.org");
var exitEvent = new ManualResetEvent(false);
using (var client = new WebsocketClient(url))
{
client.MessageReceived.Subscribe(msg => Console.WriteLine($"Message: {msg}"));
await client.Start();
await client.Send("Echo");
exitEvent.WaitOne();
}
Console.ReadLine();
}
Be sure to use ManualResetEvent. Otherwise it doesn't work.
If you connect with a WebSocket client and you get an HTTP 200 as response, means that probably you are connecting to the wrong place (host, path and/or port).
Basically, you are connecting to a normal HTTP endpoint that is not understanding your WebSocket requirement, and it is just returning the "OK" response (HTTP 200). Probably the WebSocket server runs in another port or path in the same server.
Check your URL.
Not quite sure what happened to WebSocketSharp nuget package, however I noticed that now WebSocket# is showing up as most relevant result in nuget repo. It took me some time before I realized that Connect() is now returning Task, hopefully this example will be useful to someone:
using System;
using System.Threading.Tasks;
using WebSocketSharp;
namespace Example
{
class Program
{
private static void Main(string[] args)
{
using (var ws = new WebSocket(url: "ws://localhost:1337", onMessage: OnMessage, onError: OnError))
{
ws.Connect().Wait();
ws.Send("Hey, Server!").Wait();
Console.ReadKey(true);
}
}
private static Task OnError(ErrorEventArgs errorEventArgs)
{
Console.Write("Error: {0}, Exception: {1}", errorEventArgs.Message, errorEventArgs.Exception);
return Task.FromResult(0);
}
private static Task OnMessage(MessageEventArgs messageEventArgs)
{
Console.Write("Message received: {0}", messageEventArgs.Text.ReadToEnd());
return Task.FromResult(0);
}
}
}
All the libraries mentioned above are Wrappers. The .Net Frameworks class doing this is System.Net.WebSockets.ClientWebSocket
Websocket URLs should start with ws:// or wss:// where the latter is secure websocket.

How can I get a certificate to verify my RSA digital signature using jsrsasign?

I am using jsrsasign and I have an RSA public and private key that I generated earlier. I used the following code to generate a signature.
var key = new RSAKey();
key.readPrivateKeyFromPEMString($("#private")[0].value); // "private" is a textarea containing the PEM encoded private key.
var sig = new KJUR.crypto.Signature({"alg": "SHA1withRSA", "prov": "cryptojs/jsrsa"});
sig.initSign(key);
sig.updateString('message');
var sigValueHex = sig.sign();
This produced the expected hex signature. The documentation for jsrsasign provides the following code to verify signatures.
var sig = new KJUR.crypto.Signature({"alg": "SHA1withRSA", "prov": "cryptojs/jsrsa"});
sig.initVerifyByCertificatePEM("-----BEGIN CERTIFICATE-----(snip)");
sig.updateString('message');
var isValid = sig.verify(sigValueHex);
My problem is that I do not have a certificate to verify with. sig.sign() only gives the signature, no certificate. There is also sig.initVerifyByPublicKey(RSAKey) which seemed promising at first. However, RSAKey only has ways to get the private key, not public key.
So, my question is how can I get this certificate? And if I can't, how can I get an RSAKey object from my public key? And if I can't do that, is there a better way to do digital signatures with javascript?
I am using jsrsasign and jQuery. http://kjur.github.io/jsrsasign/
If there is no way to do this with the methods I am using, is there a better way? My main goal here is to be able to send a message to a server and be sure that the message wasn't tampered with and that it came from the correct place. SSL is not an option here. The message does not need to be encrypted, only protected.
You can create the public key with KEYUTIL.getKey(param), where "param" can be a string with either your certificate or your public key.
Here are the docs for that method
Example:
var publicKey = KEYUTIL.getKey(publicKeyString);
var sig = new r.Signature({"alg": "SHA256withRSA", "prov": "cryptojs/jsrsa"});
sig.initVerifyByPublicKey(publicKey);
sig.updateString(message);
var isValid = sig.verify(signature);
Hope that helps.
You could generate an X.509 self-signed key/certificate pair by using openssl.
openssl req -newkey rsa:4096 -x509 -nodes -keyout key.pem -out certificate.pem
Then upload certificate.pem to the server, and use key.pem to sign messages on the client.
The message and signature can be verified on the server.
Here is the sample code of using jsrsasign:
const jsrsasign = require("jsrsasign");
const fs = require('fs');
// sign
let key = fs.readFileSync("./key.pem", "utf-8");
let sig = new jsrsasign.KJUR.crypto.Signature({"alg": "SHA1withRSA"});
sig.init(key);
sig.updateString("message");
const signature = sig.sign();
// verify
let certificate = fs.readFileSync("./certificate.pem", "utf-8");
let ver = new jsrsasign.KJUR.crypto.Signature({"alg": "SHA1withRSA"});
ver.init(certificate);
ver.updateString("message");
ver.verify(signature); // return true
For your reference.

Problems with AES in crypto-js and pycrypto

I try to implement a communication between
crypto-js (a javascript crypto library)
and pycrypto (a python crypto library)
On the python server side I encrypt a string with an iv and a passphrase and send the iv with the encrypted text base64 encoded to the javascript client side. Then I want to decrypt the string with the passphrase the user can enter.
python - server
from Crypto.Cipher import AES
from Crypto import Random
iv = Random.get_random_bytes(16)
key = "1234567812345678"
aes = AES.new(key, AES.MODE_CFB, iv)
encrypted_text = base64.b64encode(aes.encrypt("this is a test.."))
iv = base64.b64encode(iv)
# send iv, encrypted_text to client
javascript - client
// <script type="text/javascript"
src="http://crypto-js.googlecode.com/files/2.5.3-crypto-sha1-hmac-pbkdf2-blockmodes-aes.js">
</script>
// text, and iv is base64encoded from the python script
// key is a string from an <input type='text'>
decrypted = Crypto.AES.decrypt(text, key, {iv: iv, mode: new Crypto.mode.CFB});
With this example I get a javascript error
Uncaught URIError: URI malformed
But this is just one example - I tried every constellation of base64 encodings/decodings I could think of. I also tried to changed the Mode. But these are all random tests and I want to understand what I really have to do.
What encoding does the crypt-js want?
Which mode should I chose?
Is there something I should change on the python server side?
what is about padding? Could there be the fault?
any other javascript libraries you can recommend?
thank you very much and kind reagards,
samuirai
Before You encode to base64 You must sum iv and encrypted_text:
encrypted_text = base64.b64encode(iv + aes.encrypt("this is a test.."))
From the official documentation (https://www.dlitz.net/software/pycrypto/doc/) :
As an example, encryption can be done as follows:
from Crypto.Cipher import AES
from Crypto import Random
key = b'Sixteen byte key'
iv = Random.new().read(AES.block_size)
cipher = AES.new(key, AES.MODE_CFB, iv)
msg = iv + cipher.encrypt(b'Attack at dawn')

Categories

Resources