前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >非对称加密

非对称加密

作者头像
小蜜蜂
发布于 2019-07-24 09:10:54
发布于 2019-07-24 09:10:54
88300
代码可运行
举报
文章被收录于专栏:明丰随笔明丰随笔
运行总次数:0
代码可运行

非对称加密的类型之间的关系如图所示。

加密模式

加密模式只有一种实现,即RSACryptoServiceProvider,采用的是RSA算法。DSACryptoServiceProvider只能进行认证模式,即数字签名,不能进行加密模式。

下面便以RSACryptoServiceProvider为例,来说明加密模式的实现过程。

不管是对称加密还是非对称加密,密钥都是关键。

在对称加密中,密钥可以是开发者自行设定的字符串。

对于非对称加密来说,根据算法的不同密钥的格式也不相同,并且会复杂很多。因此密钥通常是算法自动生成的,而不是由开发者来创建。

在创建RSACryptoServiceProvider类型的实例时,会自动创建一个公/私密钥对。

可以在实例上调用ToXmlString()方法来获得,ToXmlString()返回的结果不仅包含了密钥,还包含了一些其他用于优化算法执行效率的信息。

这个方法接受一个bool类型的参数:

当该参数值为true时,返回的字符串中将包含公钥和私钥;

当该参数值为false时,仅包含公钥信息。

因此,可以通过下面的语句来获得公/私密钥对,或者仅获取公钥:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
RSACryptoServiceProvider provider = new RSACryptoServiceProvider();
string publicPrivate = provider.ToXmlString(true); // 获得公/私密钥对
string publicOnly = provider.ToXmlString(false); // 只获得公钥

得到的结果类似于下面,需要注意每次执行上面的代码,得到的结果都不相同:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<!--包含公钥和私钥的XML -->
<RSAKeyValue>
    <Modulus>2hERzSJlfyX0aKuBwTgZYDUyX+kP7yOBrwPfNhWL9E/Ykq0eevDm+fqQO4M0ax+ISPkBgFEQUvWCeUS33DCmpgN0HrvJwr68RQB33LjoaNGPvJ9RyW5UquPPXc8gGiBMVAJjXIdRf0Y4abJoazsYDaeH4G5H4x2Ys+Hqqm+h3pE=</Modulus>
    <Exponent>AQAB</Exponent>
    <P>5I8eCXeqxj5UuPBV2Kbt2nYQfR4deCp7pvmjIT6YeMSkv46cKvNM6pk1NMyHslrhmZjskbR/eSW1xhZYy3H1hw==</P>
    <Q>9D92rDXFPw7y93E5qtzWsRt1801h8T8ykS8J0fy/gwlmAaM5lywZ0+PyFNeFW6rjTak688qfvUlgQBkNPiyRJw==</Q>
    <DP>SdR5TXGcdqFX2M25zVxO5QzSUrhRqKmAe/WT3n9L3WcYGNDGXZFuPTH0X/PZuaFl0qn1cTOvIcEusKgzUrSjLQ==</DP>
    <DQ>UQl9ZkWw2+sp0c9PQtFiqgBicgcKp/A/5sukhndFU0SbA5AUW4PWTecjOqcHKBLat7meRaTEuxjNRncJXceLoQ==</DQ>
    <InverseQ>qpKLZdqeM314Jc4ue7xaTN+U4iRA/DflzhinLS+WrXRKVkvbXxy+9+5kKPTsfkvE7sisQNhm/dpzs3LfxCI60A==</InverseQ>
    <D>JfVys9KY+FkTAmVYYNnzENwxuKBJNcdoe56g7Dkz84Myn9WiyKPGkR0cnj9okH0crBcsO7ngrZAu9g0QNDQDze/egPgvVfcRaubV+vqgWjgU2DmxvJC+lt0KVx7v4xuXIAlJJbyNy9dUsWqrQ/l0hVVyzY035WIHzILDRlS7oEE=</D>
</RSAKeyValue>
<!--仅包含公钥的XML -->
<RSAKeyValue>
    <Modulus>2hERzSJlfyX0aKuBwTgZYDUyX+kP7yOBrwPfNhWL9E/Ykq0eevDm+fqQO4M0ax+ISPkBgFEQUvWCeUS33DCmpgN0HrvJwr68RQB33LjoaNGPvJ9RyW5UquPPXc8gGiBMVAJjXIdRf0Y4abJoazsYDaeH4G5H4x2Ys+Hqqm+h3pE=</Modulus>
    <Exponent>AQAB</Exponent>
</RSAKeyValue>

XML节点的数据是用Base64String字符串表示的byte[]字节数组,通过ExportParameters()方法直接获得字节数组。ExportParameters()方法参数的意义与ToXmlString()方法相同:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
RSACryptoServiceProvider provider = new RSACryptoServiceProvider();
RSAParameters pPublicPrivate = provider.ExportParameters(true); // 获得公/私密钥对
RSAParameters pPublicOnly = provider.ExportParameters(false); // 只获得公钥

