数字签名原理

理解数字签名的工作机制及前端应用场景

问题

数字签名是什么?它是如何工作的?

解答

数字签名是一种用于验证数据完整性和发送者身份的密码学技术。类似于手写签名,但更安全、不可伪造。

工作原理

签名过程:
原始数据 → 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>

关键点

  • 非对称加密:私钥签名,公钥验证,私钥必须保密
  • 不可伪造:没有私钥无法生成有效签名
  • 不可篡改:数据被修改后签名验证会失败
  • 不可否认:签名者无法否认自己的签名
  • 签名 ≠ 加密:签名用于验证身份和完整性,不是为了保密数据