Abel'Blog

我干了什么?究竟拿了时间换了什么?

0%

go-rsa

概述

rsa是一个基础组件,处理非对称加密的工作。

rsa一般指rsa加密算法。RSA加密算法是一种非对称加密算法。在公开密钥加密和电子商业中RSA被广泛使用。1977年由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的。

  • 需要搞清楚一件事情,理解流程,理解概念很重要。然后才是工程上具体的实施。
  • 写文章的原则“豹头、猪肚、凤尾”。

概念

签名

RSA签名流程主要包括以下步骤:

  1. 对要签名的数据(消息)进行哈希处理,得到消息摘要。
  2. 使用私钥对消息摘要进行加密,得到签名。
  3. 将签名和原始消息一起传输或者存储。

加密

RSA是一种非对称加密技术,其中包含公钥和私钥。公钥可以用于加密数据,私钥可以用于解密数据。下面是RSA的加密和解密过程:

生成一对公钥和私钥。

  1. 选择两个大质数p和q。
  2. 计算n = p * q和φ(n)=(p-1)(q-1)。
  3. 选择一个整数e,使得1 < e < φ(n),且e与φ(n)互质。
  4. 计算d,使得d * e ≡ 1 (mod φ(n)),即d是e关于模φ(n)的乘法逆元。
  5. 将n和e封装成公钥,将n和d封装成私钥。
    加密过程:

  6. 对要加密的数据(明文)进行哈希处理,得到消息摘要M’。

  7. 使用公钥对消息摘要进行加密,得到密文C。具体地,将消息摘要M’用二进制表示成位串,然后对位串进行填充,生成一个长度为k的多项式f(x),然后计算f(0)、f(1)、…、f(k-1),得到一个k位的密文C。
  8. 将密文C传输给接收方。
    解密过程:

  9. 使用私钥对密文进行解密,得到消息摘要M’’。

  10. 对解密后的消息摘要进行哈希处理,得到明文M。
  • 注意:在加密过程中,不需要输入私钥进行加密,而是输入公钥进行加密。

pkcs#1 pkcs#8

PKCS#1和PKCS#8是两个不同的标准,分别用于定义RSA密钥对的表示格式和RSA私钥的表示格式。

PKCS#1定义了RSA密钥对的表示格式,其中包括公钥和私钥的编码格式和算法参数。它规定了RSA密钥对的生成、加密、解密和签名验证等操作的标准实现方法。

PKCS#8定义了存储和管理私钥的标准格式,其中包括私钥的编码格式和算法参数。它规定了RSA公钥和私钥的生成、加密、解密和签名验证等操作的标准实现方法。

因此,PKCS#1和PKCS#8的主要区别在于它们定义的内容不同。PKCS#1主要用于定义RSA密钥对的表示格式,而PKCS#8主要用于定义RSA私钥的表示格式。

PKCS#8标准定义的是存储和管理私钥的格式,并不包含公钥的信息。因此,PKCS#8私钥中并不包含公钥。

在PKCS#8标准中,私钥的格式定义包括了私钥的算法、模数、私钥的哈希代码等信息。而公钥的信息通常是在证书中存储的,因此如果需要使用PKCS#8私钥进行加密解密等操作,需要将其转换为包含公钥的证书格式。

在Go语言中,如果您需要从PKCS#8格式的私钥中提取公钥,可以使用crypto/x509包中的ParsePKCS8PrivateKey()函数将私钥解析为rsa.PrivateKey结构体,然后使用x509.MarshalPKCS1PublicKey()函数将rsa.PrivateKey结构体转换为PKCS#1格式的公钥。

工程实践

加密解密

在这个示例中,我们使用Go语言实现了RSA加密和解密过程。我们首先使用rsa.GenerateKey()函数生成一个2048位的公钥和私钥对。然后,我们使用rsa.EncryptOAEP()函数使用公钥加密数据,并使用rsa.DecryptOAEP()函数使用私钥解密数据。最后,我们输出原始数据、加密后的数据和解密后的数据。请注意,加密和解密过程都需要使用随机数生成器,以增加安全性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package main  

import (
"fmt"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"encoding/base64"
)

func main() {
// 生成公钥和私钥
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
panic(err)
}
pub := &privateKey.PublicKey

// 加密数据
message := []byte("Hello, world!")
envelope, err := rsa.EncryptOAEP(sha256.New(), rand.Reader, pub, message, nil)
if err != nil {
panic(err)
}

// 解密数据
decrypted, err := rsa.DecryptOAEP(sha256.New(), rand.Reader, privateKey, envelope, nil)
if err != nil {
panic(err)
}

