gpt4 book ai didi

cryptography - 容器未返回 RSA 加密公钥?

转载 作者:行者123 更新时间:2023-12-02 00:45:27 24 4
gpt4 key购买 nike

我觉得我想做的事情很简单。但出于某种原因,它不想工作:

这是一个完整的代码片段,用于测试我正在尝试做的事情:

using 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";
//create the two providers
RSACryptoServiceProvider serverRSA = GetKeyFromContainer(fullKeyContainer);

//save public and full key pairs
SaveKeyToContainer(fullKeyContainer, serverRSA.ExportParameters(true));
SaveKeyToContainer(publicKeyContainer, serverRSA.ExportParameters(false));

//get rid of them from memory
serverRSA.Clear();
serverRSA = null;
GC.Collect();

//retrieve a full server set and a private client set
serverRSA = GetKeyFromContainer(fullKeyContainer);
RSACryptoServiceProvider clientRSA = GetKeyFromContainer(publicKeyContainer);

//at this point the public key should be the same for both RSA providers
string clientPublicKey = clientRSA.ToXmlString(false);
string serverPublicKey = serverRSA.ToXmlString(false);

if (clientPublicKey.Equals(serverPublicKey))
{//they have the same public key.

// Create an XmlDocument object.
XmlDocument xmlDoc = new XmlDocument();

// Load an XML file into the XmlDocument object.
try
{
xmlDoc.PreserveWhitespace = true;
xmlDoc.Load("test.xml");
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}

//we can encypt with the clientRSA using the public key
Encrypt(xmlDoc, "Fields", "DataFields", clientRSA, "test");

Console.WriteLine("Encrypted: \r\n" + xmlDoc.OuterXml);

//and should be able to decrypt with the serverRSA using the private key
Decrypt(xmlDoc, serverRSA, "test");

Console.WriteLine("Decrypted : \r\n" + xmlDoc.OuterXml);
}
else
{
Console.WriteLine("The two RSA have different public keys...");
}

Console.ReadLine();
}



private static CspParameters GetCspParameters(string containerName)
{
// Create the CspParameters object and set the key container
// name used to store the RSA key pair.
CspParameters tmpParameters = new CspParameters();
tmpParameters.Flags = CspProviderFlags.UseMachineKeyStore; //use the machine key store--this allows us to use the machine level container when applications run without a logged-in user
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);

// Create a new instance of RSACryptoServiceProvider that accesses
// the key container
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(tmpParameters);

//set the key information from the text
rsa.ImportParameters(rsaParameters);
}

public static RSACryptoServiceProvider GetKeyFromContainer(string containerName)
{
// Create the CspParameters object and set the key container
// name used to store the RSA key pair.
CspParameters tmpParameters = GetCspParameters(containerName);

// Create a new instance of RSACryptoServiceProvider that accesses
// the key container.
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(tmpParameters);

return rsa;
}

public static void DeleteKeyFromContainer(string containerName)
{
// Create the CspParameters object and set the key container
// name used to store the RSA key pair.
CspParameters tmpParameters = GetCspParameters(containerName);

// Create a new instance of RSACryptoServiceProvider that accesses
// the key container.
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(tmpParameters);

// Delete the key entry in the container.
rsa.PersistKeyInCsp = false;

// Call Clear to release resources and delete the key from the container.
rsa.Clear();
}



