数字签名和相关的加密算法-RSA/DSA/ECC

223 阅读4分钟

以下是关于数字签名和相关加密算法的详细介绍:

1. 数字签名的概念

  • 定义

    • 数字签名是一种用于验证数字信息(如文档、消息、软件等)的真实性和完整性的技术。它使用公钥密码学,通过私钥对消息进行签名,接收方可以使用对应的公钥验证签名是否是使用相应私钥生成的,并且消息在传输过程中是否被篡改。
  • 工作原理

    • 签名生成

      • 发送方使用私钥对消息的哈希值(使用哈希函数计算得到)进行加密,得到的结果就是数字签名。
      • 哈希函数将任意长度的消息转换为固定长度的哈希值,如 SHA-256 算法将消息转换为 256 位的哈希值。
    • 验证过程

      • 接收方使用发送方的公钥对数字签名进行解密,得到哈希值。
      • 接收方对收到的消息使用相同的哈希函数计算哈希值。
      • 将解密得到的哈希值和新计算的哈希值进行比较,如果相等,说明消息未被篡改,并且是由持有相应私钥的发送方发送的。

2. 相关的加密算法

公钥加密算法

  • RSA(Rivest-Shamir-Adleman)

    • 特点

      • RSA 是一种广泛使用的公钥加密算法,它基于大数分解的数学难题。
      • 可用于加密和数字签名。对于加密,使用接收方的公钥加密消息,接收方使用自己的私钥解密;对于数字签名,使用发送方的私钥签名,接收方使用发送方的公钥验证。
    • 示例代码(Node.js 中使用 RSA 进行数字签名)

收起

javascript

const crypto = require('crypto');
const { privateKey, publicKey } = crypto.generateKeyPairSync('rsa', {
  modulusLength: 2048,
  publicKeyEncoding: {
    type: 'spki',
    format: 'pem'
  },
  privateKeyEncoding: {
    type: 'pkcs8',
    format: 'pem'
  }
});

const message = 'Hello, World!';
const sign = crypto.createSign('SHA256');
sign.update(message);
const signature = sign.sign(privateKey, 'base64');

const verify = crypto.createVerify('SHA256');
verify.update(message);
const isVerified = verify.verify(publicKey, signature, 'base64');
console.log(isVerified); 
  • 解释

    • crypto.generateKeyPairSync 生成 RSA 公钥和私钥对。
    • crypto.createSign 创建签名对象,使用 SHA256 哈希算法对消息进行签名。
    • sign.sign(privateKey, 'base64') 使用私钥对消息签名并转换为 base64 编码。
    • crypto.createVerify 创建验证对象,使用 SHA256 哈希算法对消息进行验证。
    • verify.verify(publicKey, signature, 'base64') 用公钥验证签名。
  • DSA(Digital Signature Algorithm)

    • 特点

      • DSA 主要用于数字签名,基于离散对数问题。它比 RSA 速度快,但通常仅用于签名,不能用于加密。
    • 示例代码(Python 中使用 DSA 进行数字签名)

收起

python

from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import dsa
from cryptography.hazmat.primitives import serialization

private_key = dsa.generate_private_key(
    key_size=1024
)
public_key = private_key.public_key()

message = b"Hello, World!"
signer = private_key.signer(hashes.SHA256())
signer.update(message)
signature = signer.finalize()

verifier = public_key.verifier(signature, hashes.SHA256())
verifier.update(message)
print(verifier.verify())
  • 解释

    • dsa.generate_private_key 生成 DSA 私钥,private_key.public_key() 获取公钥。
    • private_key.signer(hashes.SHA256()) 创建签名对象,使用 SHA256 哈希算法。
    • signer.update(message) 更新要签名的消息。
    • signer.finalize() 完成签名。
    • public_key.verifier(signature, hashes.SHA256()) 创建验证对象。

椭圆曲线密码学(ECC)

  • ECDSA(Elliptic Curve Digital Signature Algorithm)

    • 特点

      • ECDSA 是基于椭圆曲线密码学的数字签名算法,提供与 RSA 相同的安全级别,但使用更短的密钥长度,因此在性能和空间上更有优势。
    • 示例代码(Java 中使用 ECDSA 进行数字签名)

收起

java

import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.Signature;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.spec.ECGenParameterSpec;

public class ECDSASignature {
    public static void main(String[] args) throws Exception {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC");
        keyPairGenerator.initialize(new ECGenParameterSpec("secp256r1"), new SecureRandom());
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        PrivateKey privateKey = keyPair.getPrivate();
        PublicKey publicKey = keyPair.getPublicKey();

        String message = "Hello, World!";
        Signature ecdsaSign = Signature.getInstance("SHA256withECDSA");
        ecdsaSign.initSign(privateKey);
        ecdsaSign.update(message.getBytes());
        byte[] signature = ecdsaSign.sign();

        Signature ecdsaVerify = Signature.getInstance("SHA256withECDSA");
        ecdsaVerify.initVerify(publicKey);
        ecdsaVerify.update(message.getBytes());
        boolean isVerified = ecdsaVerify.verify(signature);
        System.out.println(isVerified);
    }
}
  • 解释

    • KeyPairGenerator.getInstance("EC") 获取 ECDSA 密钥对生成器。
    • keyPairGenerator.initialize(new ECGenParameterSpec("secp256r1"), new SecureRandom()) 初始化生成器。
    • Signature.getInstance("SHA256withECDSA") 获取 ECDSA 签名和验证对象。
    • ecdsaSign.initSign(privateKey) 初始化签名,ecdsaSign.update(message.getBytes()) 更新消息,ecdsaSign.sign() 完成签名。

3. 应用场景

软件分发

  • 软件开发者使用数字签名对软件包进行签名,用户下载软件后可以使用开发者的公钥验证签名,确保软件未被篡改和确实来自开发者。

电子邮件安全

  • 发送方对邮件内容进行数字签名,接收方使用发送方的公钥验证,确保邮件内容的真实性和完整性。

电子商务和金融交易

  • 数字签名可用于验证交易信息,确保交易的不可抵赖性和安全性,防止篡改和伪造。

4. 总结

  • 数字签名使用公钥密码学,结合哈希函数,确保数字信息的真实性和完整性。不同的加密算法(如 RSA、DSA、ECDSA)各有特点,可根据不同的场景和需求进行选择。在开发中,要注意密钥的管理和存储,确保私钥的安全性,防止私钥泄露导致签名的安全性受到威胁。