RSAParameters类型的属性对应XML中的节点,例如DQ、D、P等,它们的值与私钥相关,可以视为私钥由这些值组合而成。作为开发者而言,并不需要关心这些内容,可以简单地将其视为公/私密钥对。

在首次创建了公/私密钥对以后,就可以将公钥公开,将私钥保存。

在发送方发送消息前,使用接收方的公钥进行加密;

在接收方收到消息后,使用私钥进行解密。

可以创建一个RSACryptoHelper帮助类,其中包含以下两个方法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class RSACryptoHelper 
{
  // 发送方公钥加密
  public static string Encrypt(string publicKeyXml, string plainText)
  {
    RSACryptoServiceProvider provider = new RSACryptoServiceProvider();
    provider.FromXmlString(publicKeyXml); // 使用公钥初始化对象
    byte[] plainData = Encoding.UTF8.GetBytes(plainText);
    byte[] encryptedData = provider.Encrypt(plainData, true);
    return Convert.ToBase64String(encryptedData);
  }
  // 接收方私钥解密
  public static string Decrypt(string privateKeyXml, string encryptedText)
  {
    RSACryptoServiceProvider provider = new RSACryptoServiceProvider();
    provider.FromXmlString(privateKeyXml); // 使用公/私钥对初始化对象
    byte[] encryptedData = Convert.FromBase64String(encryptedText);
    byte[] plainData = provider.Decrypt(encryptedData, true);
    string plainText = Encoding.UTF8.GetString(plainData);
    return plainText;
  }
}

最后,进行以下测试:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
string plainText = "Hello, world!";
string publicKey = "...";
string encryptedText = RSACryptoHelper.Encrypt(publicKey, plainText);
Console.WriteLine(encryptedText);
string privateKey = "...";
string clearText = RSACryptoHelper.Decrypt(privateKey, encryptedText);
Console.WriteLine(clearText);

最后运行的结果如下:

数字签名

数字签名可以说是极大地优化了认证模式,并且实现起来也不会增加太多的复杂度,因此应用得更加广泛。在.NET中可以使用RSACryptoServiceProvider或者DSACryptoServiceProvider来完成数字签名。

下面继续以RSACryptoServiceProvider为例来说明这一过程。

在RSACryptoServiceProvider类型中,有一对方法SignData()和VerifyData():

SignData()用于运算原文的摘要,并对摘要进行数字签名,最后返回签名后的摘要;

VerifyData()用于重新运算消息,得出本地摘要,并解密传递进来的原始摘要,最后对本地摘要和原始摘要进行对比,并返回bool型的结果。

我们可以扩展前面的RSACryptoHelper帮助类,添加下面两个方法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//私钥签名
public static string SignData(string plainText, string privateKeyXml)
{
  RSACryptoServiceProvider provider = new RSACryptoServiceProvider();
  provider.FromXmlString(privateKeyXml);
  byte[] plainData = Encoding.UTF8.GetBytes(plainText);
  // 设置获取摘要的算法
  HashAlgorithm sha1 = HashAlgorithm.Create("SHA1");
  // 获得签名过的摘要
  byte[] signedDigest = provider.SignData(plainData, sha1);
  return Convert.ToBase64String(signedDigest);
}
//公钥验证
public static bool VerifyData(string plainText, string signature, string publicKeyXml)
{
  RSACryptoServiceProvider provider = new RSACryptoServiceProvider();
  provider.FromXmlString(publicKeyXml);
  byte[] plainData = Encoding.UTF8.GetBytes(plainText);
  byte[] signedDigest = Convert.FromBase64String(signature);
  HashAlgorithm sha1 = HashAlgorithm.Create("SHA1");
  bool isDataIntact = provider.VerifyData(plainData, sha1, signedDigest);
  return isDataIntact;
}

接下来,可以对上面的方法进行以下测试:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 发送方
string plainText = "Hello, readers";
string privateKey = "<RSAKeyValue>...</RSAKeyValue>";
string signedDigest = RSACryptoHelper.SignData(plainText, privateKey);
Console.WriteLine(signedDigest);
// 接收方
string publicKey = "<RSAKeyValue>...</RSAKeyValue>";
bool isCorrect = RSACryptoHelper.VerifyData(plainText, signedDigest, publicKey);
Console.WriteLine(isCorrect);

如果上面的publicKey和privateKey是匹配的,则返回true。如果接收方对消息plainText进行了修改,或者使用了错误的公钥,VerifyData()则会返回false.

SignData()和VerifyData()方法执行了太多的操作,大家可能理解得不够清楚。在RSACryptoServiceProvider中还有一对方法SignHash()和VerifyHash(),只针对摘要进行操作,相当于将上面的过程进行了拆分。

