Cryptography

node v10.24.1
version: 6.0.0
endpointsharetweet
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()
Loading…

no comments

    sign in to comment