// 输出结果
fmt.Printf("原始数据:%s\n", message)
fmt.Printf("加密后的数据:%s\n", base64.StdEncoding.EncodeToString(envelope))
fmt.Printf("解密后的数据:%s\n", string(decrypted))
}

签名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
package main  

import (
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"encoding/base64"
"fmt"
)

func main() {
// 原始数据
data := []byte("Hello, world!")

// 生成私钥和公钥
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
panic(err)
}
publicKey := &privateKey.PublicKey

// 使用私钥进行签名
hashed := sha256.Sum256(data)
signature, err := rsa.SignPKCS8(rand.Reader, privateKey, crypto.SHA256, hashed[:])
if err != nil {
panic(err)
}

// 将签名转换为字符串
signatureBytes := signature.ToWire().Data()
signatureBase64 := make([]byte, base64.StdEncoding.EncodedLen(len(signatureBytes)))
base64.StdEncoding.Encode(signatureBase64, signatureBytes)

// 使用公钥进行验证
if rsa.VerifyPKCS8(publicKey, crypto.SHA256, hashed[:], signature) == nil {
fmt.Println("Signature verified successfully")
} else {
fmt.Println("Signature verification failed")
}

// 输出结果
fmt.Printf("Original data: %s\n", data)
fmt.Printf("Encrypted data: %s\n", base64.StdEncoding.EncodeToString(hashed[:]))
fmt.Printf("Signature: %s\n", string(signatureBase64))
}

在这个示例代码中,我们使用rsa.GenerateKey()函数生成一个2048位的私钥和公钥对。然后,我们使用rsa.SignPKCS8()函数使用私钥对原始数据进行SHA256哈希,并使用RSA-PKCS#8算法对哈希值进行签名。签名后,我们将签名转换为字符串,并使用rsa.VerifyPKCS8()函数使用公钥验证签名的正确性。最后,我们输出原始数据、加密后的数据和签名。请注意,在RSA-PKCS#8签名中,需要指定填充方案为rsa.PSSS,并且在验证时需要指定公钥格式为PKCS#8格式。

go补充资料

x509

在Go语言中,x509是一个用于处理X.509证书和密钥的库。X.509是一种公钥基础设施(PKI)标准,用于定义和管理数字证书的格式和用法。x509库提供了用于解析、验证和创建X.509证书的功能。

x509库提供了以下主要功能:

  1. 证书解析:x509库允许您解析和读取X.509证书,包括证书链中的多个证书。您可以提取证书的有效期、主题和颁发者信息,以及密钥用法和扩展字段等其他属性。
  2. 证书验证:x509库允许您验证证书的有效性,包括验证证书链的完整性、检查证书的过期日期、以及确保证书不被撤销等。
  3. 证书创建:x509库还提供了创建X.509证书的功能,允许您生成新的证书请求(CSR),自签名证书,或者创建包含特定属性和扩展的证书。
  4. 密钥管理:x509库还提供了一些用于管理RSA、DSA和ECDSA等常见密钥类型的函数。您可以生成和销毁密钥,以及使用它们来加密和解密数据。

通过x509库,您可以方便地处理数字证书和密钥,确保安全地在应用程序中使用它们。

Linux相关的命令行

RSA是一种非对称加密算法,常用于加密和数字签名。在Linux中,可以使用以下指令来生成和使用RSA密钥对:

生成RSA密钥对
使用openssl命令可以生成RSA密钥对,可以在终端中执行以下命令:

openssl genpkey -algorithm RSA -out private.key
该命令将生成一个2048位的RSA密钥对,并将其保存在private.key文件中。

从私钥文件中读取私钥
可以使用以下命令从私钥文件中读取私钥:

openssl rsa -in private.key -out private_key.pem -passin pass:password
其中private.key是私钥文件的路径,password是保护私钥的密码。该命令将读取私钥并将其保存在private_key.pem文件中。

从公钥文件中读取公钥
可以使用以下命令从公钥文件中读取公钥:

openssl rsa -in public.key -out public_key.pem
其中public.key是公钥文件的路径。该命令将读取公钥并将其保存在public_key.pem文件中。

使用RSA密钥对加密和解密数据
可以使用以下命令使用RSA密钥对加密和解密数据:

1
2
openssl rsautl -encrypt -inkey private.key -pubin -in data.txt -out data.encrypted  
openssl rsautl -decrypt -inkey public.key -in data.encrypted -out data.decrypted

其中private.key是私钥文件的路径,public.key是公钥文件的路径,data.txt是要加密的数据文件的路径,data.encrypted是加密后的数据的路径,data.decrypted是解密后的数据的路径。

  • 注意:在使用RSA密钥对加密和解密数据时,需要使用相同的RSA密钥对。

引用