下面的两个方法SignData2()、VerifyData2()作用等同于前面的SignData()和VerifyData(),从简洁性来说差一些,但从步骤上来说更为清晰,便于大家理解。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//私钥签名
public static string SignData2(string plainText, string privateKeyXml)
{
  RSACryptoServiceProvider provider = new RSACryptoServiceProvider();
  provider.FromXmlString(privateKeyXml);
  byte[] plainData = Encoding.UTF8.GetBytes(plainText);
  // 设置获取摘要的算法
  HashAlgorithm sha1 = HashAlgorithm.Create("SHA1");
  // 获得原始摘要
  byte[] digestData = sha1.ComputeHash(plainData);
  // 对原始摘要签名
  byte[] signedDigest = provider.SignHash(digestData, "SHA1");
  return Convert.ToBase64String(signedDigest);
}
//公钥验证
public static bool VerifyData2(string plainText, string signedDigest, string publicKeyXml)
{
  RSACryptoServiceProvider provider = new RSACryptoServiceProvider();
  provider.FromXmlString(publicKeyXml);
  byte[] plainData = Encoding.UTF8.GetBytes(plainText);
  byte[] signedDigestData = Convert.FromBase64String(signedDigest);
  // 获得本地摘要
  HashAlgorithm sha1 = HashAlgorithm.Create("SHA1");
  byte[] digest = sha1.ComputeHash(plainData);
  // 解密签名,并判断摘要是否一致
  bool isDataIntact = provider.VerifyHash(digest, "SHA1", signedDigestData);
  return isDataIntact;
}

执行结果与前面是一样的。

全文回顾:

非对称加密的类型之间的关系

加密模式

自动创建一个公/私密钥对

