I want to use nodeJS as a server side language. NodeJS have crypto module where DiffieHellman is a class. So, I can use this method to generate key and compute key.
But, client also need to create another instance of diffiehellman class. But how to do that? Can I use crypto module on client side? If yes then how, any solution?
Here are my client side code...
const crypto = require('crypto');
const express = require('express');
const app = express();
// Generate server's keys...
const server = crypto.createDiffieHellman(139);
const serverKey = server.generateKeys();
//send p=prime and g=generator to the client
Not sure what you're planning to achieve here, but it appears there's such port for browser:
https://www.npmjs.com/package/crypto-browserify.
createDiffieHellman is on the list of already ported modules. Especially take a look at the example: https://github.com/crypto-browserify/crypto-browserify/tree/master/example. Instead of createHash I believe you could try invoking createDiffieHellman.
See http://www-cs-students.stanford.edu/~tjw/jsbn/ecdh.html for an example of client-side ECDH key generation and key exchange in javascript.
Related
I am following this instruction to implement custom message sender in Cognito https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-lambda-custom-sms-sender.html
All works well with similar code (I use Typescript on AWS Lambda):
import {buildClient, CommitmentPolicy, KmsKeyringNode} from '#aws-crypto/client-node';
import b64 from 'base64-js';
const {decrypt} = buildClient(CommitmentPolicy.REQUIRE_ENCRYPT_ALLOW_DECRYPT);
const keyring = new KmsKeyringNode({keyIds: ["my-key-arn"]});
...
const {plaintext} = await decrypt(keyring, b64.toByteArray(event.request.code));
console.log(plainttext.toString()) // prints plain text exactly as I need
However, this library #aws-crypto/client-node makes my bundle really huge, almost 20MB! Probably because it depends on some of older AWS libs...
I used to use modular libraries like #aws-sdk/xxx which indeed give much smaller bundles.
I have found that for encrypt/decrypt I can use #aws-sdk/client-kms. But it doesn't work!
I am trying the following code:
import {KMSClient, DecryptCommand} from "#aws-sdk/client-kms";
import b64 from 'base64-js';
const client = new KMSClient;
await client.send(new DecryptCommand({CiphertextBlob: b64.toByteArray(event.request.code), KeyId: 'my-key-arn'}))
Which gives me an error:
InvalidCiphertextException: UnknownError
at deserializeAws_json1_1InvalidCiphertextExceptionResponse (/projectdir/node_modules/#aws-sdk/client-kms/dist-cjs/protocols/Aws_json1_1.js:3157:23)
at deserializeAws_json1_1DecryptCommandError (/projectdir/node_modules/#aws-sdk/client-kms/dist-cjs/protocols/Aws_json1_1.js:850:25)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async /projectdir/node_modules/#aws-sdk/middleware-serde/dist-cjs/deserializerMiddleware.js:7:24
at async /projectdir/node_modules/#aws-sdk/middleware-signing/dist-cjs/middleware.js:14:20
at async StandardRetryStrategy.retry (/projectdir/node_modules/#aws-sdk/middleware-retry/dist-cjs/StandardRetryStrategy.js:51:46)
at async /projectdir/node_modules/#aws-sdk/middleware-logger/dist-cjs/loggerMiddleware.js:6:22
at async REPL7:1:33 {
'$fault': 'client',
'$metadata': {
httpStatusCode: 400,
requestId: '<uuid>',
extendedRequestId: undefined,
cfId: undefined,
attempts: 1,
totalRetryDelay: 0
},
__type: 'InvalidCiphertextException'
}
What am I doing wrong? Does this KMSClient support what I need?
I have also tried AWS CLI aws kms decrypt --ciphertext-blob ... command, gives me exactly same response. Though if I encrypt and decrypt any random message like "hello world", it works like a charm.
What am I doing wrong and what is so special about Cognito code ciphertext so I have to decrypt it somehow another way?
Short answer: Cognito does not use KMS to encrypt the text, it uses the Encryption SDK. So you cannot use KMS to decrypt Cognito ciphertext.
Longer answer: I spent the past day trying to get a Python email-sender-trigger function working against Cognito using boto3 and the KMS client until I found another post (somewhere?) explaining that Cognito does not encrypt data using KMS, rather the Encryption SDK. Of course these two encryption mechanisms are not compatible.
For JavaScript and Node.js applications, it looks like you have an alternative to including the entire crypto-client: https://www.npmjs.com/package/#aws-crypto/decrypt-node
If all you are doing is decrypting, the above package will let you decrypt using the Encryption SDK and it's only 159KB.
I have managed to solve my task. I have realized that indeed it does not simply uses KMS to encrypt the text, the encryption/decryption process is much more complicated.
There is reference page https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/message-format.html
It describes how the message looks like, with all the headers and body, with IV, AAD, keys, etc... I have written my own script to parse it all and properly decrypt, it worked! Probably it's too long to share... I suggest to use the reference instead. Hopefully in future they will publish proper modular version of SDK.
The one from '#aws-crypto' didn't work for me, probably doesn't support all the protocols properly. This might be not the truth at the moment you are reading it.
Imagine this sample Express app straight from the documentation:
const express = require('express')
const app = express()
app.get('/', (req, res) => {
res.send('Hello World!')
})
app.listen(3000)
What is the idiomatic way to invoke the '/' endpoint programmatically from a different point in the same application code? Assume that I already removed the last line app.listen(3000).
The reason for this is that I want to take something like express-pouchdb and write an adapter for a different wire protocol, but leveraging the extensive routes already defined. I want to invoke these routes directly from js code without going over the network.
The application has dozens of routes already defined so changing each one to direct function calls as suggested in the first comment is not an option.
UPDATE:
I tried calling app.route.dispatch() but nothing comes back on the rsp object.
Your question is a duplicate of this answer: Is it possible to call Express Router directly from code with a "fake" request?
You can use run-middleware module exactly for that. You create an express app a usual, and then you can call the app using your parameters
Can someone explain this to me clearly?
const express = require("express");
const app = express();
I get the first line of code, but don't get the concept of initializing a variable "app" as express()? When we import express, we also have access to express()?
What does it do theoretically? What does that () of express() do?
Do we always have to do it like that?
Thank you.
If you are familiar with object-oriented programming, then the way to think of this is by creating an instance.
When you import express, you are importing the class. However, your server is an instance of that class. So, when you call
const app = express();
you are spinning up your server. You now have the encoding of a server you can interact with from app, whereas the original import just refers to the same class (i.e. like a template) for what that server is. The function express() is merely initializing a new server object for you.
Technically, you could have multiple 'servers' running:
const app1 = express();
const app2 = express();
You would want these to be independent of each other, which is why you don't just use the top-level import.
According to the documentation
The express() function is a top-level function exported by the express module
The function returns a app object which is essentially an Express application.
The app object has methods for
Routing HTTP requests; see for example, app.METHOD and app.param.
Configuring middleware
Rendering HTML views; see
Registering a template engine; see app.engine.
I have this use case:
- I'm working on a game with a webapp for user management and chat, which is on MERN, and a unity game, with socket.io as the real time messaging layer for the multiplayer game.
- User may register to webapp by either providing a pair of email/password, or getting authenticated on FB/Gamil/etc. as usual, in which case the user's email is obtained and saved to MongoDB and this is done by passport.
- There is no session in express side, and socket.io is on a redis. There is no cookie but JWT is used.
My problem is that I don't know what's the best practices in this. I read this
article
and this
one
which both have content and code close to what I want to do, but in the first one:
app.use(express.cookieParser());
while I don't want to use cookie at all, and the other one also has in code:
cookie: {
secure: process.env.ENVIRONMENT !== 'development' && process.env.ENVIRONMENT !== 'test',maxAge: 2419200000}...
Also, I found this on
github
which suggests for the client side (unity):
var socket = io.connect('http://localhost:9000');
socket.on('connect', function (socket) {
socket.on('authenticated', function () {
//do other things
})
.emit('authenticate', {token: jwt}); //send the jwt
});
meaning that:
1. socket is created
2. authentication is requested
but I think that the approach I found in the other article is better, where the socket is not created at all if the JWT for auth is not provided at the first ever connection request sent to "io", so if I'd do it I'd issue:
var socket = io.connect('http://localhost:9000', {query: {"JWT":"myjwt"}});
and in my server side where I have:
io.on("connection", function(socket){...});
I'd like to first get the JWT:
var jwt = socket.handshake.query["JWT"];
and then if auth will be unsuccessful, simply return socket.disconnect('reason') and do not open any connection at all (here maybe I just didn't understand, say, that the approach the Author took in the github source is using a middle ware technique and it is maybe also done before anything else).
I still could not find out what is the best practice that Gurus use, please help me get clear.
I'm unable to use React's server side rendering due to my use of client side libraries such as reqwest. I would like to pass some data to my react components, however. Is there a way to do this?
The easiest way to do this is by having api-client.js and api.js. In your browserify/webpack config you set up a client side version. For browserify put this in your package.json (feel free to edit and add webpack).
"browser": {
"./path/to/api.js": "path/to/api-client.js"
}
The second option is better in my opinion, but more difficult to implement. You create an abstract representation of your API that works like this:
var comments = require('./api').get('comments');
comments.getById('7').then(function(comment){ ... });
comments.create({...}).then(...);
On the server api.js simply calls the correct functions, which all return promises. On the client it returns a promise, makes an ajax request to the server, which calls these functions, and sends back the response, and the api client resolves/rejects its promise.
This allows the api to automatically work, and allows you to do additional things like track unfulfilled promises, and pre-populate state on the client, etc. (see react-async for example).