如何解密rsa_图解 Golang 实现 RSA 加密和签名(有示例)

本文介绍了RSA加密算法的基本原理和Go语言实现,包括公钥和私钥的生成、加密、解密、签名及校验过程。通过示例展示了如何在Go中使用crypto/rsa库进行操作,并提醒了在实际应用中需要注意的数据长度和哈希算法选择。
摘要由CSDN通过智能技术生成

本文介绍 RSA 干了什么,以及我们怎样用 Go 实现它。

c8366a2abfd5d9231686f01da40ec40e.png

RSA(Rivest–Shamir–Adleman)加密是使用最广的安全数据加密算法之一。

它是一种非对称加密算法,也叫”单向加密“。用这种方式,任何人都可以很容易地对数据进行加密,而只有用正确的”秘钥“才能解密。

如果你想跳过解释直接看源码,点击这里[1]

RSA 加密,一言以蔽之

RSA 是通过生成一个公钥和一个私钥进行加/解密的。公钥和私钥是一起生成的,组成一对秘钥对。

9b7f962fbbad64ba491ec6b715fd94e3.png

公钥可以用来加密任意的数据,但不能用来解密。

0d17199371069dc23f9baaf55993c1a9.png

私钥可以用来解密由它对应的公钥加密的数据。

e4ddadf43194759f9baa0443ca57048d.png

这意味着我们可以把我们的公钥给任何想给的人。之后他们可以把想发送给我们的信息进行加密,唯一能访问这些信息的方式就是用我们的私钥进行解密。

e5964bb3f86acd735c437d2f1837742b.png

秘钥的生成过程,以及信息的加密解密过程不在本文讨论范围内,但是如果你想研究详细信息,这里有一个关于此主题的强大视频[2]

秘钥的生成

我们要做的第一件事就是生成公钥私钥对。这些秘钥是随机生成的,在后面所有的处理中都会用到。

我们用标准库 crypto/rsa[3] 来生成秘钥,用 crypto/rand[4] 库来生成随机数。

// The GenerateKey method takes in a reader that returns random bits, and// the number of bitsprivateKey, err := rsa.GenerateKey(rand.Reader, 2048)if err != nil { panic(err)}// The public key is a part of the *rsa.PrivateKey structpublicKey := privateKey.PublicKey// use the public and private keys// ...

publicKey 和 privateKey 变量分别用于加密和解密。

加密

我们用 EncryptOEAP[5] 函数来加密一串随机的信息。我们需要为这个函数提供一些输入:

  1. 一个哈希函数,用了它之后要能保证即使输入做了微小的改变,输出哈希也会变化很大。SHA256 适合于此。
  2. 一个用来生成随机位的 random reader,这样相同的内容重复输入时就不会有相同的输出
  3. 之前生成的公钥
  4. 我们想加密的信息
  5. 可选的标签参数(本文中我们忽略)
encryptedBytes, err := rsa.EncryptOAEP( sha256.New(), rand.Reader, &publicKey, []byte("super secret message"), nil)if err != nil { panic(err)}fmt.Println("encrypted bytes: ", encryptedBytes)

这段代码会打印加密后的字节,看起来有点像无用的信息。

解密

如果想访问加密字节承载的信息,就需要对它们进行解密。

解密它们的唯一方法就是使用与加密时的公钥对应的私钥。

*rsa.PrivateKey 结构体有一个方法 Decrypt[6],我们使用这个方法从加密数据中解出原始的信息。

解密时我们需要输入的参数有:1. 被加密的数据(称为密文)2. 加密数据用的哈希

// The first argument is an optional random data generator (the rand.Reader we used before)// we can set this value as nil// The OEAPOptions in the end signify that we encrypted the data using OEAP, and that we used// SHA256 to hash the input.decryptedBytes, err := privateKey.Decrypt(nil, encryptedBytes, &rsa.OAEPOptions{Hash: crypto.SHA256})if err != nil { panic(err)}// We get back the original information in the form of bytes, which we// the cast to a string and printfmt.Println("decrypted message: ", string(decryptedBytes))

签名和校验

RSA 秘钥也用于签名和校验。签名不同于加密,签名可以让你宣示真实性,而不是机密性。

也就是说,由原始信息生成一段数据,称为“签名”,而不是伪装原始信息的内容(像加密[7]中做的那样)。

c8130b8b1099978474bda143ec31dd21.png

有签名、信息和公钥的任何人,可以用 RSA 校验来确保信息就是来自拥有公钥的人。如果数据和签名不匹配,校验不通过。

f35998b674b60933c8b7a3cc2bdffb30.png

请注意,只有拥有私钥的人才能对信息进行签名,但是有公钥的人可以验证它。

msg := []byte("verifiable message")// Before signing, we need to hash our message// The hash is what we actually signmsgHash := sha256.New()_, err = msgHash.Write(msg)if err != nil { panic(err)}msgHashSum := msgHash.Sum(nil)// In order to generate the signature, we provide a random number generator,// our private key, the hashing algorithm that we used, and the hash sum// of our messagesignature, err := rsa.SignPSS(rand.Reader, privateKey, crypto.SHA256, msgHashSum, nil)if err != nil { panic(err)}// To verify the signature, we provide the public key, the hashing algorithm// the hash sum of our message and the signature we generated previously// there is an optional "options" parameter which can omit for nowerr = rsa.VerifyPSS(&publicKey, crypto.SHA256, msgHashSum, signature, nil)if err != nil { fmt.Println("could not verify signature: ", err) return}// If we don't get any error from the `VerifyPSS` method, that means our// signature is validfmt.Println("signature verified")

总结

本文中我们看到了如何生成 RSA 公钥和私钥,以及怎样使用它们进行加密、解密、签名和验证任意数据。

在将它们用于你的数据之前,你需要了解一些使用限制。首先,你要加密的数据必须比你的秘钥短。例如,EncryptOAEP 文档[8] 中说“(要加密的)信息不能比公布的模数减去哈希长度的两倍后再减去 2 长”。

使用的哈希算法要适合你的需求。SHA256(在本例中用的就是 SHA256)可以用于大部分案例,但是如果是对数据要求更高的应用,你可能需要用 SHA512。

你可以在这里[9]找到所有示例的源码。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值