软装公司网站建设,买衣服app排行榜前十名,建设专业网站所需设备,旅行社销售网站建设方案本来用 rsa 库基本搞定#xff0c;但文心一言建议改用 ring 库。原因是 rsa 库已经放弃维护#xff0c;而 ring 库性能公认很好。但是如何进行 RSA 数字签名#xff0c;网上几乎查不到这方面材料。仔细查看了 ring 库的源代码和代码注释#xff0c;终于完成趟坑。总结一下供…本来用 rsa 库基本搞定但文心一言建议改用 ring 库。原因是 rsa 库已经放弃维护而 ring 库性能公认很好。但是如何进行 RSA 数字签名网上几乎查不到这方面材料。仔细查看了 ring 库的源代码和代码注释终于完成趟坑。总结一下供大家参考。
1. 生成密钥文件
用 RSA数字签名算法时如何从磁盘文件加载密钥这需要用 openssl 工具。这个工具如何下载安装不再赘述。
1.1 PEM 格式密钥文件
PEMPrivacy-Enhanced Mail直译为“保密邮件”但在此上下文中它主要指的是一种用于存储加密密钥和证书的文件格式。PEM格式是一种基于ASCII编码的密钥和证书的存储格式说白了就是文本文件广泛用于安全领域特别是在SSL/TLS协议中的证书和密钥管理。
以下是关于PEM格式密钥文件的详细解释 文件内容 PEM文件可以包含公钥、私钥、证书等敏感信息。这些信息通常以Base64编码的形式存储并且包含了起始标记和结束标记以便于识别和区分不同类型的密钥和证书。 文件结构 PEM文件的内容通常以-----BEGIN 标签-----开头以-----END 标签-----结束。标签部分用于指示文件内容的类型例如CERTIFICATE表示证书PRIVATE KEY表示私钥等等。Base64编码的数据位于这两个标记之间是实际的密钥或证书内容。 应用场景 PEM格式的文件在建立安全的网络连接如HTTPS时用于证明服务器的身份。它们也用于对数据进行加密和解密或者进行数字签名。PEM文件还可以用于构建完整的证书链以验证服务器证书的有效性。 安全性 由于PEM文件中包含了敏感的密钥和证书信息因此需要采取一些措施来保护其安全性。可以通过严格限制访问权限、使用加密算法进行加密存储、以及采取安全通道和安全设备来传输和存储PEM文件以防止中间人攻击和数据泄露。 与其他格式的转换 PEM格式与其他格式如DER、PKCS#7、PKCS#12等之间的转换是常见的需求。可以使用OpenSSL工具或其他相关工具来完成这些转换。
综上所述PEM是一种重要的密钥和证书存储格式在安全通信和数据保护方面发挥着关键作用。了解PEM格式的结构和应用场景有助于更好地管理和保护敏感信息的安全性。
1.2 生成 PEM 格式的 RSA 密钥文件
下面 openssl 命令可以生成一个名为private_key.pem 的密钥文件。该文件可以用记事本打开查看结果。
openssl genpkey -algorithm RSA -out private_key.pem -pkeyopt rsa_keygen_bits:20481.3 从 RSA 密钥文件导出 RSA 公钥文件
下面 openssl 命令可以从私钥文件 private_key.pem 中提取出公钥文件 public_key.pem。
openssl rsa -pubout -in private_key.pem -out public_key.pem1.4 PEM 密钥文件的使用
我曾用过 C 的 Crypto 库这个库可以直接使用 PEM 密钥文件加载密钥。我以为 ring 库也是如此结果非常失望。如果哪位朋友能用 ring 库直接加载希望能告知本人不胜感谢
1.5 生成 PKCS#8 密钥
私钥文件用于签名。ring 库可以导入PKCS#8 规格的密钥要求密钥文件按照 pk8 格式保存。ring 库的源代码注释提供了数字签名的方法。首先 ring 库需要的 PKCS#8 密钥证书的生成方法代码如下
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -pkeyopt rsa_keygen_pubexp:65537 | openssl pkcs8 -topk8 -nocrypt -outform der rsa-2048-private-key.pk81.6 导出公钥文件
公钥文件用于验证数字签名。ring 库可以读取 DER 格式的公钥文件。但 ring 的源代码等文档并没提供如何获得这份文件。经过反复尝试发现从私钥文件抽取公钥文件分两步进行首先生成 PEM 格式公钥文件然后再转换成 DER 格式的公钥文件。命令如下
openssl rsa -pubout -in rsa-2048-private-key.pk8 -inform DER -outform PEM -out rsa-2048-public-key.pem
openssl rsa -pubin -in rsa-2048-public-key.pem -inform PEM -RSAPublicKey_out -outform DER -out rsa-2048-public-key.der1.7 关于 PEM、DER、PK8 格式的说明
PEM、DER、PK8通常指的是PKCS#8私钥格式但为简化讨论这里将PK8视为PKCS#8的私钥部分的简称是三种常见的密钥文件格式它们各自有不同的特点和应用场景。以下是关于这三种密钥文件格式以及它们名字来历的详细说明
1.7.1 PEMPrivacy-Enhanced Mail
来历 PEM格式最早由美国互联网工程任务组IETF在1987年的RFC 1421中定义。最初是为了解决电子邮件的加密和签名问题而设计的。 特点 PEM格式是一种基于ASCII编码的密钥和证书的存储格式。文件通常以“.pem”为后缀名。可以包含公钥、私钥、证书等敏感信息。使用Base64编码并且包含了起始标记和结束标记以便于识别和区分不同类型的密钥和证书。具有良好的可读性和可编辑性。
1.7.2 DERDistinguished Encoding Rules
来历 DER是一种二进制编码格式常用于证书和密钥的存储和传输。它是ASN.1Abstract Syntax Notation One标准的一部分由国际电信联盟ITU-T定义。 特点 DER文件通常以“.der”或“.cer”在某些上下文中特别是Windows平台上“.cer”可能用于表示DER编码的证书文件为后缀名。与PEM格式相比DER格式更加紧凑和高效因为它使用二进制编码而不是Base64编码。DER格式的文件不易于阅读和编辑通常需要专业的工具才能查看和解析。
1.7.3 PKCS#8Private-Key Cryptography Standards #8
来历 PKCS#8是由RSA实验室发布的一种标准用于存储私钥信息。它是PKCSPublic-Key Cryptography Standards系列标准的一部分。 特点 PKCS#8定义了私钥的语法包括如何对私钥进行编码和加密。提供了未加密和加密两种格式的私钥存储方式。未加密的私钥信息通常以明文形式存储但编码为Base64或其他格式以方便存储和传输而加密的私钥信息则使用密码短语或其他加密算法进行保护。常与OpenSSL等工具配合使用。在较新版本的OpenSSL中生成的RSA私钥默认符合PKCS#8的PrivateKeyInfo结构。
需要注意的是虽然PEM、DER和PKCS#8在密钥和证书的存储和管理中扮演着重要角色但它们并不是互斥的。实际上它们可以相互转换并且可以在不同的应用场景中共同使用。例如可以使用OpenSSL等工具将PEM格式的私钥转换为DER格式或者将PKCS#8格式的私钥转换为PKCS#1格式的私钥尽管PKCS#1主要用于公钥的存储。
2. 实现签名与验证的源代码
下面直接贴 ring 提供的示例代码 Cargo.toml 添加下面库
ring 0.17.8程序源代码
use ring::{rand, rsa, signature};fn sign_and_verify_rsa(private_key_path: std::path::Path,public_key_path: std::path::Path)- Result(), MyError {
// Create an RSA keypair from the DER-encoded bytes. This example uses
// a 2048-bit key, but larger keys are also supported.
let private_key_der read_file(private_key_path)?;
let key_pair rsa::KeyPair::from_der(private_key_der).map_err(|_| MyError::BadPrivateKey)?;// Sign the message hello, world, using PKCS#1 v1.5 padding and the
// SHA256 digest algorithm.
const MESSAGE: static [u8] bhello, world;
let rng rand::SystemRandom::new();
let mut signature vec![0; key_pair.public().modulus_len()];
key_pair.sign(signature::RSA_PKCS1_SHA256, rng, MESSAGE, mut signature).map_err(|_| MyError::OOM)?;// Verify the signature.
let public_key signature::UnparsedPublicKey::new(signature::RSA_PKCS1_2048_8192_SHA256,read_file(public_key_path)?);
public_key.verify(MESSAGE, signature).map_err(|_| MyError::BadSignature)
}#[derive(Debug)]
enum MyError {IO(std::io::Error),BadPrivateKey,OOM,BadSignature,
}fn read_file(path: std::path::Path) - ResultVecu8, MyError {use std::io::Read;let mut file std::fs::File::open(path).map_err(|e| MyError::IO(e))?;let mut contents: Vecu8 Vec::new();file.read_to_end(mut contents).map_err(|e| MyError::IO(e))?;Ok(contents)
}我加了一段测试程序供参考
#[test]
fn test2() {let pkcs8 read_file(std::path::Path::new(rsa-2048-private-key.pk8)).unwrap();let key_pair rsa::KeyPair::from_pkcs8(pkcs8).unwrap();const MESSAGE: static [u8] bhello, world;let rng rand::SystemRandom::new();let mut signature vec![0; key_pair.public().modulus_len()];key_pair.sign(signature::RSA_PKCS1_SHA256, rng, MESSAGE, mut signature).map_err(|_| MyError::OOM).unwrap();println!(\nsignature:{:?}, signature);let public_key signature::UnparsedPublicKey::new(signature::RSA_PKCS1_2048_8192_SHA256,read_file(std::path::Path::new(rsa-2048-public-key.der)).unwrap(),);println!(\npublic_key {:?}, public_key);public_key.verify(MESSAGE, signature).unwrap();
}3. 心得体会
阅读开源库的源代码可以解决文档不足的问题。希望多展开交流加快学习进步