【密码学五】数字签名、RSA实现数字签名和验证

消息认证码&数字签名

消息认证码(message authentication code)是一种确认完整性并进行认证的技术,取三个单词的首字母,简称为MAC。

消息认证码的输入包括任意长度的消息和一个发送者与接收者之间共享的密钥,它可以输出固定长度的数据,这个数据称为MAC值

根据任意长度的消息输出固定长度的数据,这一点和单向散列函数很类似。但是单向散列函数中计算散列值时不需要密钥,而消息认证码中则需要使用发送者与接收者之间共享的密钥。

要计算MAC必须持有共享密钥,没有共享密钥的人就无法计算MAC值,消息认证码正是利用这一性质来完成认证的。此外,和单向散列函数的散列值一样,哪怕消息中发生1比特的变化,MAC值也会产生变化,消息认证码正是利用这一性质来确认完整性的。

消息认证码有很多种实现方法,大家可以暂且这样理解:消息认证码是一种与密钥相关联的单向散列函数。

Alice 和 Bob 的故事

像以前一样,我们还是从一个Alice和Bob的故事开始讲起。不过,这一次Alice和Bob分别是两家银行,Alice银行通过网络向Bob银行发送了一条汇款请求,Bob银行收到的请求内容是:

从 账 户 A − 5374 向 账 户 B − 6671 汇 款 1000 万 元 从账户A-5374 向账户B-6671汇款1000万元 A5374B66711000

当然,Bob银行所收到的汇款请求内容必须与Alice银行所发送的内容是完全一致的。如果主动攻击者Mallory在中途将Alice银行发送的汇款请求进行了篡改,那么Bob银行就必须要能够识别出这种篡改,否则如果Mallory将收款账户改成了自己的账户,那么1000万元就会被盗走。

话说回来,这条汇款请求到底是不是Alice银行发送的呢?有可能Alice银行根本就没有发送过汇款请求,而是由主动攻击者Mallory伪装成Alice银行发送的。如果汇款请求不是来自Alice银行,那么就绝对不能执行汇款。

现在我们需要关注的问题是汇款请求(消息)的 “完整性" 和 “认证" 这两个性质。

消息的完整性(integrity), 指的是:消息没有被篡改"这一性质,完整性也叫一致性。如果能够确认汇款请求的内容与Alice银行所发出的内容完全一致,就相当于是确认了消息的完整性,也就意味着消息没有被篡改。

消息的认证(authentication)指的是“消息来自正确的发送者"这一性质。如果能够确认汇款请求确实来自Alice银行,就相当于对消息进行了认证,也就意味着消息不是其他人伪装成发送者所发出的。

通过使用本章中要介绍的消息认证码,我们就可以同时识别出篡改和伪装,也就是既可以确认消息的完整性,也可以进行认证。


数字签名是一种将相当于现实世界中的盖章、签字的功能在计算机世界中进行实现的技术。使用数字签名可以识别篡改和伪装,还可以防止否认。

从消息认证到数字签名

  • 消息认证码的局限性

    消息认证码,我们可以识别消息是否被篡改或者发送者身份是否被伪装,也就是可以校验消息的完整性,还可以对消息进行认证。然而,比如在出具借条的场景中却无法使用消息认证码,因为消息认证码无法防止否认。

    消息认证码之所以无法防止否认,是因为消息认证码需要在发送者Alice和接收者Bob两者之间共享同一个密钥。正是因为密钥是共享的,所以能够使用消息认证码计算出正确MAC值的并不只有发送者Alice,接收者Bob也可以计算出正确的MAC值。由于Alice和Bob双方都能够计算出正确的MAC值,因此对于第三方来说,我们无法证明这条消息的确是由Alice生成的。

  • 通过数字签名解决问题

    下面请大家开动一下脑筋。假设发送者Alice和接收者Bob不需要共享一个密钥,也就是说,Alice和Bob各自使用不同的密钥。

    我们假设Alice使用的密钥是一个只有Alice自己才知道的私钥。当Alice发送消息时,她用私钥生成一个“签名"。相对地,接收者Bob则使用一个和Alice不同的密钥对签名进行验证。使用Bob的密钥无法根据消息生成签名,但是用Bob的密钥却可以对Alice所计算的签名进行验证,也就是说可以知道这个签名是否是通过Alice的密钥计算出来的。如果真有这么一种方法的话,那么不管是识别篡改、伪装还是防止否认就都可以实现了吧 ?

    实际上,这种看似很神奇的技术早就已经问世了,这就是数字签名(digital signature)。

    签名的生成和验证

    让我们来稍微整理一下。

    在数字签名技术中,出现了下面两种行为:

    • 生成消息签名的行为
    • 验证消息签名的行为

    生成消息签名这一行为是由消息的发送者Alice来完成的,也称为“对消息签名”。生成签名就是根据消息内容计算数字签名的值,这个行为意味着 “我认可该消息的内容"。

    验证数字签名这一行为一般是由消息的接收者Bob来完成的,但也可以由需要验证消息的第三方来完成,这里的第三方我们暂且将其命名为验证者Victor。验证签名就是检查该消息的签名是否真的属于Alice,验证的结果可以是成功或者失败,成功就意味着这个签名是属于Alice的,失败则意味着这个签名不是属于Alice的。

    在数字签名中,生成签名和验证签名这两个行为需要使用各自专用的密钥来完成。

    Alice使用“签名密钥"来生成消息的签名,而Bob和Victor则使用“验证密钥"来验证消息的签名。数字签名对签名密钥和验证密钥进行了区分,使用验证密钥是无法生成签名的。这一点非常重要。此外,签名密钥只能由签名的人持有,而验证密钥则是任何需要验证签名的人都可以持有

