In cryptography, the Elliptic Curve Digital Signature Algorithm (ECDSA) offers a variant of the Digital Signature Algorithm (DSA) which uses elliptic curve cryptography. https://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange#Description
The server will sign only messages that it generates itself; and, in any case, the only "private" operation involving a curve in ECDSA is multiplication of the conventional base point (hardcoded, since it is part of the curve definition, hence correct) by a random value that the server generates. There is no risk of private key leakage that would be specific to the used curve.
Mathematical theory behind elliptic curves: https://www.youtube.com/watch?v=NF1pwjL9-DE.
Signing your message with your private key enables the recepient to verify it was really you who created this message. Reason why we use them is the potential for MITM attack: https://www.youtube.com/watch?v=vsXMMT2CqqE.
Safety of different elliptic curves: http://safecurves.cr.yp.to
To use eliliptic curves in JS code you can use: https://github.com/indutny/elliptic

var EC = require('elliptic').ec
// Create and initialize EC context
var ec = new EC('secp256k1')
// Generate keys
var key = ec.genKeyPair()
key.priv.words

// Sign the message's hash
var msgHash = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
var signature = key.sign(msgHash)
// Export DER encoded signature in Array
var derSign = signature.toDER()
// Verify signature
key.verify(msgHash, derSign)

Above is the magic which makes the HTTPS (SSL) protocol secure. Similar security elements are used when establishing SSH connections, VPN connections, cryptocurrency wallets, etc. ...
In practice we use ephemeral Diffie-Hellman key exchange to generate a shared short term session key combined with long term RSA private key. This prevents any later decryption of our (potentially logged via MITM attack by ARP poisoning) encrypted data by obtaining our RSA private key at any point in the future.
For more details on Diffie-Hellman key exchange works see: https://www.youtube.com/watch?v=NmM9HA2MQGI
Each time we use a web browser on an HTTPS web site we are:
- getting the server's public key
- encrypting our request with public key
- sending our encrypted request to the server
https://www.sohamkamani.com/nodejs/rsa-encryption/#rsa-encryption-in-a-nutshell
To make all of this practical in real world we use the NodeJS built-in library named crypto:

const crypto = require("crypto")

"Interoperability" means that we would prefer it if SSL clients can actually connect to our server; otherwise, having a SSL server would be rather pointless. In practice, average clients only support two curves, the ones which are designated in so-called NSA Suite B: these are NIST curves P-256 and P-384 (in OpenSSL, they are designated as, respectively, "prime256v1" and "secp384r1").
If we use any other curve, then some widespread Web browsers will be unable to talk to our server. Use P-256 to minimize trouble.

const {privateKey, publicKey} = crypto.generateKeyPairSync("rsa", {
modulusLength: 512,
namedCurve: 'prime128v1',
publicKeyEncoding: { type: 'spki', format: 'pem' },
privateKeyEncoding: { type: 'pkcs1', format: 'pem' },
})

Keys in the same format generated with a different curve look the same.

const {privateKey2, publicKey2} = crypto.generateKeyPairSync("rsa", {
modulusLength: 2048,
namedCurve: 'secp384r1',
publicKeyEncoding: { type: 'spki', format: 'pem' },
privateKeyEncoding: { type: 'pkcs1', format: 'pem' },
})

To sign the data first step is to get a hash.

const md5 = data => crypto.createHash('md5').update(data).digest("hex")
const data = 'our data'
const dataHash = md5(data)
'hash of the string \''+data+'\' is: ' + dataHash

Then we use our private key, to sign the hash.

const sign = crypto.createSign('RSA-SHA256')
sign.update(dataHash)
sign.end()
const signature_ = sign.sign(privateKey)

We can express the signature in other encodings.

const signedHash = signature_.toString("base64")
console.log({
dataLocation: "rf://0xABCD/someUri",
dataHash,
signedHash
})

To verify the data, we combine the hash with our public key.

const verify = crypto.createVerify('RSA-SHA256')
verify.update(dataHash)
verify.end()
'key is ok: ' + verify.verify(publicKey, signature_)

Encryption

const encryptedData = crypto.publicEncrypt(
publicKey,
Buffer.from(data)
)

We can render the encrypted bytes in other encodings.

encryptedData.toString("base64")

To decrypt the data we need the private key corresponding to the public key.

const decryptedData = crypto.privateDecrypt(
privateKey,
encryptedData
)

Decrypted data is in bytes, to convert it to string use toString.

decryptedData.toString()

sign in to comment