我有一个导出的rsaparameters私钥,我想将其导入另一台计算机。我可以将 new 键保存到本地计算机或用户容器中,但是我坚持尝试导入现有键。
下面的代码将生成一个新的密钥对,我知道我可以直接在容器中生成一个新键 - 但是我希望能够生成一个键并将同一键导入到少数不同的计算机中。
如何使用rsaparameters或XML(一个(字符串并将其导入本地用户(或计算机(容器?
public async Task<KeyGenerationResult> GenerateNewKeyAsync(int keySize)
{
var csp = new RSACng(keySize);
var privKey = await Task.Run(() => csp.ExportParameters(includePrivateParameters: true));
var pubKey = csp.ExportParameters(includePrivateParameters: false);
var pubKeyString = exportKeyToString(pubKey);
var privKeyString = exportKeyToString(privKey);
return new KeyGenerationResult
{
PrivateKey = privKey,
PublicKey = pubKey,
PrivateKeyCleartext = privKeyString,
PublicKeyCleartext = pubKeyString
};
}
private static string exportKeyToString(RSAParameters key)
{
string keyString;
var sw = new StringWriter();
var xs = new XmlSerializer(typeof(RSAParameters));
xs.Serialize(sw, key);
keyString = sw.ToString();
return keyString;
}
public void SavePrivateKeyToLocalMachine(RSAParameters privateKey, string keyName)
{
//Stuck here. :(
}
cngkey.import((采用一个字节[],这看起来很有希望,但是我还没有找到任何方法 create cngkey.import((需要的字节[]。
var d = new RSACryptoServiceProvider();
d.ImportParameters(privateKey);
var keyBlob = d.ExportCspBlob(true);
var key = CngKey.Import(keyBlob, CngKeyBlobFormat.Pkcs8PrivateBlob);
这给我带来了一个字节[],但是无论我使用哪种cngkeyblobformat,我都会得到例外。我被困住了。
update
我找到了一种使用
获得字节[]的方法 var cp = new CngKeyCreationParameters();
cp.KeyUsage = CngKeyUsages.AllUsages;
cp.ExportPolicy = CngExportPolicies.AllowPlaintextExport | CngExportPolicies.AllowExport | CngExportPolicies.AllowArchiving | CngExportPolicies.AllowPlaintextArchiving;
cp.Parameters.Add(new CngProperty("Length", BitConverter.GetBytes(keySize), CngPropertyOptions.None));
var key = CngKey.Create(CngAlgorithm.Rsa, null, cp);
var bytes = key.Export(CngKeyBlobFormat.{I have tried them all});
此代码看起来像应该让我导入字节[]
/* try to save this key to the local user container */
var keyParameters = new CngKeyCreationParameters()
{
KeyCreationOptions = CngKeyCreationOptions.OverwriteExistingKey,
Provider = CngProvider.MicrosoftSoftwareKeyStorageProvider,
KeyUsage = CngKeyUsages.AllUsages,
ExportPolicy = CngExportPolicies.AllowPlaintextExport
};
keyParameters.KeyCreationOptions = CngKeyCreationOptions.None;
keyParameters.Parameters.Add(new CngProperty("Length", BitConverter.GetBytes(keySize), CngPropertyOptions.None));
keyParameters.Parameters.Add(new CngProperty(blobType.Format, bytes, CngPropertyOptions.None));
var newKey = CngKey.Create(CngAlgorithm.Rsa, "MyTestName", keyParameters);
...但是再一次,没有骰子。我尝试了什么cngkeyblobformat都没关系,他们都给我异常,我无法将密钥导入本地密钥存储提供商。
我需要哪些魔术和参数进行此工作?
好吧,我终于使它起作用了。这是代码最终安顿下来的代码。
public class KeyGenerationResult
{
public RSAParameters PublicKey { get; set; }
public string PublicKeyCleartext { get; set; }
public string PrivateKeyCleartext { get; set; }
public byte[] PrivateBytes { get; set; }
public int KeySize { get; set; }
public CngKeyBlobFormat BlobFormat { get; set; }
}
public async Task<KeyGenerationResult> GenerateNewKeyAsync(int keySize)
{
var cp = new CngKeyCreationParameters();
cp.KeyUsage = CngKeyUsages.AllUsages;
cp.ExportPolicy = CngExportPolicies.AllowPlaintextExport | CngExportPolicies.AllowExport | CngExportPolicies.AllowArchiving | CngExportPolicies.AllowPlaintextArchiving;
cp.Parameters.Add(new CngProperty("Length", BitConverter.GetBytes(keySize), CngPropertyOptions.None));
var key = await Task.Run(() => CngKey.Create(CngAlgorithm.Rsa, null, cp)).ConfigureAwait(false);
var blobType = CngKeyBlobFormat.GenericPrivateBlob;
var bytes = await Task.Run(() => key.Export(blobType)).ConfigureAwait(false);
var rsa = new RSACng(key);
var pubKey = rsa.ExportParameters(includePrivateParameters: false);
var pubKeyString = exportKeyToString(pubKey);
return new KeyGenerationResult
{
PublicKey = pubKey,
PrivateKeyCleartext = Convert.ToBase64String(bytes),
PublicKeyCleartext = pubKeyString,
PrivateBytes = bytes,
BlobFormat = blobType,
KeySize = keySize
};
}
private static string exportKeyToString(RSAParameters key)
{
string keyString;
var sw = new StringWriter();
var xs = new XmlSerializer(typeof(RSAParameters));
xs.Serialize(sw, key);
keyString = sw.ToString();
return keyString;
}
public void SavePrivateKeyToLocalMachine(KeyGenerationResult keyData, string keyName)
{
var myKSP = CngProvider.MicrosoftSoftwareKeyStorageProvider;
const bool MachineKey = false;
if (!CngKey.Exists(keyName, myKSP))
{
var keyParams = new CngKeyCreationParameters
{
ExportPolicy = CngExportPolicies.AllowPlaintextExport,
KeyCreationOptions = (MachineKey) ? CngKeyCreationOptions.MachineKey : CngKeyCreationOptions.None,
Provider = myKSP
};
keyParams.Parameters.Add(new CngProperty("Length", BitConverter.GetBytes(keyData.KeySize), CngPropertyOptions.None));
keyParams.Parameters.Add(new CngProperty(keyData.BlobFormat.Format, keyData.PrivateBytes, CngPropertyOptions.None));
CngKey.Create(CngAlgorithm.Rsa, keyName, keyParams);
}
else
{
throw new CryptographicException($"The key with the name '{keyName}' already exists!");
}
}