.NET_RSA加密全接触(重、难点解析)

时间:2021-10-05 10:22:43

.NET_RSA加密全接触(重、难点解析)

.NET Framework提供了两个类供我们使用RSA算法,分别是:用于加密数据的RSACryptoServiceProvider和用于数字签名的DSACryptoServiceProvider,本文主要谈论RSACryptoServiceProvider的使用以及微软实现RSA算法时的一些主要特点。

1.NETRSA密钥格式

RSA的密钥有两种表现形式,一种是通过RSAParameters对象来表现,另一种是通过XML字符串来表现,当通过默认构造函数构造一个RSACryptoServiceProvider实例的时候,会自动生成一对公私钥,可以通过调用其ExportParameters()方法或ToXmlString()方法导出密钥(分别对应前面所述的两种表现形式)。这两种表现形式的本质是一样的,前者是一个含有八个字段的结构体,后者是一个含有八个XML配置节的XMLNODE,这八个元素的名称分别为:

D、DP、DQ、Exponent、InverseQ、Modulus、Q

要了解这些元素的意义,首先需要了解构造公私钥的过程

A)      找到两个大素数P和q,相乘得n

B)      选择一个数e,它小于n且与n互素,得到公钥(e,n)

C)      得到一个数d,它满足(d*e)mod ((p-1)*(q-1))=1,得到私钥(d,n)

D)      纯文本m到密文c的加密过程c=(m^e)mod n,解密过程为m=(c^d)mod n,加密解密过程是可逆的。

了解了密钥的构造过程,下面是这八个元素的详细解释:

RSAParameters 字段

Contains

对应的 PKCS #1 字段

D

d,私钥指数

privateExponent

DP

d mod (p - 1)

exponent1

DQ

d mod (q - 1)

exponent2

Exponent

e,公钥指数

publicExponent

InverseQ

(InverseQ)(q) = 1 mod p

Coefficient

Modulus

N

Modulus

P

P

prime1

Q

Q

prime2

第三列的“PKCS”指的是一种RSA加密标准,类似于这样的标准有多个,下文会进行叙述!

2.NET中加密结果的不确定性

Net环境下对同一个字符串用相同的RSA公钥加密,每次的结果都会不一样!如下程序所示:

class Program

{

static void Main(string[] args)

{

RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();

byte[] c=rsa.Encrypt(UTF8Encoding.UTF8.GetBytes("hello"),true);

Console.WriteLine(Convert.ToBase64String(c));

Console.ReadLine();

}

}

出现这种结果不确定的原因在于:.Net为了加强RSA加密算法的安全性,在每次加密的时候都会生成一定的随机数和原始数据一起被加密,这显然不是单纯标准的RSA加密 。

其实这些随机数的生成也是遵循算法标准的,更专业的说是随机填充算法,比如NoPadding、ISO10126Padding、OAEPPadding、PKCS1Padding、PKCS5Padding、SSL3Padding,而最常见的应该是OAEPPadding【Optimal Asymmetric Encryption Padding】、PKCS1Padding;.Net支持PKCS1Padding或OAEPPadding,其中OAEPPadding仅在XP或更高版本的操作系统上可用。此处不在讨论这些填充算法的具体细节,读者朋友只需知道有这些填充标准即可,需要强调的一点是:不论是.net,java或者是C++等,只要他们用相同的填充标准,即使每次加密的结果都不一样,不同语言之间照样可以互通!

3、关于密钥的Base64编码(AQAB=65537是怎样得到的?)

大家都知道RSACryptoServiceProvider的ToXmlString()方法可以将公私钥导出到一个XML

字符串中,并且是以Base64编码的形式导出的。感兴趣的读者可以用Reflector反编译微软的dll文件,你会发现,这个方法导出的字符串就是分别对RSAParameters的八个字段(八个字节数组)进行Base64编码,然后串在一起得到的。

前面说到,当我们通过默认构造函数创建一个RSACryptoServiceProvider的实例的时候,会自动产生对应于该实例的一对儿公私钥,这种情况下微软选择的公钥都是一样的,都是65537,这个65537转化成的字节数组就是RSAParameters的Exponent的值,AQAB就是由65537编码而来。

