A digital signature makes tampering visible. It is data generated with a private key that lets a recipient use the corresponding public key to verify a message’s authenticity and integrity. In web applications, this matters when data travels through a client-controlled location such as a cookie or JWT: an attacker may edit a username, role, or other session value before sending it back. section 9.10 section 14.8
Treat signed client-side data as untrusted until its signature has been validated. A server accepting a JWT must validate its signature before using it as an authentication token; otherwise, altered content can be mistaken for legitimate session state. Signing protects against modification, not disclosure: clients can still read a digitally signed cookie or JWT. section 9.10 section 9.11
Use signatures where data can be changed outside server control:
- Tamperproof client-side session cookies, or encrypt them when their contents must remain secret. section 9.3 section 9.11
- Sign JWT payloads and verify the signature in every microservice that accepts the token. section 9.10
- Sign serialized content received from untrusted sources when a signature is needed to prevent data tampering. section 11.16
- Use DKIM for outgoing email by publishing a public key in DNS and signing mail with the matching private key. section 14.8
Rejecting an altered session cookie
A signed cookie can contain a value followed by its signature. To verify it, separate the tentative value, generate the expected signed form with the secret, and compare it with the received input. If the comparison fails, return false rather than accepting the changed session value. The shown Node.js implementation also uses a timing-safe comparison. section 9.10
/**
* Unsign and decode the given `input` with `secret`,
* returning `false` if the signature is invalid.
*/
exports.unsign = function(input, secret){
var tentativeValue = input.slice(0, input.lastIndexOf('.')),
expectedInput = exports.sign(tentativeValue, secret),
expectedBuffer = Buffer.from(expectedInput),
inputBuffer = Buffer.from(input);
return (
expectedBuffer.length === inputBuffer.length &&
crypto.timingSafeEqual(expectedBuffer, inputBuffer)
) ? tentativeValue : false;
};
This verification routine shows the decision point that matters: recover the original value only when the received signed input matches the expected signature; otherwise reject it. section 9.10
Signing and encryption solve different problems. Use a signature to detect unauthorized changes. Encrypt, or keep data outside the client-side session, when users must not be able to read it. Pair either choice with normal session defenses such as HTTPS, Secure cookies, HttpOnly cookies, strong server-generated session IDs, and current framework patches. section 9.11