public static void Encrypt(XmlDocument Doc, string ElementToEncrypt, string EncryptionElementID, RSA Alg, string KeyName)
{
// Check the arguments.
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");

////////////////////////////////////////////////
// Find the specified element in the XmlDocument
// object and create a new XmlElemnt object.
////////////////////////////////////////////////
XmlElement elementToEncrypt = Doc.GetElementsByTagName(ElementToEncrypt)[0] as XmlElement;

// Throw an XmlException if the element was not found.
if (elementToEncrypt == null)
{
throw new XmlException("The specified element was not found");

}
RijndaelManaged sessionKey = null;

try
{
//////////////////////////////////////////////////
// Create a new instance of the EncryptedXml class
// and use it to encrypt the XmlElement with the
// a new random symmetric key.
//////////////////////////////////////////////////

// Create a 256 bit Rijndael key.
sessionKey = new RijndaelManaged();
sessionKey.KeySize = 256;

EncryptedXml eXml = new EncryptedXml();

byte[] encryptedElement = eXml.EncryptData(elementToEncrypt, sessionKey, false);
////////////////////////////////////////////////
// Construct an EncryptedData object and populate
// it with the desired encryption information.
////////////////////////////////////////////////

EncryptedData edElement = new EncryptedData();
edElement.Type = EncryptedXml.XmlEncElementUrl;
edElement.Id = EncryptionElementID;
// Create an EncryptionMethod element so that the
// receiver knows which algorithm to use for decryption.

edElement.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncAES256Url);
// Encrypt the session key and add it to an EncryptedKey element.
EncryptedKey ek = new EncryptedKey();

byte[] encryptedKey = EncryptedXml.EncryptKey(sessionKey.Key, Alg, false);

ek.CipherData = new CipherData(encryptedKey);

ek.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncRSA15Url);

// Create a new DataReference element
// for the KeyInfo element. This optional
// element specifies which EncryptedData
// uses this key. An XML document can have
// multiple EncryptedData elements that use
// different keys.
DataReference dRef = new DataReference();

// Specify the EncryptedData URI.
dRef.Uri = "#" + EncryptionElementID;

// Add the DataReference to the EncryptedKey.
ek.AddReference(dRef);
// Add the encrypted key to the
// EncryptedData object.

edElement.KeyInfo.AddClause(new KeyInfoEncryptedKey(ek));
// Set the KeyInfo element to specify the
// name of the RSA key.


// Create a new KeyInfoName element.
KeyInfoName kin = new KeyInfoName();

// Specify a name for the key.
kin.Value = KeyName;

// Add the KeyInfoName element to the
// EncryptedKey object.
ek.KeyInfo.AddClause(kin);
// Add the encrypted element data to the
// EncryptedData object.
edElement.CipherData.CipherValue = encryptedElement;
////////////////////////////////////////////////////
// Replace the element from the original XmlDocument
// object with the EncryptedData element.
////////////////////////////////////////////////////
EncryptedXml.ReplaceElement(elementToEncrypt, edElement, false);
}
catch (Exception e)
{
// re-throw the exception.
throw e;
}
finally
{
if (sessionKey != null)
{
sessionKey.Clear();
}

}

}

public static void Decrypt(XmlDocument Doc, RSA Alg, string KeyName)
{
// Check the arguments.
if (Doc == null)
throw new ArgumentNullException("Doc");
if (Alg == null)
throw new ArgumentNullException("Alg");
if (KeyName == null)
throw new ArgumentNullException("KeyName");

// Create a new EncryptedXml object.
EncryptedXml exml = new EncryptedXml(Doc);

// Add a key-name mapping.
// This method can only decrypt documents
// that present the specified key name.
exml.AddKeyNameMapping(KeyName, Alg);

// Decrypt the element.
exml.DecryptDocument();

}

}
}

只要我使用私钥和公钥保存/获取 RSACryptoServiceProvider,这似乎就可以正常工作。一旦我用一个公钥保存了一个 RSACryptoServiceProvider,下次我尝试检索它时,我得到的只是一个新的和不同的 RSACryptoServiceProvider!

正如您所想象的,您无法使用一组 key 加密某些内容,然后尝试使用一组全新的 key 进行解密!

关于为什么会发生这种情况的任何想法?或者存储只公开 key 的正确方法是什么?

最佳答案

我有 a very similar question .

我现在几乎可以肯定 key 容器不能用于存储公钥。它们的主要目的似乎是存储 key 对。 key 容器仅存储最初生成的 key ,导入 PublicOnly key 仅影响实例而不影响存储。

.NET 开发人员指南的“How to: Store Asymmetric Keys in a Key Container”页面指出

If you need to store a private key, you should use a key container

...这与我通过 MSDN 能够找到的声明一样清晰。

我使用的替代机制是将 key 存储在一个 XML 文件中(因为它是一个公钥,所以如果它很容易看到就没有关系),并使用文件系统访问规则设置权限以防止不必要的修改。

关于cryptography - 容器未返回 RSA 加密公钥?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/827518/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com