65537的转化成的字节数组是什么样的?可能有读者会说,非常简单,一条语句就够了,用Convert.ToBase64Array(“65537”)即可!错!这样想的读者应该思考一下,此处的65537是什么?对,它是一个大素数,是一个数字,并不是一个字符串,我们应该将其转化为二进制串,然后每八位一截取,得到其对应的字节数组!此处限于篇幅不在详细叙述得到“AQAB”的详细过程,读者朋友可以参见该博客所述:http://www.cnblogs.com/midea0978/archive/2007/05/22/755826.html

4、密钥的保存

对于临时会话,无需保存密钥,但是很多情况下我们需要重复的使用一组密钥,此时就需要将密钥保存下来,在.NET中保存密钥主要有三种方法:

1、  将密钥导出到本地文件,然后对文件进行加密;

2、  利用Windows系统的数据保护API;

从Windows2000开始,Windows操作系统提供了一套密码学方面的API,称为DAPI(Data Protection API,数据保护API)。这套API由crypt32.dll库实现,可以实现用户、进程、会话或机器级别上的数据加密保护,从而确保它们的机密性,这样就使我们不再需要负责密钥的管理。

.Net中我们可以将密钥对儿保存到密钥容器中,这个密钥容器由操作系统管理,可以是用户级别的容器,也可以是机器级别的容器。密钥容器是公用的,只不过在不同的语言中有不同的实现,这样在.net中创建的公私钥对儿,C、C++程序也都可以读取。

.NET中可以使用CspParameters对象创建或使用密钥容器

1)实例化CspParameters对象CspParameters cspPara = new CspParameters();

