一般对接第三方的接口时,接口提供方如果要求以RSA方式进行加密传输,并且给了你一串字符串说是RSA加密公钥,那么该公钥一般是PEM格式文件的base64字符串表现形式。
完整PEM格式示例:
1:示例证书:
-----BEGIN RSA PRIVATE KEY-----
base64字符串
-----END RSA PRIVATE KEY-----
注意其格式,接口提供方有可能只给你中间的base64字符串,也有可能将完整的格式内容都给你,那么你要留意去除除了base64字符串内容之外的头尾以及空行。
那么问题来了,在C#的RSA加密工具类RSACryptoServiceProvider中,并没有支持PEM格式公钥为基准的加密方法,只能用一种.net平台认可的xml字符串的公钥才能够进行加密。
RSACryptoServiceProvider _rsa = new RSACryptoServiceProvider();
_rsa.FromXmlString(publickey);//这里的公钥指定只能是平台认可的xml字符串格式,直接传入pem的base64是不行的
byte[] cipherbytes = _rsa.Encrypt(_b, false);//进行加密
想要从pem公钥转为xml公钥,只能依赖于一个第三方库,叫做BouncyCastle
然后用以下方法进行转换:
/// <summary>
/// RSA公钥pem的base64字符串-->XML格式字符串转换,
/// </summary>
/// <param name="publicKey">pem公钥base64字符串</param>
/// <returns></returns>
public static string RSAPublicKey(string publicKey)
{
RsaKeyParameters publicKeyParam = (RsaKeyParameters)PublicKeyFactory.CreateKey(Convert.FromBase64String(publicKey));
string XML = string.Format("<RSAKeyValue><Modulus>{0}</Modulus><Exponent>{1}</Exponent></RSAKeyValue>",
Convert.ToBase64String(publicKeyParam.Modulus.ToByteArrayUnsigned()),
Convert.ToBase64String(publicKeyParam.Exponent.ToByteArrayUnsigned()));
return XML;
}
另外如果在之后加密时报长度超长之类的错误,说明需要分段加密,因为RSA的加密机制要求:待加密的字节数不能超过密钥的长度值除以 8 再减去 11。
可以用如下方法进行分段加密:
/// <summary>
/// RSA加密并且返回加密后内容的base64字符串
/// </summary>
/// <param name="publickey">公钥xml格式字符串</param>
/// <param name="content">加密内容</param>
/// <returns></returns>
public static string RSAEncrypt(string publickey, string content)
{
RSACryptoServiceProvider _rsa = new RSACryptoServiceProvider();
_rsa.FromXmlString(publickey);
var _b = Encoding.Default.GetBytes(content);
//将字符编码转为utf8
_b = Encoding.Convert(Encoding.Default, new UTF8Encoding(), _b);
int _maxSize = _rsa.KeySize/8-11;
if (_b.Length <= _maxSize)
{
byte[] cipherbytes = _rsa.Encrypt(_b, false);
return Convert.ToBase64String(cipherbytes);
}
else//分块加密
{
using (MemoryStream PlaiStream = new MemoryStream(_b))
using (MemoryStream CrypStream = new MemoryStream())
{
Byte[] Buffer = new Byte[_maxSize];
int BlockSize = PlaiStream.Read(Buffer, 0, _maxSize);
while (BlockSize > 0)
{
Byte[] ToEncrypt = new Byte[BlockSize];
Array.Copy(Buffer, 0, ToEncrypt, 0, BlockSize);
Byte[] Cryptograph = _rsa.Encrypt(ToEncrypt, false);
CrypStream.Write(Cryptograph, 0, Cryptograph.Length);
BlockSize = PlaiStream.Read(Buffer, 0, _maxSize);
}
return Convert.ToBase64String(CrypStream.ToArray(), Base64FormattingOptions.None);
}
}
}
但是上面的加密方式有一个问题,就是同样的待加密内容和公钥,每次加密之后的结果都不相同,虽然都能用私钥进行解密。如果是那种涉及到MD5验证之类的摘要算法进行验证,那么这种“加密结果不固定”的加密方式就不可取了。
之所以出现这种问题是与RSA加密算法的“填充(Padding)”有关,这里的东西我也不懂,所以略过,有兴趣的同学可以深入研究一下。
所以基于这种情况,下面的方法就是一种无填充的公钥加密方式,可以让每一次的加密结果都一致:
/// <summary>
/// RSA公钥加密(无填充,结果不变)
/// </summary>
/// <param name="clearText">待加密内容的字节数组</param>
/// <param name="publicKey">公钥(无pem格式头尾,仅base64部分)</param>
/// <returns>加密结果的字节数组</returns>
public byte[] RsaEncryptWithPublic(byte[] srcData, string publicKey)
{
var encryptEngine = new RsaEngine(); // new Pkcs1Encoding (new RsaEngine());
using (var txtreader = new StringReader("-----BEGIN PUBLIC KEY-----\n" + publicKey + "\n-----END PUBLIC KEY-----"))
{
var keyParameter = (AsymmetricKeyParameter)new Org.BouncyCastle.OpenSsl.PemReader(txtreader).ReadObject();
encryptEngine.Init(true, keyParameter);
}
byte[] _resultBytes;
var _maxSize = encryptEngine.GetInputBlockSize();
if (srcData.Length <= _maxSize)
{
_resultBytes = encryptEngine.ProcessBlock(srcData, 0, srcData.Length);
}
else//分块加密
{
using (MemoryStream PlaiStream = new MemoryStream(srcData))
using (MemoryStream CrypStream = new MemoryStream())
{
Byte[] Buffer = new Byte[_maxSize];
int BlockSize = PlaiStream.Read(Buffer, 0, _maxSize);
while (BlockSize > 0)
{
Byte[] ToEncrypt = new Byte[BlockSize];
Array.Copy(Buffer, 0, ToEncrypt, 0, BlockSize);
Byte[] Cryptograph = encryptEngine.ProcessBlock(ToEncrypt, 0, ToEncrypt.Length);
CrypStream.Write(Cryptograph, 0, Cryptograph.Length);
BlockSize = PlaiStream.Read(Buffer, 0, _maxSize);
}
_resultBytes = CrypStream.ToArray();
}
}
return _resultBytes;
}
如何在ruby中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL
我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha
C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.
我有一个.pfx格式的证书,我需要使用ruby提取公共(public)、私有(private)和CA证书。使用shell我可以这样做:#ExtractPublicKey(askforpassword)opensslpkcs12-infile.pfx-outfile_public.pem-clcerts-nokeys#ExtractCertificateAuthorityKey(askforpassword)opensslpkcs12-infile.pfx-outfile_ca.pem-cacerts-nokeys#ExtractPrivateKey(askforpassword)o
我在加密来self正在使用的第三方供应商的值时遇到问题。他们的指令如下:1)Converttheencryptionpasswordtoabytearray.2)Convertthevaluetobeencryptedtoabytearray.3)Theentirelengthofthearrayisinsertedasthefirstfourbytesontothefrontofthefirstblockoftheresultantbytearraybeforeencryption.4)EncryptthevalueusingAESwith:1.256-bitkeysize,2.25
我在我的rails应用程序中安装了来自github.com的acts_as_versioned插件,但有一段代码我不完全理解,我希望有人能帮我解决这个问题class_eval我知道block内的方法(或任何它是什么)被定义为类内的实例方法,但我在插件的任何地方都找不到定义为常量的CLASS_METHODS,而且我也不确定是什么here,并且有问题的代码从lib/acts_as_versioned.rb的第199行开始。如果有人愿意告诉我这里的内幕,我将不胜感激。谢谢-C 最佳答案 这是一个异端。http://en.wikipedia
首先,关于我们系统的一些信息,它基本上是建筑行业的电子招标解决方案。所以:列表项我们的系统有多家公司每个公司都有多个用户每家公司可以创建多个拍卖然后其他公司可以为可用的拍卖提交他们的出价。一个出价包含数百或数千个单独的项目,我们只需要加密这些记录的“价格”部分。我们面临的问题是,我们的大客户不希望我们知道投标价格,至少在投标过程中是这样,这是完全可以理解的。现在,我们只是通过对称加密对价格进行加密,因此即使价格在数据库中有效加密,他们担心的是我们拥有解密价格的key。因此,我们正在研究某种形式的公钥加密系统。以下是我们对解决方案的初步想法:当一家公司注册时,我们会使用OpenSSL为其
我正在尝试对某些帖子的评论使用简单的身份验证。用户使用即时ID和密码输入评论我使用“bcrypt”gem将密码存储在数据库中。在comments_controller.rb中像这样@comment=Comment.new(comment_params)bcrypted_pwd=BCrypt::Password.create(@comment.user_pwd)@comment.user_pwd=bcrypted_pwd当用户想要删除他们的评论时,我使用data-confirm-modalgem来确认数据在这部分,我必须解密用户输入的密码以与数据库中的加密密码进行比较我怎样才能解密密码,
按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visitthehelpcenter指导。关闭9年前。我最近开始学习Ruby,这是我的第一门编程语言。我对语法感到满意,并且我已经完成了许多只教授相同基础知识的教程。我已经写了一些小程序(包括我自己的数组排序方法,在有人告诉我谷歌“冒泡排序”之前我认为它非常聪明),但我觉得我需要尝试更大更难的东西来理解更多关于Ruby.关于如何执行此操作的任何想法?
我在Ruby中遇到了一个关于Dir[]和File.join()的简单程序,blobs_dir='/path/to/dir'Dir[File.join(blobs_dir,"**","*")].eachdo|file|FileUtils.rm_rf(file)ifFile.symlink?(file)我有两个困惑:首先,File.join(@blobs_dir,"**","*")中的第二个和第三个参数是什么意思?其次,Dir[]在Ruby中有什么用?我只知道它等价于Dir.glob(),但是,我对Dir.glob()确实不是很清楚。 最佳答案