通过RSA实现数字签名

前边章节已经介绍过了如何通过自己编写的go代码生成非对称加密算法RSA的公钥和私钥文件, 假设公钥文件的文件名为 public.pem,私钥文件对应的文件名为 private.pem

生成数字签名
// SignatureRSA
// myData 要签名的数据
func SignatureRSA(myData []byte) ([]byte, error) {
	// 1. 从秘钥文件中读生成的秘钥内容
	fp, err := os.Open("private.pem")
	if err != nil {
		return nil, errors.New("打开私钥文件 - private.pem 失败")
	}
	// 2. 读文件内容
	fileInfo, _ := fp.Stat()
	all := make([]byte, fileInfo.Size())
	_, err = fp.Read(all)
	if err != nil {
		return nil, errors.New("读文件内容失败")
	}
	fmt.Println("文件内容: ", string(all))
	// 3. 关闭文件
	defer fp.Close()
	// 4. 将数据解析成pem格式的数据块
	block, _ := pem.Decode(all)
	// 5. 解析pem数据块, 得到私钥
	privKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
	if err != nil {
		return nil, errors.New("解析私钥失败")
	}

	// 6. 将数据通过哈希函数生成信息摘要
	myHash := sha256.New()
	myHash.Write(myData)
	result := myHash.Sum(nil)
	// 7. 生成签名
	mySignature, err := rsa.SignPKCS1v15(rand.Reader, privKey, crypto.SHA256, result)
	if err != nil {
		return nil, errors.New("生成签名失败")
	}

	return mySignature, nil
}
验证数字签名
// VerifyRSA
// src 签名数据
// myData 元数据
func VerifyRSA(src, myData []byte) error {
	// 1. 从秘钥文件中读生成的秘钥内容
	fp, err := os.Open("public.pem")
	if err != nil {
		return errors.New("打开公钥文件 - public.pem 失败")
	}
	// 2. 读文件内容
	fileInfo, _ := fp.Stat()
	all := make([]byte, fileInfo.Size())
	num, err := fp.Read(all)
	if err != nil {
		return errors.New("读文件内容失败")
	}
	fmt.Println("文件大小: ", num)
	// 3. 关闭文件
	defer fp.Close()
	// 4. 将公钥数据解析为pem格式的数据块
	block, _ := pem.Decode(all)
	// 5. 将公钥从pem数据块中提取出来
	pubInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
	if err != nil {
		return errors.New("解析公钥失败")
	}
	// 6. 公钥接口转换为公钥对象
	pubKey := pubInterface.(*rsa.PublicKey)
	// 7. 将数据通过哈希函数生成信息摘要
	myHash := sha256.New()
	myHash.Write(myData)
	result := myHash.Sum(nil)

	// 7. 数据认证
	err = rsa.VerifyPKCS1v15(pubKey, crypto.SHA256, result, src)
	if err != nil {
		return err
	}

	fmt.Println("数字签名验证成功, 恭喜o(* ̄︶ ̄*)o恭喜")
	return nil
}
  • 3
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
该项目是一个**使用Python语言基于RSA算法实现数字签名生成软件**。下面是对该软件的详细介绍: 1. **技术实现**: - 该软件使用了Python编程语言,并结合了MySQL数据库来存储密钥和其他相关信息。 - 主要技术包括Python语言、MySQL数据库以及RSA数字签名算法。 - 利用Python的RSA模块来生成公钥和私钥对,私钥用于对数据进行签名,而公钥用于验证签名的有效性。 2. **功能特点**: - 用户可以实现登录模块的安全认证。 - 提供数字签名的生成、修改和验证功能。 - 通过非对称加密确保数据传输的安全性和身份验证。 3. **应用价值**: - 对于需要安全传输和身份验证的场景非常有用,如电子商务、电子政务等领域。 - 帮助企业和个人保护他们的信息不被未授权访问或篡改。 - 可以作为学习和教育用途,帮助理解非对称加密和数字签名的原理及应用。 4. **资源内容**: - 提供了完整的Python源代码,包含实现数字签名的核心逻辑和用户界面设计等脚本。 - 包括详细的系统设计文档和技术实现说明,方便用户了解软件的工作原理和配置方法。 - 可能还包括了用于开发的依赖库和工具,以及相关的配置文件和使用示例。 总的来说,这个基于RSA算法数字签名生成软件项目不仅提供了实用的工具和资源,也为信息安全和密码学领域的研究和应用提供了有价值的参考。
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yida&yueda

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值