2)指定CspParameters对象实例的名称 ,cspPara.KeyContainerName = "test"。如果名称为key_container_test的密钥容器不存在,RSA对象会创建这个密钥容器;如果名称为key_container_test的密钥容器已经存在,RSA对象会使用这个密钥容
器。
        
   3)设置密钥类型为Exchange ,cspPara.KeyNumber = 1;
   4)设置密钥容器保存到计算机密钥库(默认为用户密钥库,cspPara.Flags =  CspProviderFlags.UseMachineKeyStore

3、  利用数字证书

此处不再详述,参考文档1、“.NET中非对称加密RSA算法的密钥保存

2、“了解计算机级别和用户级别的 RSA 密钥容器

5、.net和java端的RSA互通

.net和java的RSA互通要谈论的东西比较多,请参见另一篇文章“.NET和Java的RSA互通,仅此而已!”

.NET_RSA加密全接触(重、难点解析)的更多相关文章

  1. LUA重难点解析

    1.元表 元表也是一个 table,它附加在另一个 table 上,可以扩展该 table 的某些行为. 拿 __index 来举例,它是用来扩展查找索引行为的.在查找一个 key 对应的值时,会依次 ...

  2. Collection集合重难点梳理,增强for注意事项和三种遍历的应用场景,栈和队列特点,数组和链表特点,ArrayList源码解析, LinkedList-源码解析

    重难点梳理 使用到的新单词: 1.collection[kəˈlekʃn] 聚集 2.empty[ˈempti] 空的 3.clear[klɪə(r)] 清除 4.iterator 迭代器 学习目标: ...

  3. web前端学习(三)css学习笔记部分(8)-- SVN的介绍和应用、CSS动画效果、CSS3布局属性全接触

    15.SVN的介绍和应用 15.1.SVN的介绍和应用课程概要 将代码进行集中管理,有版本号的进行迭代,方便集体工作的build流程 15.2.SVN的介绍 SVN是Subversion的简称,是一个 ...

  4. 李洪强漫谈iOS开发[C语言-008]- C语言重难点

      C语言学习的重难点 写程序的三个境界: 照抄的境界,翻译的境界,创新的境界 1  伪代码: 描述C语言的编程范式 范式: 规范的一种表示 对于C的范式学会的话,C, C++ Java 都会了 2 ...

  5. STM32 CAN总线标识符过滤器难点解析

    STM32 CAN总线标识符过滤器难点解析 原创 2016年05月31日 15:12:24 标签: stm32 / CAN 4910 CAN总线是目前应用非常多的一种总线,在汽车电子,航空航天中应用广 ...

  6. 【转】Microsoft .Net Remoting之Remoting事件处理全接触

    Remoting事件处理全接触 前言:在Remoting中处理事件其实并不复杂,但其中有些技巧需要你去挖掘出来.正是这些技巧,仿佛森严的壁垒,让许多人望而生畏,或者是不知所谓,最后放弃了事件在Remo ...

  7. English--音标重难点

    English|音标重难点 在拥有了,音标的元音与辅音的基础之后,需要对于这些音标进行加以区分,毕竟方言对于口型的影响非常的大. 前言 目前所有的文章思想格式都是:知识+情感. 知识:对于所有的知识点 ...

  8. 这是一份非常适合收藏的Android进阶/面试重难点整理

    写在前面 记得我大二时“不务正业”地自学Android并跟了老师做项目,到大三开始在目前的公司实习,至今毕业已有几年多,学习Android已经6.7年多了!但总感觉知识点很零散,并且不够深入,遇到瓶颈 ...

  9. 《十天学会 PHP》的重难点

    记录一下我在学习<十天学会 PHP>(第六版)的过程中的遇到的重难点,该课程是学习制作一个简单的留言板. 准备工作 XAMPP(Apache + MySQL + PHP + PERL) 是 ...

随机推荐

  1. LCLFramework框架之Plugin模式

    插件应用架构概述 基于LCLFramework插件框架的应用由以下三个部分构成: (1)主程序:针对特定应用环境(Web.WinForm等应用环境),加载启动插件,获取插件入口,运行入口程序. (2) ...

  2. SQL的定义与使用

    一.SQL的定义 SQL(structured query language)即结构化查询语句,是关系数据库的标准语言. SQL的特点有: 1.综合统一 SQL集数据定义语言DDL.数据操作语言DML ...

  3. 读书笔记--用Python写网络爬虫02--数据抓取

    抓取(scraping)---爬虫从网页中抽取一些数据用以实现某些用途. 三种抽取网页数据的方法:正则表达式.Beautiful Soup和lxml. 2.1 分析网页 通过浏览器自带选项,查看网页源 ...

  4. 10分钟精通SharePoint - SharePoint升级

    类型: b2b(安装更新)和v2v(跨版本升级) 内容:二进制文件和数据库 过程:   升级前检查 - 检查场内数据,配置和自定义等等 升级准备和计划 - 根据需要和升级检查制定相应计划和准备工作   ...

  5. Windows-universal-samples-master示例 XamlCommanding

    Windows-universal-samples-master XamlCommanding 运行默认如果是 ARM会出现没有引用System,只要在调试选择CPU为PC的就好 默认 选择PC平台 ...

  6. &lbrack;bzoj4849&rsqb;&lbrack;Neerc2016&rsqb;Mole Tunnels

    来自FallDream的博客,未经允许,请勿转载,谢谢 貌似是省队集训女队讲的题... 今天在bzoj找一道题无果,但是翻到了这道就顺便写了下. 鼹鼠们在底下开凿了n个洞,由n-1条隧道连接,对于任意 ...

  7. 使用vue开发项目需要注意的问题和可能踩到的坑

    最近,在公司给一些刚刚使用vue进行开发的同学做了一次分享, 其中包括一些vue开发中需要注意的点, 以及一些可能会踩到的坑.具体内容如下: 一.生命钩子使用需要注意的地方 1.beforeCreat ...

  8. centos6&period;8下源码编译安装tmux

    1. 获取源码 git clone https://github.com/tmux/tmux.git ~/tmux 2. 准备工作 2.1 安装ncurses开发库 yum install ncurs ...

  9. servlet初认知(持续更新中)

    一:前言: 一个Servlet程序其实就是一个实现了Java特殊接口的类,它由支持Servlet(具有Servlet引擎)的WEB服务器调用和启动运行.一个Servlet程序负责处理它对应的一个或者多 ...

  10. javaweb-简单的验证码和算术验证码

    我们登陆网站时,每次都会填写一些验证码,这些验证码的作用:防止被恶意攻击,验证码上面的字母数字一般都是随机生成的,因此我们首先要写一个方法生成一个随机的字符串,这里就需要java里面的随机函数Rand ...