数字签名

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-07-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 明丰随笔 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Silverlight中非对称加密及数字签名RSA算法的实现
RSA算法是第一个既能用于数据加密也能用于数字签名的算法。它易于理解和操作,也很流行。它的安全性是基于大整数素因子分解的困难性,而大整数因子分解问题是数学上的著名难题,至今没有有效的方法予以解决,因此可以确保RSA算法的安全性。     到目前Silverlight4 Beta发布为止,Silverlight中仍然没有提供非对称加密及数字签名相关的算法。而.NET Framework中提供的RSA等算法,都是通过操作系统提供的相关API实现的,没法移植到Silverlight中使用。因此很难实现一个健壮点的
葡萄城控件
2018/01/10
1K0
WinForm加密技术全解析
在当今数字化时代,数据安全至关重要。对于WinForm应用程序而言,保护敏感数据不被窃取或篡改是开发者必须重视的问题。加密技术作为数据安全的重要防线,能够将原始数据转换为密文,只有通过特定的密钥和算法才能还原为原始数据。本文将深入探讨WinForm中的加密技术,包括常见的加密算法及其实现方式。
郑子铭
2025/03/24
860
WinForm加密技术全解析
[信息安全] 1.密码工具箱
0. 何谓安全? 对于信息安全性的重要性,我想大家都不会否认。那么具体来说应该具有哪些特性才能称之为安全呢?举个简单的例子:我给你发送一条消息“借给我100元”,当你收到这条消息并且处理后你的账户里面会少出来100块,我的账户会多出来100块。在这个过程中,你是消息接收方,我是消息发送方。 作为通信双方的你我都不希望让其他人能读懂这条消息,这是信息的机密性,即消息在传递过程中不被其他人解读。 作为通信双方的你我都不希望消息内容变成"借老子1000块!"(操,借钱还这么牛逼,100块都不给你,还要1000块!
blackheart
2018/01/19
1.1K0
[信息安全] 1.密码工具箱
Golang与非对称加密
DSA是基于整数有限域离散对数难题的,其安全性与RSA相比差不多。DSA的一个重要特点是两个素数公开,这样,当使用别人的p和q时,即使不知道私钥,你也能确认它们是否是随机产生的,还是作了手脚。RSA算法却做不到,但是其缺点就是只能用于数字签名,不能用于加密
仙人技术
2021/12/31
1.2K0
Golang与非对称加密
C#加解密
加密解密在开发中经常用到,比如登录密码加密解密、消息传输加密解密等。但是很多人只会使用不理解其中的原理,这篇文章就带领大家快速学习加密解密的原理和使用。
喵叔
2020/09/08
1.1K0
那些常用的加密算法
MD5加密是最常见的加密方式,因为MD5是不可逆的,所以很多系统的密码都是用MD5加密保存的。
Kiba518
2020/11/26
1.2K0
那些常用的加密算法
Unity SKFramework框架(二十五)、RSA算法加密、签名工具 RSA Crypto
在调用Java后端接口,需要使用后端提供的pem私钥,在Unity中使用RSA算法对参数进行签名时,需要先将pem文件中的私钥内容转换为c#支持的xml格式再进行签名,该工具提供了转换及签名的函数,已上传至我的开发框架SKFramework中的开发工具包中,如图所示:
CoderZ
2022/08/29
9280
Unity SKFramework框架(二十五)、RSA算法加密、签名工具 RSA Crypto
c#RSA加密字符串
立羽
2023/08/24
2440
加密与安全_探索非对称加密算法_RSA算法
加密与安全_探索密钥交换算法(Diffie-Hellman算法) 中我们可以看到,公钥-私钥组成的密钥对是非常有用的加密方式,因为公钥是可以公开的,而私钥是完全保密的,由此奠定了非对称加密的基础。
小小工匠
2024/05/26
2010
对称加密与非对称加密
优点:速度快,对称性加密通常在消息发送方需要加密大量数据时使用,算法公开、计算量小、加密速度快、加密效率高。
lyb-geek
2022/03/09
2.5K0
最通俗易懂的RSA加密解密指导
RSA加密算法是一种非对称加密算法,简单来说,就是加密时使用一个钥匙,解密时使用另一个钥匙。
Kiba518
2020/06/23
1.3K0
最通俗易懂的RSA加密解密指导
RSA非对称加密
需要注意的一点,这个公钥和私钥必须是一对的,如果用公钥对数据进行加密,那么只有使用对应的私钥才能解密,所以只要私钥不泄露,那么我们的数据就是安全的。
会跳舞的机器人
2018/09/03
1.6K0
DotNet加密方式解析--数字签名
    马上就要过年回村里了,村里没有wifi,没有4G,没有流量,更加重要的是过几天电脑就得卖掉换车票了,得赶紧写几篇文章。     数据安全的相关技术在现在愈来愈变得重要,因为人们对
彭泽0902
2018/01/04
1.4K0
DotNet加密方式解析--数字签名
每日一博 - 对称加密算法 vs 非对称加密算法
我们今天来梳理一下将分别介绍这两种加密算法的优缺点,并通过Java代码实现和测试结果来验证其效果。
小小工匠
2023/05/29
4830
加解密算法分析与应用场景
在日常开发中,无论是使用何种编程语言,我们都会遇到加解密的需求。例如,为了保护接口数据安全,我们需要对数据进行加密传输;在HTTPS协议中,通过非对称加密传输客户端私钥,然后双方使用该私钥进行对称加密通信;使用MD5算法进行文件一致性校验等。然而,面对众多的加解密方案,我们往往不清楚何时使用哪种方法。本文将为您梳理当前主流的加解密技术,并对算法进行科普性说明,但不涉及具体算法分析。根据日常应用场景,加解密技术大致可分为以下四类:
不惑
2024/05/13
5780
加解密算法分析与应用场景
非对称加密之RSA是怎么加密的
前几天阿粉刚刚说了这个 MD5 加密的前世今生,因为 MD5 也确实用的人不是很多了,阿粉就不再继续的一一赘述了,今天阿粉想给大家分享的,是非对称加密中的一种,那就是 RSA 加密算法。
Java极客技术
2022/12/04
1.2K0
加密解密(RSA)非对称加密算法
RSA加解密是一种非对称加密算法,由三位数学家Rivest、Shamir和Adleman于1977年提出。它的概念是基于两个密钥:公钥和私钥。公钥用于加密数据,私钥用于解密数据。
一百减一是零
2024/08/04
2710
请看,常见的加密算法及详解都在这里!
加密算法,是现在每个软件项目里必须用到的内容。广泛应用在包括了用户登入、数字签名、数据传输等多个场合。那大家都知道那些呢?今天我把常见的加密算法全部整理在这里,供大家学习参考。
攻城狮的那点事
2019/12/10
1.5K0
了解主流加密方式:离散、对称与非对称加密算法
尊敬的读者们,大家好!今天我将为大家介绍计算机加密领域中主流的加密方式,帮助您更好地理解加密算法。我们将重点探讨离散加密、对称加密以及非对称加密算法,并以Go语言为示例进行说明。让我们一起深入了解这些关键的加密技术!
运维开发王义杰
2023/08/10
4660
了解主流加密方式:离散、对称与非对称加密算法
快速了解常用的非对称加密算法,再也不用担心面试官的刨根问底
加密算法通常被分为两种:对称加密算法和非对称加密算法。其中,对称加密算法在加密和解密时使用的密钥相同;非对称加密算法在加密和解密时使用的密钥不同,分为公钥和私钥。此外,还有一类叫做消息摘要算法,是对数据进行摘要并且不可逆的算法。
万猫学社
2022/04/22
1.6K0
快速了解常用的非对称加密算法,再也不用担心面试官的刨根问底
相关推荐
Silverlight中非对称加密及数字签名RSA算法的实现
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验