NodeJS SubtleCrypto - Multiple keyUsage for RSA Keys - node.js

I'm so sorry for the ambiguous title of this question, i'm not really sure how to phrase this.
I've generated a Public and Private key using SubtleCrypto in NodeJS like so:
const { publicKey, privateKey } = await subtle.generateKey({
name: 'RSA-OAEP',
4096,
new Uint8Array([1, 0, 1]),
'SHA-256',
}, true, ['encrypt', 'decrypt']);
And this works perfectly for one use case:
Public Key to Encrypt, Private Key to Decrypt.
However, the way I wish to implement RSA in my project is as such:
Client asks Server for a Public Key
Client encrypts payload using Public Key
Server decrypts payload using Private Key
Server encrypts response payload using Private Key
Client decrypts response payload using Public Key
When I try to perform Step 4, i encountered this error:
The requested operation is not valid for the provided key
Is there a way to specify that each key could be used for Encrypt & Decrypt?
Also if my implementation is completely wrong, i'm sorry for that.

Step 4, as described by you, is a signing operation. Signing is very different from encrypting data. For this to work, both, client and server would need their own keypair:
client: client public key & client private key
server: server public key & server private key
Client uploads its client public key
Client asks server for the server public key
Client encrypts payload using the server public key
Server decrypts payload using the server private key
Server encrypts response payload using client public key
Client decrypts response payload using client private key
Besides the possible huge computational workload of encrypting and decrypting large amount of data using RSA, what is the threat model here and what do you want to achieve? You should be very careful if you really want to deploy this into production, as you seem to be rather inexperienced with this topic (no offense here).

Related

JWT with RSA public and private key

I don't understand why I should use the public key in signing JWT. The private key is there so that the JWT token cannot be forged, yes? But why additionally sign it with a public key? Are there any benefits? Because I don't understand it at all. After all, a JWT signed with a private key can be read without the public key. What is this public key for?
Signing a JWT means you take the cleartext, signing it with a key - either the private key from an RSA pair or a symmetric key, then add the signature to the JWT. The JWT itself is still readable without decrtypting the signature. But someone with the key can decrypt the signature and confirm the contents match the cleartext.
The advantage of using RSA over symmetric key is that anyone can verify the signature without them having to have a secret key. You can either pass the public key to the JWT recipient over a side channel, or if using OAuth2 it provides a URL to access public keys.
You would use the public key for encrypting, not signing. You encrypt with the recipient's public key so that only the recipient can decrypt it.

ADFS sso and using passport-saml Express "No decryption key for encrypted SAML response"

I am having this issue while logging ADFS SSO. "No decryption key for encrypted SAML response".
Login from another account is being successful. Someone can help me with this. I am using Express with passport-saml work.
This is code snap where I am stuck.
node_modules/passport-saml/lib/passport-saml/saml.js in null. at line 623:15
if (encryptedAssertions.length == 1) {
if (!self.options.decryptionPvk)
throw new Error('No decryption key for encrypted SAML response');
var encryptedAssertionXml = encryptedAssertions[0].toString();
How encryption works in SAML: identity provider encrypts some elements of the SAML response with service provider's public key. The service provider decrypts using the private key that corresponds to the public key used to encrypt. In other words, the service provider needs to own a keypair - private key and public key - for this use case to work.
The private key of the aforementioned keypair needs to be configured via decryptionPvk parameter in passport-saml. Since the assertion is encrypted yet no private key is found in decryptionPvk, passport-saml complains.
Either remove the encryption on ADFS side or provide the private key to passport-saml.

NodeJS: HTTPS Server error w/ host key (wrong tag?)

I am receiving an error when the https server starts, something along the lines of:
Error:0D0680A8:asn1 encoding routines:ASN1_CHECK_TLEN:wrong tag
I may be completely going about this the wrong way. I need to get an SSL cert from a 3rd party CA. This CA requires that I give them a Certificate Signing Request (CSR) that I have generated.
I generated a CSR using certreq.exe on Windows and provided the CSR to them. They provided the public key cert in response.
Here's where I'm a little confused. The https server has a key and cert property. As I understand, cert is for the public key (from the CA) and key is for the private key. Where's this private key??
After some googling, it appears that certreq.exe will create a key pair in the windows cert store when the CSR is generated. I exported the PFX, used openssl to extract the private key, and decrypted the key so that it was in a format that had "--BEGIN RSA PRIVATE KEY.. etc". The key looks fine to me. It's formatted the same way my previous self-signed certs were formatted which worked fine.
I used this private key for the https key property and received that asn1 wrong tag error. Am I going about getting the private key the wrong way? Or is the error something else?

Asymmetric Encryption

If a public key is used to encrypt the private key, and the public key is known to everyone, what is stopping a hacker from intercepting the private key, then using the public key to decrypt it and then using the private key to decrypt and encoded message?
The way public/private key crypto works is that anyone can use the public key to encrypt a piece of data, but you need the private key (which the owner does not distribute) in order to decrypt that data.
It doesn't matter that the data being encrypted is the private key itself.

Sharing only the public key Is secure?

I need to secure a REST request knowing who is doing it. I know the HMAC method but I wouldn't like not store the client private key on my server. This is my approach:
The SERVER creates a private and public key for the client
The SERVER sends the private key and a client id to the client
The CLIENT stores its private key
The SERVER stores only the public client key
The CLIENT makes a RESTful request by encrypting its client id with its private key (ecryptedData) and sends the pair clientID:encryptedData to the SERVER
The SERVER looks for the public key of the given client id and decrypt the encryptedData
The SERVER checks if the decrypted data contains the same client id. If the client id is the same then the SERVER trusts on the sender otherwise it rejects the request.
Maybe this method already exists but I don't know it.
Is it secure this method?
EDIT
I reformulate the question:
if I care only about who is the sender and not about what he is sending in a monodirectional communication (CLIENT -> SERVER), can I use RSA in this way?
ONE TIME
SERVER creates the RSA pair key for the client
SERVER stores the client public key (I doesn't matter if the key is stolen..it's public!)
SERVER sends the client private key to the client
DURING THE CLIENT -> SERVER COMMUNICATION
CLIENT encrypts a known word + timestamp (to prevent replay attack) by its private key ex. SIGNATURE = encrypt(RSA, 'FOO:1234234')
CLIENT sends the message with the API KEY and singature ex. 54545345:SIGNATURE
SERVER looks up the public key of the given API KEY
SERVER decrypts the message with the public key found
SERVER checks the correctness of the known word FOO and the timestamp
SERVER rejects the message if the previous step fails
Is it secure this method?
Thanks a lot!
aGO!
"SERVER sends the client private key to the client": this does not seem very secure.
If malicious clients intercept this communication, they can get client's private-key and can send messages as if they were sent by the actual client.
You should let the client generate the two keys, without sharing the private one.
It's not secure to send a Private Key to a user. Please take a look at the next approach:
The Client uses your or open-source (3rd-party) SDK (or crypto library) to generate a Key Pair (Private and a Public Key) - if you need, I can share some cool solution;
The Client stores a Private Key into local storage (that key can be based on a Client password);
The Client sends a request to your Server that contains his Public Key and some additional data about the Client (his Identity, name/email/etc.). This request will be encrypted with a Public Key of your server and signed with Client's Private Key;
The Server decrypts the encrypted request, authenticates/registers the Client and his Public Key and signature. Here you should have some Public Key Management (Keys Service).
At communication step, the Server and the Client use their Private Keys to decrypt and sign data / Public Keys to encrypt data and verify signatures.

Resources