Rust: 加密算法库 ring 如何用于 RSA 数字签名?

本来用 rsa 库基本搞定,但文心一言建议改用 ring 库。原因是 rsa 库已经放弃维护,而 ring 库性能公认很好。但是如何进行 RSA 数字签名,网上几乎查不到这方面材料。仔细查看了 ring 库的源代码和代码注释,终于完成趟坑。总结一下供大家参考。

1. 生成密钥文件

用 RSA数字签名算法时,如何从磁盘文件加载密钥?这需要用 openssl 工具。这个工具如何下载安装不再赘述。

1.1 PEM 格式密钥文件

PEM(Privacy-Enhanced Mail)直译为“保密邮件”,但在此上下文中,它主要指的是一种用于存储加密密钥和证书的文件格式。PEM格式是一种基于ASCII编码的密钥和证书的存储格式,说白了就是文本文件,广泛用于安全领域,特别是在SSL/TLS协议中的证书和密钥管理。

以下是关于PEM格式密钥文件的详细解释:

  1. 文件内容

    • PEM文件可以包含公钥、私钥、证书等敏感信息。
    • 这些信息通常以Base64编码的形式存储,并且包含了起始标记和结束标记,以便于识别和区分不同类型的密钥和证书。
  2. 文件结构

    • PEM文件的内容通常以-----BEGIN <标签>-----开头,以-----END <标签>-----结束。
    • <标签>部分用于指示文件内容的类型,例如CERTIFICATE表示证书,PRIVATE KEY表示私钥,等等。
    • Base64编码的数据位于这两个标记之间,是实际的密钥或证书内容。
  3. 应用场景

    • PEM格式的文件在建立安全的网络连接(如HTTPS)时用于证明服务器的身份。
    • 它们也用于对数据进行加密和解密,或者进行数字签名。
    • PEM文件还可以用于构建完整的证书链,以验证服务器证书的有效性。
  4. 安全性

    • 由于PEM文件中包含了敏感的密钥和证书信息,因此需要采取一些措施来保护其安全性。
    • 可以通过严格限制访问权限、使用加密算法进行加密存储、以及采取安全通道和安全设备来传输和存储PEM文件,以防止中间人攻击和数据泄露。
  5. 与其他格式的转换

    • 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:2048

1.3 从 RSA 密钥文件导出 RSA 公钥文件

下面 openssl 命令可以从私钥文件 private_key.pem 中提取出公钥文件 public_key.pem

openssl rsa -pubout -in private_key.pem -out public_key.pem

1.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.pk8

1.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.der

1.7 关于 PEM、DER、PK8 格式的说明

