Issue
I want to be able to ensure that the public and private key are valid. I would be storing the public key on the server rather than each request which is uploaded by a user. However, it won’t be allowed to be sent.
server.js(Server)
const express = require('express')
const crypto = require("crypto")
const fetch = require("node-fetch")
const app = express()
const port = 3002
app.get('/', async (req, res) => {
var res2 = await fetch('http://localhost:3001/data')
var verifiableData = await res2.text()
var res2 = await fetch('http://localhost:3001/key')
var publicKey = await res2.text()
var res2 = await fetch('http://localhost:3001/sig')
var signature = await res2.text()
const isVerified = crypto.verify(
"sha256",
Buffer.from(verifiableData),
{
key: publicKey,
padding: crypto.constants.RSA_PKCS1_PSS_PADDING,
},
signature
)
res.send(isVerified)
})
app.listen(port, () => {
console.log(`Listening at http://localhost:${port}`)
})
index.js(Client)
const express = require('express')
const crypto = require("crypto")
const app = express()
const port = 3001
const { publicKey, privateKey } = crypto.generateKeyPairSync("rsa", {
// The standard secure default length for RSA keys is 2048 bits
modulusLength: 2048,
})
const verifiableData = "this need to be verified"
const signature = crypto.sign("sha256", Buffer.from(verifiableData), {
key: privateKey,
padding: crypto.constants.RSA_PKCS1_PSS_PADDING,
})
app.get('/data', (req, res) => {
res.send(verifiableData)
})
app.get('/sig', (req, res) => {
res.send(signature.toString("base64"))
})
app.get('/key', (req, res) => {
res.send(publicKey)
})
app.listen(port, () => {
console.log(`Listening at http://localhost:${port}`)
})
I know I should be requesting the information from the server rather than the client but I am just trying to get it working.
I got this error with the server.js code with the signature
(node:19312) UnhandledPromiseRejectionWarning: TypeError [ERR_INVALID_ARG_TYPE]: The "signature" argument must
be an instance of Buffer, TypedArray, or DataView. Received type string ('OFEush86vZIuFnTLFBiFt4Be...)
at Object.verifyOneShot [as verify] (internal/crypto/sig.js:212:11)
at C:\Users\user\Documents\coding\nodestuff\stesting\server\server.js:20:31
at processTicksAndRejections (internal/process/task_queues.js:97:5)
(node:19312) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:19312) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise
rejections that are not handled will terminate the Node.js process with a non-zero exit code.
Updated the index.js to
app.get('/sig', (req, res) => {
res.send(signature.toString("base64"))
})
And the server.js to
const isVerified = crypto.verify(
"sha256",
Buffer.from(verifiableData),
{
key: publicKey,
padding: crypto.constants.RSA_PKCS1_PSS_PADDING,
},
Buffer.from(signature, 'base64')
)
Then got this an error:
(node:5580) UnhandledPromiseRejectionWarning: Error: error:0909006C:PEM routines:get_name:no start line
at Object.verifyOneShot [as verify] (internal/crypto/sig.js:219:10)
at C:\Users\user\Documents\coding\nodestuff\stesting\server\server.js:20:31
at processTicksAndRejections (internal/process/task_queues.js:97:5)
(node:5580) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:5580) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
It works perfectly fine in a single file just doesn’t work when sent over an express API. How do I fix the error/errors?
Solution
What needed to be done was that the publicKey was invalid. This is because it was a PublicKeyObject
meaning it wouldn’t be sent with express leaving the value as {}
I had to do
const { publicKey, privateKey } = crypto.generateKeyPairSync("rsa", {
// The standard secure default length for RSA keys is 2048 bits
publicKeyEncoding: {
type: 'spki',
format: 'pem'
},
modulusLength: 2048,
})
As well as using this in the signature part.
Buffer.from(signature, 'base64')