数字签名原理
理解数字签名的工作机制及前端应用场景
问题
数字签名是什么?它是如何工作的?
解答
数字签名是一种用于验证数据完整性和发送者身份的密码学技术。类似于手写签名,但更安全、不可伪造。
工作原理
签名过程:
原始数据 → Hash算法 → 摘要 → 私钥加密 → 数字签名
验证过程:
1. 用公钥解密签名 → 得到摘要A
2. 对原始数据做Hash → 得到摘要B
3. 比较摘要A和摘要B是否一致
前端代码示例
// 使用 Web Crypto API 实现数字签名
// 1. 生成密钥对
async function generateKeyPair() {
return await crypto.subtle.generateKey(
{
name: 'RSASSA-PKCS1-v1_5',
modulusLength: 2048,
publicExponent: new Uint8Array([1, 0, 1]),
hash: 'SHA-256'
},
true, // 可导出
['sign', 'verify']
)
}
// 2. 签名
async function sign(privateKey, data) {
const encoder = new TextEncoder()
const dataBuffer = encoder.encode(data)
const signature = await crypto.subtle.sign(
'RSASSA-PKCS1-v1_5',
privateKey,
dataBuffer
)
return signature
}
// 3. 验证签名
async function verify(publicKey, signature, data) {
const encoder = new TextEncoder()
const dataBuffer = encoder.encode(data)
const isValid = await crypto.subtle.verify(
'RSASSA-PKCS1-v1_5',
publicKey,
signature,
dataBuffer
)
return isValid
}
// 使用示例
async function demo() {
const { publicKey, privateKey } = await generateKeyPair()
const message = 'Hello, this is a signed message'
// 签名
const signature = await sign(privateKey, message)
console.log('签名完成')
// 验证
const isValid = await verify(publicKey, signature, message)
console.log('签名有效:', isValid) // true
// 篡改数据后验证
const isValidTampered = await verify(publicKey, signature, 'tampered message')
console.log('篡改后验证:', isValidTampered) // false
}
demo()
前端常见应用场景
// 1. JWT 签名验证(简化示意)
const jwt = 'header.payload.signature'
const [header, payload, signature] = jwt.split('.')
// 服务端用私钥签名,客户端/服务端用公钥验证
// 2. API 请求签名
function signRequest(params, secretKey) {
// 参数排序
const sortedParams = Object.keys(params).sort()
.map(key => `${key}=${params[key]}`)
.join('&')
// 生成签名(实际应用中使用 HMAC)
return hmacSHA256(sortedParams, secretKey)
}
// 3. 子资源完整性校验 (SRI)
// <script src="app.js"
// integrity="sha384-xxxxx"
// crossorigin="anonymous">
// </script>
关键点
- 非对称加密:私钥签名,公钥验证,私钥必须保密
- 不可伪造:没有私钥无法生成有效签名
- 不可篡改:数据被修改后签名验证会失败
- 不可否认:签名者无法否认自己的签名
- 签名 ≠ 加密:签名用于验证身份和完整性,不是为了保密数据
目录