PEM、DER、PK8(通常指的是PKCS#8私钥格式,但为简化讨论,这里将PK8视为PKCS#8的私钥部分的简称)是三种常见的密钥文件格式,它们各自有不同的特点和应用场景。以下是关于这三种密钥文件格式以及它们名字来历的详细说明:

1.7.1 PEM(Privacy-Enhanced Mail)
  • 来历
    • PEM格式最早由美国互联网工程任务组(IETF)在1987年的RFC 1421中定义。
    • 最初是为了解决电子邮件的加密和签名问题而设计的。
  • 特点
    • PEM格式是一种基于ASCII编码的密钥和证书的存储格式。
    • 文件通常以“.pem”为后缀名。
    • 可以包含公钥、私钥、证书等敏感信息。
    • 使用Base64编码,并且包含了起始标记和结束标记,以便于识别和区分不同类型的密钥和证书。
    • 具有良好的可读性和可编辑性。

1.7.2 DER(Distinguished Encoding Rules)

  • 来历
    • DER是一种二进制编码格式,常用于证书和密钥的存储和传输。
    • 它是ASN.1(Abstract Syntax Notation One)标准的一部分,由国际电信联盟(ITU-T)定义。
  • 特点
    • DER文件通常以“.der”或“.cer”(在某些上下文中,特别是Windows平台上,“.cer”可能用于表示DER编码的证书文件)为后缀名。
    • 与PEM格式相比,DER格式更加紧凑和高效,因为它使用二进制编码而不是Base64编码。
    • DER格式的文件不易于阅读和编辑,通常需要专业的工具才能查看和解析。

1.7.3 PKCS#8(Private-Key Cryptography Standards #8)

  • 来历
    • PKCS#8是由RSA实验室发布的一种标准,用于存储私钥信息。
    • 它是PKCS(Public-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] = b"hello, 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) -> Result<Vec<u8>, MyError> {use std::io::Read;let mut file = std::fs::File::open(path).map_err(|e| MyError::IO(e))?;let mut contents: Vec<u8> = 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] = b"hello, 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. 心得体会

  • 阅读开源库的源代码可以解决文档不足的问题。
  • 希望多展开交流,加快学习进步!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/461942.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux之nfs服务器和dns服务器

NFS服务器 NFS&#xff08;Network File System&#xff0c;网络文件系统)&#xff0c;NFS服务器可以让PC将网络中的NFS服务器共享的目录挂载到本地端的文件系统中&#xff0c;而在本地端的系统 中看来&#xff0c;那个远程主机的目录就好像是自己的一个磁盘分区一样。 注&am…

【机器学习】25. 聚类-DBSCAN(density base)

聚类-DBSCAN-density base 1. 介绍2. 实现案例计算 3. K-dist4. 变化密度5. 优缺点 1. 介绍 DBSCAN – Density-Based Spatial Clustering of Applications with Noise 与K-Means查找圆形簇相比&#xff0c;DBSCAN可以查找任意形状和复杂形状的簇&#xff0c;如S形、椭圆、半圆…

计组-层次化存储结构

这里主要看存储的整体结构&#xff0c;cache&#xff0c;内存 这里看存储结构是按什么样的层次来划分存储结构&#xff0c;速度由慢到快&#xff0c;容量由大到小&#xff0c;这是基于性价比的考虑&#xff0c;所以分为多级多层次&#xff0c;可以做到提高速度的同时没有增加多…

奇瑞不客气智驾 晚不晚?

文/孔文清 一直很好奇&#xff1a; 尹同跃董事长的金句“智驾不客气”&#xff0c;应该怎么翻译成英语&#xff1f; 谷俊丽的演讲PPT给了我答案&#xff1a; All in Ai Cars ——全力以赴、全情投入智能化汽车。 谷俊丽是奇瑞全球创新大会上最兴奋的人之一&#xff0c;有一种闭…

【万兴科技-注册_登录安全分析报告】

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 暴力破解密码&#xff0c;造成用户信息泄露短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造成亏损无底洞…

vue3中跨层传递provide、inject

前置说明 在 Vue 3 中&#xff0c;provide 和 inject 是一对用于跨组件树传递数据的 API。它们允许你在祖先组件中使用 provide 提供数据或服务&#xff0c;然后在后代组件中使用 inject 来获取这些数据或服务。这种方式特别适用于跨多个层级的组件传递数据&#xff0c;而不需要…

JAVA——网络编程

目录 1.概述 常见的网络架构 2.网络编程三要素 a.ip b.端口 c.协议 3.UDP协议 a.InetAddress类 1.概述 2.实例化对象 b.DatagramSocket类&#xff08;快递公司&#xff09; c.DatagramPacket类&#xff08;包裹&#xff09; d.单播、组播、广播 4.TCP协议 …

完全透彻了解一个asp.net core MVC项目模板1

当我们使用Visual Studio 2022去新建一个基于asp.net core Web项目的时候&#xff0c;一般有三种选择&#xff0c;一种是空项目&#xff0c;一种是基于MVC的项目、再有一种就是基于包含Razor Pages实例的web应用。如下图&#xff1a; 今天&#xff0c;我们打算选择基于MVC模…

在米尔电子MPSOC实现12G SDI视频采集H.265压缩SGMII万兆以太网推流

1. 引言 随着网络视频平台的发展&#xff0c;用户对于4K高清画质的需求日益增长。然而&#xff0c;许多用户发现&#xff0c;即使购买了视频平台的会员&#xff0c;观看4K内容时画质却不如预期&#xff0c;有时甚至还会出现模糊、卡顿的情况。这种现象背后涉及到视频编码、网络…

Matlab数字信号处理——基于改进小波变换的图像去噪方法(7种去噪算法)

1.基于小波变换的阈值收缩法去噪 该方法利用小波变换分离出信号中的噪声成分&#xff0c;并通过设置合适的阈值对小波系数进行收缩&#xff0c;保留主要信息的同时&#xff0c;去除噪声。 %基于小波变换的阈值收缩法去噪算法 clear clc Iimread(nana.png); X im2double(I); …

HTB:Analytics[WriteUP]

目录 连接至HTB服务器并启动靶机 1.How many open TCP ports are listening on Analytics? 2.What subdomain is configured to provide a different application on the target web server? 3.What application is running on data.analytical.htb? 4.What version of…

「Mac畅玩鸿蒙与硬件11」鸿蒙UI组件篇1 - Text 和 Button 组件详解

本篇将详细介绍鸿蒙应用开发中的 Text 和 Button 组件。通过本篇内容,你将学习如何使用 Text 组件显示文本、格式化文本样式,以及如何使用 Button 组件处理点击事件并自定义样式。掌握这些基本组件的用法将为后续的 UI 开发奠定基础。 关键词 Text 组件Button 组件样式设置事…

05-07实现面向对象领域模型-停车案例

学习视频来源&#xff1a;DDD独家秘籍视频合集 https://space.bilibili.com/24690212/channel/collectiondetail?sid1940048&ctype0 源代码地址&#xff1a;https://github.com/ByteBlizzard 本篇文章是讲视频中的3期内容合并为一起。 文章目录 需求模型命令聚合领域事…

如何批量裁剪图片?5个软件帮助你快速进行图片裁剪

如何批量裁剪图片&#xff1f;5个软件帮助你快速进行图片裁剪 批量裁剪图片可以通过多种工具轻松实现&#xff0c;以下5个软件可以帮助你快速裁剪大量图片&#xff1a; 万能图片编辑器 这是一款支持批量图像处理的多功能小工具&#xff0c;功能丰富且界面简单&#xff0c;支持…

vxe-table v4.8+ 与 v3.10+ 虚拟滚动支持动态行高,虚拟渲染更快了

Vxe UI vue vxe-table v4.8 与 v3.10 解决了老版本虚拟滚动不支持动态行高的问题&#xff0c;重构了虚拟渲染&#xff0c;渲染性能大幅提升了&#xff0c;行高自适应和列宽拖动都支持&#xff0c;大幅降低虚拟渲染过程中的滚动白屏&#xff0c;大量数据列表滚动更加流畅。 自适…

期权懂|开通ETF股票期权需要什么条件?ETF股票期权佣金是多少?

期权小懂每日分享期权知识&#xff0c;帮助期权新手及时有效地掌握即市趋势与新资讯&#xff01; 开通ETF股票期权需要什么条件&#xff1f;ETF股票期权佣金是多少&#xff1f; 一、开通ETF股票期权需满足以下条件&#xff1a; ‌&#xff08;1&#xff09;资金要求‌&#xf…

Lucene的概述与应用场景(1)

文章目录 第1章 Lucene概述1.1 搜索的实现方案1.1.1 传统实现方案1.1.2 Lucene实现方案 1.2 数据查询方法1.1.1 顺序扫描法1.1.2 倒排索引法 1.3 Lucene相关概念1.3.1 文档对象1.3.2 域对象1&#xff09;分词2&#xff09;索引3&#xff09;存储 1.3.3 常用的Field种类 1.4 分词…

在服务器运维过程中,发现服务器时间倒退以及DNS无法解析域名造成yum不可用的问题解决

目录 一.问题描述 二.问题排查过程 2.1yum下载NTP 2.2排查DNS 三.问题解决过程 3.1修复DNS 3.2更新yum源 3.3下载ntp 四.问题解决结果 4.1ntp服务情况检查 4.2服务器时间检查 4.3软件系统时间检查 一.问题描述 对服务器进行运维的过程中&#xff0c;发现服务器时间…

Redis高频面试题

一、Redis有什么好处? 高性能:Redis是一个基于内存的数据存储系统,相比于传统的基于磁盘的数据库系统,它能够提供更高的读写性能。支持丰富的数据类型:Redis支持多种数据结构,包括字符串、哈希、列表、集合、有序集合等,这使得它可以用于多种不同的应用场景。持久化:Re…

[POI2014] PTA-Little Bird(单调队列优化 DP)

luogu 传送门https://www.luogu.com.cn/problem/P3572 解题思路 先设 表示到 的最小劳累值。 很容易得出转移&#xff1a; 其中 由 和 的大小关系决定&#xff0c;并且 。 很显然&#xff0c;直接暴力是 的&#xff0c;会超时。 于是&#xff0c;考虑优化。 我们发现…