- 浏览: 1545295 次
- 性别:
- 来自: 厦门
-
文章分类
- 全部博客 (516)
- Java (49)
- Java/Struts 2.0 (25)
- Java/Spring、Spring MVC (11)
- Java/Quartz (3)
- Java/Lucene (6)
- Java/Hibernate (19)
- Java/openJPA (7)
- Java/DWR (7)
- Java/Security、Spring Security/OAuth2 (6)
- Java/Threading (9)
- Java/XML (22)
- java/design pattern (4)
- Android (2)
- JavaScript (46)
- jquery (3)
- DB/MySQL (23)
- DB/Oracle (16)
- PHP (25)
- CSS (20)
- Linux (38)
- C/C++、DLL、Makefile、VC++ (31)
- 正则 (9)
- Eclipse (4)
- 安全、网络等概念 (25)
- 集群 (7)
- 网页 (5)
- 视频\音频 (1)
- HTML (6)
- 计算机数学/算法 (3)
- Virtualbox (1)
- LDAP (2)
- 数据挖掘 (6)
- 工具破解 (1)
- 其他 (13)
- Mail (1)
- 药材 (3)
- 游戏 (2)
- hadoop (13)
- 压力测试 (3)
- 设计模式 (3)
- java/Swing (2)
- 缓存/Memcache (0)
- 缓存/Redis (1)
- OSGI (2)
- OSGI/Gemini (0)
- 文档写作 (0)
- java/Servlet (3)
- MQ/RabbitMQ (2)
- MQ/RocketMQ (0)
- MQ/Kafka (1)
- maven (0)
- SYS/linux (1)
- cache/redis (1)
- DB/Mongodb (2)
- nginx (1)
- postman (1)
- 操作系统/ubuntu (1)
- golang (1)
- dubbo (1)
- 技术管理岗位 (0)
- mybatis-plus (0)
最新评论
-
pgx89112:
大神,请赐我一份这个示例的项目代码吧,万分感谢,1530259 ...
spring的rabbitmq配置 -
string2020:
不使用增强器 怎么弄?
OpenJPA的增强器 -
孟江波:
学习了,楼主,能否提供一份源代码啊,学习一下,十分感谢!!!4 ...
spring的rabbitmq配置 -
eachgray:
...
spring-data-redis配置事务 -
qljoeli:
学习了,楼主,能否提供一份源代码啊,学习一下,十分感谢!!!1 ...
spring的rabbitmq配置
上一章节讨论了如何使用RSA证书加密数据,文中提到:“Dotnet的RSA实现有个特点,它必须要在明文中添加一些随机数,所以明文不能把128字节占满,实际测试,明文最多为117字节,留下的空间用来填充随机数”。也就是说对于1024位密钥的RSA来说,一次只能加密128字节的数据,对于Dotnet的RSA实现更是只能加密117个字节的数据。
这就引出一个问题,超过128字节(或者说超过117字节)的数据怎么加密?
有个办法,就是把数据明文拆分为合适大小的数据块之后逐块加密,解密时逐块的解密再拼接。事实上,DES(包括TripleDES)算法采用的就是这个办法,DES算法每次把数据明文拆分为8字节为单位的数据块,一次加密一个数据块,下一个数据块使用密钥和前一个数据块的加密结果再进行加密,如此逐块的进行加密,解密时也一样,逐块解密再拼接为明文。Dotnet提供的DES算法实现的DESCryptoServiceProvider(或TripleDESCryptoServiceProvider)类把这些拆分、加密、解密、拼接的过程都在内部实现,不需要开发人员自己去处理,对于开发人员可以认为DES可以直接一次性的加密长数据。
既然DES可以这么做,为什么RSA算法不这么做,直接在实现RSA算法的RSACryptoServiceProvider类中自动分拆加密解密拼接长数据呢?
先来看一下对称算法(以DES为代表)和非对称算法(以RSA为代表)的各自特点。
l 对称算法:
加密方和解密方使用同一个密钥,必然有个密钥传送过程,密钥的保密性有较大风险。
算法相对简单,加密解密速度很快。
l 非对称算法:
加密方使用密钥对中的公钥,解密方使用密钥对中的私钥。
算法复杂,加解密速度慢。RSA算法之所以不这么做,是因为RSA算法的复杂性导致的加密解密的速度很慢,不提倡使用RSA加密长数据,所以dotnet的RSA实现也没有这么做。当然开发者可以自己写代码实现拆分加密解密拼接的过程,实现用RSA加密长数据的功能。但是这不是个好办法,比较现实的方法是:不对称加密技术结合对称加密技术加密长数据。
具体思路是这样:
加密方生成对称加密的密钥key(包括key和IV),然后对称算法使用这个key去加密长数据,之后再用解密方提供的非对称算法的公钥publickey加密刚才生成的对称密钥key,最后把加密后的长数据和加密后的对称密钥key拼接在一起发送给解密方。
解密方接收到后,首先分解数据,把加密后的对称密钥key和加密后的长数据两部分分解开。之后使用非对称算法的私钥解密,获得对称密钥key。最后用对称密钥key解密加密的长数据。
下面以前面章节生成的RSA的证书结合TripleDES算法为例描述不对称加密技术结合对称加密技术加密长数据的具体实现过程。
Figure 13. RSA结合TripleDES算法加密解密过程
RSA证书
由解密方申请X.509的RSA证书,或者使用前面“使用makecert工具获得”章节生成的MyTestCert。解密方要把自己的RSA证书导出为cer类型的只含有公钥的证书分发给所有可能需要给自己发送加密消息的加密方。
System.Security.Cryptography. TripleDESCryptoServiceProvider类是dotnet中实现TripleDES算法的主要的类。
TripleDES算法key和IV
TripleDESCryptoServiceProvider类只有一个构造方法TripleDESCryptoServiceProvider(),这个方法把一些属性初始化:
KeySize(加密密钥长度,以位为单位)= 192(24字节)
BlockSize(加密处理的数据块大小,以位为单位)= 64(8字节)
FeedbackSize(加密数据块后返回的数据大小,以位为单位)= 64(8字节)
TripleDESCryptoServiceProvider构造方法同时会初始化一组随机的key和IV。
默认的TripleDESCryptoServiceProvider的key为24字节(也可以生成16字节的key),IV为8字节,加密数据块为8字节。
生成key和IV的代码很简单:
TripleDESCryptoServiceProvider tDESalg = new TripleDESCryptoServiceProvider();
byte[] keyArray = tDESalg.Key;
byte[] IVArray = tDESalg.IV;
RSA公钥加密TripleDES算法的key和IV
RSA公钥
加密方获得的是解密方提供的只含有公钥的cer证书,要通过读取cer证书文件来获得RSA公钥(当然,也可以把证书加载到证书储存区,然后到证书储存区读取证书获得公钥)。
//从只包含公钥的证书文件载入证书
X509Certificate2 myX509Certificate2 = new X509Certificate2(@"..\..\..\MyTestCert.cer");
//从证书中获得含公钥的RSACryptoServiceProvider
RSACryptoServiceProvider publickeyProvider = (RSACryptoServiceProvider)myX509Certificate2.PublicKey.Key;
加密key和IV
Key和IV都是是以byte[]形式存在,要把它们两个连接在一起后加密,就要考虑到解密后怎么把它们两个能够准确的分割开。
Byte[]就是字节数组, key和IV又TripleDESCryptoServiceProvider类随机生成的,每个字节可以是任意值,如果直接把key和IV的byte[]直接连在一起,加密解密后,拆分它们时,根据key和IV本身的内容就无法分割,没有区分两部分内容的标识。当然可以通过key和IV本身的长度去拆分,但是key的长度也不是完全确定的,DES算法的key是8位,TripleDES算法的key是16位或24位的,所以通过长度拆分也不是好办法。
一般的做法是在key和IV直接增加一个分隔符,两部分数据通过分隔符连接起来,以后拆分的时候根据分隔符来拆分分隔符两边的不同部分就行了。
问题又来了,既然两边的内容是随机生成的,可能是任何值,如何保证两边的内容不跟分隔符相同呢,如果碰巧要两边的内容出现跟分隔符相同的部分就麻烦了,拆分出来的数据肯定不对了。
可以对需要连接的内容做一个变换,把它们转换成另一种编码,而分隔符采用这种编码中不可能有的字符就行了。
一般的选择是base64编码,这种编码只含有64个字符,就是:大写的A-Z、小写的a-z、数字0-9、'+' 和 '/'。进一步了解base64编码,请参考:http://www.cnblogs.com/chnking/archive/2007/08/12/852669.html
把key和IV分别就行base64编码,然后设置一个分隔符(比如“ßà”这样的base64中不可能有的字符),把它们连接后再进行加密。
//使用RSA公钥加密TripleDES算法的key和IV
string keyandIV = Convert.ToBase64String(keyArray) + separator + Convert.ToBase64String(IVArray);
//用RSA公钥加密TripleDES算法的key和IV
byte[] keyandIVBytesEncrypted = publickeyProvider.Encrypt(encoding.GetBytes(keyandIV),false);
//加密后的key和IV再转为base64的字符串
string keyandIVStrEncrypted = Convert.ToBase64String(keyandIVBytesEncrypted);
//建立一个MemoryStream,这里面存放加密后的数据流
MemoryStream mStream = new MemoryStream();
// 使用MemoryStream 和key、IV新建一个CryptoStream 对象
CryptoStream cStream = new CryptoStream(mStream,
new TripleDESCryptoServiceProvider().CreateEncryptor(keyArray, IVArray),
CryptoStreamMode.Write);
//将明文字符串转成指定代码页的byte[]
byte[] plainTextArray = encoding.GetBytes(plaintext);
// 将加密后的字节流写入到MemoryStream
cStream.Write(plainTextArray, 0, plainTextArray.Length);
//把缓冲区中的最后状态更新到MemoryStream,并清除cStream的缓存区
cStream.FlushFinalBlock();
// 把加密后的数据流转成Base64的字符串
string longDataStrEncrypted = Convert.ToBase64String(mStream.ToArray());
// 关闭两个streams.
cStream.Close();
mStream.Close();
待加密的数据可能有两种形式,一种是二进制的数据,本身就是一组字节流,这样的数据可以跳过这一步,直接进入加密步骤。还有一种情况是字符串数据,字符串中同样的字符使用不同的代码页会生成不同的字节码,所以从字符串到字节流的转换是需要指定使用何种编码的。在解密之后,要从字节流转换到字符串就要使用相同的代码页解码,否则就会出现乱码。
实际上凡是在byte[]类型跟string类型直接进行转换时,都需要指定代码页,因为每种代码页对相同字符的编码是不一样的,就是说同一个字符在不同的代码页中是对应到不同的二进制码。
在本例的加密解密过程中有大量的byte[]类型跟string类型之间的转换,所以在例子中使用了预先定义了一个Encoding类型的对象encoding,utf-8代码页的,本例中所有涉及byte[]类型跟string类型之间的转换都采用同一个Encoding,保证都是用同样的代码页进行转换。
跟连接key和IV的情况一样,加密后的对称密钥和加密后的长数据也需要连接起来,同样是通过一样的分隔符连接。
//把加密的长数据用分隔符同加密后的DES的密钥连接为一个字符串
string resultEncryptedStr = longDataStrEncrypted + separator + keyandIVStrEncrypted;
//加密的数据跟加密后的key、IV连接后的base64字符串再被转成byte[]以便传送
byte[]resultEncryptedBytes = encoding.GetBytes(resultEncryptedStr);
加密过程数据存在形式变化:
Figure 14. RSA结合DES加密解密大数据数据存在形式变化过程 --加密过程
上面是加密过程,下面是解密过程。
解密过程中需要多次使用到分拆字符串功能,写个分拆字符串的方法:
/// <summary>
/// 根据分隔符,将分隔符两边的字符串分开
/// </summary>
/// <param name="value">带分隔符的字符串</param>
/// <param name="separator">分隔符</param>
/// <returns></returns>
private static string[] splitByString(string value, string separator)
{
int separatorPos = value.IndexOf(separator);
string[] returnValue = new string[2];
returnValue[0] = value.Substring(0, separatorPos);
returnValue[1] = value.Substring(separatorPos + separator.Length);
return returnValue;
}
解密方使用上面的方法把收到的数据分拆为加密的长数据和加密的对称密钥两部分
//分拆加密的长数据和加密的对称密钥
string[] EncryptedDataArray = splitByString(encoding.GetString(cryptographic), separator);
//加密的长数据
string longDataStrEncrypted = EncryptedDataArray[0];
//加密的对称密钥
string keyandIVStrEncrypted = EncryptedDataArray[1];
TripleDES算法的key和IV
RSA公钥
解密方获可以从自己的pfx证书文件来获得RSA私钥(当然,也可以把证书加载到证书储存区,然后到证书储存区读取证书获得私钥钥)。载入含有私钥的证书时,需要提供私钥保护密码。
//从证书文件载入证书,如果含有私钥的,需要提供保存证书时设置的密码
X509Certificate2 myX509Certificate2 = new X509Certificate2(@"..\..\..\MyTestCert.pfx", "password");
//从证书中获得含私钥的RSACryptoServiceProvider
RSACryptoServiceProvider privatekeyProvider = (RSACryptoServiceProvider)myX509Certificate2.PrivateKey;
解密key和IV
//加密的对称密钥base64字符串转成byte[]
byte[] keyandIVBytesEncrypted = Convert.FromBase64String(keyandIVStrEncrypted);
//解密加密的对称密钥并转成字符串
string keyandIV = encoding.GetString((publickeyProvider.Decrypt(keyandIVBytesEncrypted, false)));
//拆分key和IV
string[] keyIVArray = splitByString(keyandIV, separator);
//把key从base64字符串复原为byte[]的原始形式
byte[] keyArray = Convert.FromBase64String(keyIVArray[0]);
//把IV从base64字符串复原为byte[]的原始形式
byte[] IVArray = Convert.FromBase64String(keyIVArray[1]);
byte[] longDataBytesEncrypted = Convert.FromBase64String(longDataStrEncrypted);
// 建立一个MemoryStream,这里面存放加密后的数据流
MemoryStream msDecrypt = new MemoryStream(longDataBytesEncrypted);
// 使用MemoryStream 和key、IV新建一个CryptoStream 对象
CryptoStream csDecrypt = new CryptoStream(msDecrypt,
new TripleDESCryptoServiceProvider().CreateDecryptor(keyArray, IVArray),
CryptoStreamMode.Read);
// 根据密文byte[]的长度(可能比加密前的明文长),新建一个存放解密后明文的byte[]
byte[] DecryptDataArray = new byte[longDataBytesEncrypted.Length];
// 把解密后的数据读入到DecryptDataArray
csDecrypt.Read(DecryptDataArray, 0, DecryptDataArray.Length);
msDecrypt.Close();
csDecrypt.Close();
//解密后的长数据byte[]转成字符串
string resultSrt = encoding.GetString(DecryptDataArray);
//去掉字符串后的"\0"字符
int offset = resultSrt.IndexOf("\0");
string longData = resultSrt.Substring(0, offset);
最后获得长数据的明文,有一点需要注意。
DES加密是以8字节为一个数据块,如果明文的长度不是8字节的整数倍,DES会在明文后面添加值为0的字节凑足8字节的数据块,然后加密。这样的数据解密后,添加的”\0”仍然存在,需要去掉。
解密过程数据存在形式变化:
Figure 15. RSA结合DES加密解密大数据数据存在形式变化过程 -- 解密过程
“参考:
.NET中管理数字证书(Digital Certificate)的一些类
发表评论
-
客户端用https连接服务器的一点心得
2016-05-11 17:13 578转自:http://dannyyuan.blog.51ct ... -
解决PKIX:unable to find valid certification path to requested target 的问题
2016-05-11 17:11 945转自:http://blog.csdn.net/ ... -
cookie的secure、httponly属性设置
2014-03-04 16:19 17272转载自:http://www.cnblogs ... -
框架注入漏洞
2014-02-27 16:21 73622 详细描述 攻击者有可能注入含有恶 ... -
链接注入漏洞
2014-02-27 16:20 18773详细描述 “链接注入”是修改站点内容的行为,其方式为将外 ... -
XSS跨站脚本攻击在Java开发中防范的方法
2014-02-27 16:14 4268详细描述 跨站脚本攻击(也称为XSS)指利用网站漏洞从用 ... -
XSS跨站脚本攻击在Java开发中防范的方法
2014-02-27 09:48 7860转自:http://hi.baidu.com/hkr_tam ... -
HTTP 1.1状态代码及其含义
2011-10-20 10:16 1509下表显示了常见 ... -
使用X.509数字证书加密解密实务(二)-- 使用RSA证书加密敏感数据
2010-03-03 16:52 2858源自:http://www.cnblogs.com/chnk ... -
使用X.509数字证书加密解密实务(一)-- 证书的获得和管理
2010-03-03 16:40 3311源自:http://www.cnblogs.com/chnki ... -
X.509 数字证书结构和实例
2010-03-03 16:36 3013源自:http://www.cnblogs.com/chnki ... -
CA基本常识:X.509标准
2010-03-03 16:21 4714原文连接: http://www.cnblogs.com ... -
安全认证相关文档
2010-03-02 15:59 1113PKCS#11 中文手册 -
openssl使用手册
2009-08-04 10:28 7459OpenSSL有两种运行模式 ... -
JA-SIG(CAS)学习笔记1
2009-07-15 01:16 1380实验步骤: STEP 1,搭 ... -
公钥系统_数字签名_数字证书工作原理入门 (转)
2009-02-24 07:27 2162公钥系统 / 数字签名 / 数字证书工作原理入 ... -
详解公钥、私钥、数字证书的概念
2009-02-05 15:59 3489http://pepa.iteye.com/blog/2509 ... -
CA系统、证书常识
2009-02-05 15:58 15261.什么是CA CA是Certi ... -
密钥库文件格式(Keystore)和证书文件格式(Certificate)
2009-02-05 15:56 3295密钥库文件格式【Keystore】 格式 : ... -
java 项目的安全学习地址
2009-02-01 16:07 1536java 项目的安全学习地址: http://www.ja-s ...
相关推荐
Kotti 是一个基于 Pyramid 框架的 Python 内容管理系统(CMS),适合用来搭建中小型网站、文档库、企业展示平台、知识库等需要灵活内容结构和权限模型的项目。它本身更像一个可以二次开发的 CMS 框架,比 WordPress、Drupal 这类“一装就用”的系统更倾向于开发者定制和扩展。 这是支持pyramid2.x版本的kotti! tar -xzvf kotti1.0.tar.gz 解压缩 进入目录执行 pip install -e . 来安装, 然后执行pserve app.ini 启动。 用浏览器浏览127.0.0.1:5000 即可浏览。 用户名admin ,口令qwerty
cmd-bat-批处理-脚本-hello world.zip
知识付费系统自动采集V3.0 跳转不卡顿+搭建教程,不和外面的一样跳转卡顿,这个跳转不卡顿,支持三级分销。
在Matlab环境下,对图像进行特征提取时,主要涵盖形状、纹理以及颜色这三大关键特征。其中,对于纹理特征的提取,采用灰度梯度共生矩阵这一方法来实现。通过灰度梯度共生矩阵,可以有效地捕捉图像中像素灰度值之间在不同方向和距离上的相互关系,进而量化地反映出图像的纹理特性,为后续的图像分析、分类等任务提供重要的纹理信息依据。
该数据集为2010-2023年中国A股上市公司管理层情感语调的年度面板数据,覆盖45,320条样本,数据源自年报及半年报的"管理层讨论与分析"部分。通过构建中文金融情感词典(融合《知网情感分析用词典》与L&M金融词汇表),采用文本分析方法计算情感语调指标,包括:正面/负面词汇数量、文本相似度、情感语调1((积极词-消极词)/总词数)和情感语调2((积极词-消极词)/(积极词+消极词))。同时包含盈利预测偏差、审计意见类型等衍生指标,可用于研究信息披露质量、市场反应及代理问题。该数据复刻了《管理世界》《财经研究》等期刊的变量构建方法,被应用于分析语调操纵对债券市场的影响,学术常用度与稀缺度较高。
cmd-bat-批处理-脚本-FTIME.zip
1747829038637.png
2025年自动化X光检查机项目大数据研究报告.docx
在计算机组成原理课程设计中,我全程跟随老师的指导,独立完成了以下两项任务:一是利用Logisim软件进行原码一位乘法器的仿真设计,通过逐步搭建电路、配置逻辑单元,实现了原码乘法运算的完整流程,深入理解了原码乘法的原理和实现机制;二是完成了补码一位乘法器的Logisim仿真,同样按照老师讲解的步骤,精心设计电路,确保补码乘法运算的正确性,进一步掌握了补码乘法的运算规则和电路实现方法。通过这两个项目,我不仅巩固了理论知识,还提升了动手实践能力和逻辑思维能力。
cmd-bat-批处理-脚本-msvc2017.zip
cmd-bat-批处理-脚本-virtualcam-install.zip
二十四节气之立秋介绍.pptx
cmd-bat-批处理-脚本-shift.zip
二十四节气之小雪介绍.pptx
java、SpringBoot面试专题,6页面试题
cmd-bat-批处理-脚本-GenerateUnionWinMD.zip
二十四节气之大暑节气.pptx
python实现五子棋游戏源码
cmd-bat-批处理-脚本-TransparentConsole.zip