RSA加密公钥未从容器返回? [英] RSA Encryption public key not returned from container?
本文介绍了RSA加密公钥未从容器返回?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我觉得我想做的是很简单的。但由于某种原因,它不想工作:
这是一个完整的代码片段来测试我想做什么:
使用System;
using System.Xml;
using System.Security.Cryptography;
using System.Security.Cryptography.Xml;
namespace XmlCryptographySendingTest
{
class Program
{
static void Main(string [] args)
{
string fullKeyContainer =fullKeyContainer;
string publicKeyContainer =publicKeyContainer;
//创建两个提供者
RSACryptoServiceProvider serverRSA = GetKeyFromContainer(fullKeyContainer);
//保存公钥和全密钥对
SaveKeyToContainer(fullKeyContainer,serverRSA.ExportParameters(true));
SaveKeyToContainer(publicKeyContainer,serverRSA.ExportParameters(false));
//从内存中删除它们
serverRSA.Clear();
serverRSA = null;
GC.Collect();
//检索完整的服务器集和私人客户端集
serverRSA = GetKeyFromContainer(fullKeyContainer);
RSACryptoServiceProvider clientRSA = GetKeyFromContainer(publicKeyContainer);
//此时,RSA提供程序的公钥应该是相同的
string clientPublicKey = clientRSA.ToXmlString(false);
string serverPublicKey = serverRSA.ToXmlString(false);
if(clientPublicKey.Equals(serverPublicKey))
{//他们有相同的公钥。
//创建一个XmlDocument对象。
XmlDocument xmlDoc = new XmlDocument();
//将XML文件加载到XmlDocument对象中。
try
{
xmlDoc.PreserveWhitespace = true;
xmlDoc.Load(test.xml);
}
catch(Exception e)
{
Console.WriteLine(e.Message);
}
//我们可以用clientRSA使用公共密钥
encypt加密(xmlDoc,Fields,DataFields,clientRSA,test);
Console.WriteLine(Encrypted:\r\\\
+ xmlDoc.OuterXml);
//应该能够使用私钥解密serverRSA
Decrypt(xmlDoc,serverRSA,test);
Console.WriteLine(Decrypted:\r\\\
+ xmlDoc.OuterXml);
}
else
{
Console.WriteLine(两个RSA有不同的公钥...);
}
Console.ReadLine();
}
私人静态CspParameters GetCspParameters(string containerName)
{
//创建CspParameters对象并设置密钥容器
//用于存储RSA密钥对的名称。
CspParameters tmpParameters = new CspParameters();
tmpParameters.Flags = CspProviderFlags.UseMachineKeyStore; //使用机器密钥存储 - 这允许我们在应用程序没有登录用户的情况下使用机器级容器
tmpParameters.ProviderType = 1;
tmpParameters.KeyNumber =(int)KeyNumber.Exchange;
tmpParameters.KeyContainerName = containerName;
return tmpParameters;
}
public static void SaveKeyToContainer(string containerName,RSAParameters rsaParameters)
{
CspParameters tmpParameters = GetCspParameters(containerName);
//创建一个新的RSACryptoServiceProvider实例,访问
//密钥容器
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(tmpParameters);
//从文本中设置键信息
rsa.ImportParameters(rsaParameters);
}
public static RSACryptoServiceProvider GetKeyFromContainer(string containerName)
{
//创建CspParameters对象并设置密钥容器
//用于存储RSA密钥对。
CspParameters tmpParameters = GetCspParameters(containerName);
//创建一个新的RSACryptoServiceProvider实例,访问
//密钥容器。
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(tmpParameters);
return rsa;
}
public static void DeleteKeyFromContainer(string containerName)
{
//创建CspParameters对象并设置密钥容器
//名称用于存储RSA密钥对。
CspParameters tmpParameters = GetCspParameters(containerName);
//创建一个新的RSACryptoServiceProvider实例,访问
//密钥容器。
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(tmpParameters);
//删除容器中的键条目。
rsa.PersistKeyInCsp = false;
//调用清除以释放资源并从容器中删除密钥。
rsa.Clear();
}
public static void Encrypt(XmlDocument Doc,string ElementToEncrypt,string EncryptionElementID,RSA Alg,string KeyName)
{
//检查参数。
if(Doc == null)
throw new ArgumentNullException(Doc);
if(ElementToEncrypt == null)
throw new ArgumentNullException(ElementToEncrypt);
if(EncryptionElementID == null)
throw new ArgumentNullException(EncryptionElementID);
if(Alg == null)
throw new ArgumentNullException(Alg);
if(KeyName == null)
throw new ArgumentNullException(KeyName);
////////////////////////////////////////// //////
//在XmlDocument
//对象中查找指定的元素并创建一个新的XmlElemnt对象。
//////////////////////////////////////////////// //
XmlElement elementToEncrypt = Doc.GetElementsByTagName(ElementToEncrypt)[0] as XmlElement;
//如果未找到元素,则抛出XmlException。
if(elementToEncrypt == null)
{
throw new XmlException(找不到指定的元素);
}
RijndaelManaged sessionKey = null;
try
{
////////////////////////////////// ////////////////////
//创建一个EncryptedXml类的新实例
//并使用它用$ b $加密XmlElement b //新的随机对称密钥。
//////////////////////////////////////////////// ////
//创建一个256位的Rijndael键。
sessionKey = new RijndaelManaged();
sessionKey.KeySize = 256;
EncryptedXml eXml = new EncryptedXml();
byte [] encryptedElement = eXml.EncryptData(elementToEncrypt,sessionKey,false);
//////////////////////////////////////////////// //
//构造一个EncryptedData对象,并使用所需的加密信息填充
//。
//////////////////////////////////////////////// //
EncryptedData edElement = new EncryptedData();
edElement.Type = EncryptedXml.XmlEncElementUrl;
edElement.Id = EncryptionElementID;
//创建一个EncryptionMethod元素,以便
//接收者知道用于解密的算法。
edElement.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncAES256Url);
//加密会话密钥并将其添加到EncryptedKey元素。
EncryptedKey ek = new EncryptedKey();
byte [] encryptedKey = EncryptedXml.EncryptKey(sessionKey.Key,Alg,false);
ek.CipherData = new CipherData(encryptedKey);
ek.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncRSA15Url);
//为KeyInfo元素创建一个新的DataReference元素
//。这个可选的
//元素指定哪个EncryptedData
//使用这个键。一个XML文档可以有
//多个EncryptedData元素,它们使用
//不同的键。
DataReference dRef = new DataReference();
//指定EncryptedData URI。
dRef.Uri =#+ EncryptionElementID;
//将DataReference添加到EncryptedKey。
ek.AddReference(dRef);
//将加密的密钥添加到
// EncryptedData对象。
edElement.KeyInfo.AddClause(new KeyInfoEncryptedKey(ek));
//设置KeyInfo元素以指定RSA密钥的
//名称。
//创建一个新的KeyInfoName元素。
KeyInfoName kin = new KeyInfoName();
//指定键的名称。
kin.Value = KeyName;
//将KeyInfoName元素添加到
// EncryptedKey对象中。
ek.KeyInfo.AddClause(kin);
//将加密的元素数据添加到
// EncryptedData对象。
edElement.CipherData.CipherValue = encryptedElement;
//////////////////////////////////////////////// //////
//使用EncryptedData元素替换原始XmlDocument
//对象中的元素。
//////////////////////////////////////////////// //////
EncryptedXml.ReplaceElement(elementToEncrypt,edElement,false);
}
catch(Exception e)
{
//重新抛出异常。
throw e;
}
finally
{
if(sessionKey!= null)
{
sessionKey.Clear();
}
}
}
public static void Decrypt(XmlDocument Doc,RSA Alg,string KeyName)
{
//检查参数。
if(Doc == null)
throw new ArgumentNullException(Doc);
if(Alg == null)
throw new ArgumentNullException(Alg);
if(KeyName == null)
throw new ArgumentNullException(KeyName);
//创建一个新的EncryptedXml对象。
EncryptedXml exml = new EncryptedXml(Doc);
//添加键名映射。
//此方法只能解密呈现指定键名称的文档
//。
exml.AddKeyNameMapping(KeyName,Alg);
//解密元素。
exml.DecryptDocument();
}
}
}
这似乎工作正常,只要我保存/获得一个RSACryptoServiceProvider与私钥和公钥。一旦我保存了一个带有JUST公钥的RSACryptoServiceProvider,下次我尝试检索它时,我得到的是一个新的和不同的RSACryptoServiceProvider!
你可以想象,不能用一组密钥加密某个东西,然后尝试用一个全新的集解密!
有什么想法为什么会发生?