非对称加密 RSA

使用 openssl 命令行工具生成RSA公钥和私钥

这个命令将生成一个2048位的RSA私钥,并将其保存在文件 private.pem 中

openssl genpkey -algorithm RSA -out private.pem -pkeyopt rsa_keygen_bits:2048

以下命令从私钥中提取公钥(public.pem):

openssl rsa -pubout -in private.pem -out public.pem

为什么可以从私钥中提取公钥?

钥文件通常包含了生成密钥对所需的所有信息,包括p、q、n、e和d。因此,可以从私钥文件中提取出n和e,这两者就构成了公钥

使用 python 生成 RSA 公钥和私钥

首先安装 cryptography 包.

 pip install cryptography

以下代码使用 cryptography 来生成 RSA 公钥和私钥.

from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives import serialization

# 生成私钥
private_key = rsa.generate_private_key(
    public_exponent=65537,
    key_size=2048,
    backend=default_backend()
)

# 将私钥序列化为PEM格式
pem_private_key = private_key.private_bytes(
    encoding=serialization.Encoding.PEM,
    format=serialization.PrivateFormat.PKCS8,
    encryption_algorithm=serialization.NoEncryption()
)

# 从私钥中获取公钥
public_key = private_key.public_key()

# 将公钥序列化为PEM格式
pem_public_key = public_key.public_bytes(
    encoding=serialization.Encoding.PEM,
    format=serialization.PublicFormat.SubjectPublicKeyInfo
)

# 打印私钥和公钥
print("Private Key (PEM format):")
print(pem_private_key.decode('utf-8'))

print("\nPublic Key (PEM format):")
print(pem_public_key.decode('utf-8'))

# 你可以将私钥和公钥保存到文件中
with open('private_key.pem', 'wb') as f:
    f.write(pem_private_key)

with open('public_key.pem', 'wb') as f:
    f.write(pem_public_key)

加密和解密

公钥加密消息:

# message.txt 是要加密的原始消息文件,encrypted_message.bin 是加密后的输出文件
openssl rsautl -encrypt -in message.txt -inkey public.pem -pubin -out encrypted_message.bin

私钥解密消息:

# encrypted_message.bin 是加密后的消息文件,decrypted_message.txt 是解密后的输出文件
openssl rsautl -decrypt -in encrypted_message.bin -inkey private.pem -out decrypted_message.txt

签名和验证签名

签名涉及2步, 第一步对消息做哈希,生成 hash值, 第二步对 hash 值做加密(即签名).

python 版本签名.

from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding, rsa
from cryptography.hazmat.primitives.serialization import load_pem_private_key, load_pem_public_key

# 假设你已经有了私钥,这里我们使用之前生成的私钥
# load your private key from local file: private_key.pem
with open('private_key.pem', 'rb') as file:
    pem_private_key = file.read()

# 加载私钥
private_key = load_pem_private_key(pem_private_key, password=None, backend=default_backend())

# 要签名的消息
message = b"this is a message from https://www.tianxiaohui.com"

# 生成消息的哈希值
digest = hashes.Hash(hashes.SHA256(), backend=default_backend())
digest.update(message)
digest_value = digest.finalize()

# 使用私钥对哈希值进行签名
signature = private_key.sign(
    digest_value,
    padding.PSS(
        mgf=padding.MGF1(hashes.SHA256()),
        salt_length=padding.PSS.MAX_LENGTH
    ),
    hashes.SHA256()
)

# 打印签名
print("Signature:", signature)

# 使用公钥验证签名
# public_key = private_key.public_key()
with open('public_key.pem', 'rb') as file:
    public_key = load_pem_public_key(file.read())

try:
    public_key.verify(
        signature,
        digest_value,
        padding.PSS(
            mgf=padding.MGF1(hashes.SHA256()),
            salt_length=padding.PSS.MAX_LENGTH
        ),
        hashes.SHA256()
    )
    print("Signature is valid.")
except:
    print("Signature is invalid.")

openssl 版本

# 生成RSA密钥对
openssl genpkey -algorithm RSA -out private_key.pem -pkeyopt rsa_keygen_bits:2048
openssl rsa -pubout -in private_key.pem -out public_key.pem

# 创建一个文件进行签名
echo "This is a test message." > your_file.txt

# 使用私钥进行签名
openssl dgst -sha256 -sign private_key.pem -out signature.sig your_file.txt
# -sha256 表示使用SHA-256哈希算法。
# -sign private_key.pem 指定私钥文件。
# -out signature.sig 指定输出签名文件的名称。
# your_file.txt 是你要签名的文件。

# 使用公钥验证签名
openssl dgst -sha256 -verify public_key.pem -signature signature.sig your_file.txt

# -sha256 表示使用SHA-256哈希算法。
# -verify public_key.pem 指定公钥文件。
# -signature signature.sig 指定签名文件。
# your_file.txt 是你之前签名的文件。

公钥和私钥的格式

公钥和私钥可以以多种不同的格式保存,这些格式主要分为两大类:非加密格式和加密格式。以下是一些常见的密钥保存格式:

非加密格式

  1. PEM (Privacy Enhanced Mail) 格式:

    • 以文本形式存储,可以包含Base64编码的私钥或公钥。
    • 通常以 -----BEGIN PUBLIC KEY----------END PUBLIC KEY----------BEGIN PRIVATE KEY----------END PRIVATE KEY----- 这样的标记开头和结尾。
  2. DER (Distinguished Encoding Rules) 格式:

    • 二进制格式,通常用于存储证书和密钥。
    • 不以文本形式存储,因此不能直接编辑。
  3. PKCS#1 格式:

    • 主要用于RSA密钥。
    • 可以是PEM编码的文本格式,也可以是DER格式的二进制格式。

加密格式

  1. PKCS#8 格式:

    • 专门用于私钥的存储,可以包含加密的私钥。
    • 可以是PEM编码的文本格式,也可以是DER格式的二进制格式。
    • 如果加密,通常会有 -----BEGIN ENCRYPTED PRIVATE KEY----------END ENCRYPTED PRIVATE KEY----- 标记。
  2. PKCS#12 (PFX) 格式:

    • 用于存储私钥、公钥和证书,通常包含一个密码保护的档案。
    • .pfx.p12 为文件扩展名。
    • 支持二进制格式,可以包含多个密钥和证书。

其他格式

  1. SSH 格式:

    • 专门用于SSH密钥。
    • 私钥通常以 .ssh/id_rsa 文件形式存在,公钥以 .ssh/id_rsa.pub 文件形式存在。
    • 私钥文件通常是PEM格式,但公钥文件是SSH专用的格式。
  2. XML 格式:

    • 少见,但某些应用程序可能会使用XML格式来存储密钥。

标签: none

添加新评论