- Published on
Nodejs - KeyPair generation and usage of keys
1279 words7 min read–––
Views
- Authors
- Name
- Saikrishna Reddy
Cryptography
- Refer this repositary for all files.
- In case of -> Data protection :
- Encrypt with public key and decrypt with private key.
- Refer :
- Encryption > File :
encrypt.js
>encryptWithPublicKey()
- Decryption > File :
decrypt.js
>decryptWithPrivateKey()
- Encryption > File :
- To test :
- run
node main.js
- run
- In case of -> Digital Signatures x| JWTs ...
- Encrypt with private key and decrypt with public key
- Here, after encrypting, the encrypted data need to transferred to receiver along with the algorithm used, original data and signed message. Using the receiver/application can calculate the hash and the compare it with the hash received/calculated from the received data.
- If verifed successfully, it means the data is correct and sender is not valid.
- Refer :
- Encryption > File :
encrypt.js
>encryptWithPrivateKey()
- Decryption > File :
decrypt.js
>decryptWithPublicKey()
- Encryption > File :
- To test :
- run
node verifyIdentity.js
- run
- This is how the JWT token is structured (three dots).
- first dot : algorithm used, second dot : payload data(orignal data in our case), and third dot : signature
- Using this token, server can calculate and verify wether the sender and data is valid or not.
NOTE:
- Here, we are sending data(orignalData) directly to
verifIdentity.js
file. But this data can also be structured in a way that JWT token is srtuctured or in some other format.
Main files are :
encrypt.js
const crypto = require('crypto')
/**
* In case of 'Data' protection, encrypt with public key
* In case of digital signatures(identities), encrypt with private key
* - for digital sig, there are two main steps involved
* - 1. Sign the message. (so that the receiver can know that the person who signed is the actual one and data has not been tampared with)
* - 2. Verify the signature.
*/
/**
*
* @param {*} publicKey
* @param {*} message message you want to encrypt
* @returns encrypted message
*/
function encryptWithPublicKey(publicKey, message) {
const bufferMessage = Buffer.from(message, 'utf8')
return crypto.publicEncrypt(publicKey, bufferMessage)
}
function encryptWithPrivateKey(privateKey, message) {
const bufferMessage = Buffer.from(message, 'utf8')
return crypto.privateEncrypt(privateKey, bufferMessage)
}
module.exports = {
encryptWithPublicKey,
encryptWithPrivateKey,
}
decrypt.js
const crypto = require('crypto')
function decryptWithPrivateKey(privateKey, encryptedMessage) {
return crypto.privateDecrypt(privateKey, encryptedMessage)
}
function decryptWithPublicKey(publicKey, encryptedMessage) {
return crypto.publicDecrypt(publicKey, encryptedMessage)
}
module.exports = {
decryptWithPrivateKey,
decryptWithPublicKey,
}
Digital signature : Signing data digitally and verifying it on receiver side.
Signing :
signMessage.js
const crypto = require('crypto')
const hash = crypto.createHash('sha256')
const fs = require('fs')
const { encryptWithPrivateKey } = require('./encrypt')
const myData = {
name: 'Saikrishna Reddy',
mobile: 1111111111,
securityNumber:
'Never keep anything personal or secret in a digitally signed message. Because this form of cryptgraphy does not hide data and others can see it!.',
}
const myDataString = JSON.stringify(myData)
hash.update(myDataString) // update method requires data to be in string format so...
//hashed data in hex format
const hashedData = hash.digest('hex')
const senderPrivateKey = fs.readFileSync(__dirname + '/id_rsa_private.pem', 'utf8')
const signedMessage = encryptWithPrivateKey(senderPrivateKey, hashedData)
// for a reciever to verify that the data is correct and has not been tampered with, he/she needs :
// algorith used, original data and signedMessage.
// So, using this data reciever can decrypt the message with the sender's public key and verify.(check verifyIdentity.js)
const packageOfDataToSend = {
algorithm: 'sha256',
originalData: myData,
signedAndEncryptedData: signedMessage,
}
module.exports = packageOfDataToSend
Verifying :
verifyIdentity.js
const crypto = require('crypto')
const fs = require('fs')
const { decryptWithPublicKey } = require('./decrypt')
let packageOfDataToSend = require('./signMessage')
// uncomment this line to tamper data🤣
// packageOfDataToSend.originalData.mobile = 2222222222
//decrypt with the senders public key as the message signed with senders private key.
const receivedData = packageOfDataToSend
const hash = crypto.createHash(receivedData.algorithm)
const senderPublicKey = fs.readFileSync(__dirname + '/id_rsa_pub.pem', 'utf8')
// here, decryptedMessage is the hash of the original data.
const decryptedMessage = decryptWithPublicKey(
senderPublicKey,
packageOfDataToSend.signedAndEncryptedData,
)
//once we get the hash of signedmessage, then calculate hash for the original data. Then these two hashes must be equal to verify successfully. If verified successfully, that means data is correct and signed by the person who said he/she signed it
const hashOriginal = hash.update(
JSON.stringify(packageOfDataToSend.originalData),
)
const hexOfHash = hash.digest('hex')
if (hexOfHash === decryptedMessage.toString()) {
console.log('verified successfully....data is correct and sender is valid!')
} else {
console.log('Data has been tampered or incorrect signature')
}