将 RSA 密钥容器从服务器 A 移动到服务器 B
Move RSA Key Container from Server A to Server B
我的项目需要密钥恢复功能,系统管理员可以在其中上传 RSA 密钥容器
在灾难恢复的情况下恢复它
当前的实现是当管理员上传备份 RSA 密钥容器文件时,应用程序会将其移动到位于 C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys[=12 的 RSA 密钥容器文件夹中=]
我试图将密钥容器从服务器恢复到我的本地机器
来自服务器的密钥容器 :
a953858192ce652ca077837fd55e8ea2_06454689-ae14-440b-aa53-c2eaac321be6
粗体部分是Server Machine ID
当 RSACryptoServiceProvider 尝试访问容器时,它会创建一个新容器,因为密钥名称不包含我的本地机器 ID,导致无法从服务器解密加密数据。
我尝试将机器 ID 重命名为我的本地机器 ID
a953858192ce652ca077837fd55e8ea2_fbf0b515-e8c9-450d-bc0c-4bcb55cbd342
RSACryptoService 抛出错误:
"Key not valid for use in specified state."
C#中的代码实现:
try{
// Create the CspParameters object and set the key container name used to store the RSA key pair.
var parameters = new CspParameters {KeyContainerName = containerName, Flags = UseMachineKeyStore};
// Create a new instance of RSACryptoServiceProvider that accesses
// the key container Key Container Name.
using var rsaCryptoServiceProvider = new RSACryptoServiceProvider(parameters); // error thrown "Key not valid for use in specified state."
try
{
var keyContainerBlob = rsaCryptoServiceProvider.ExportCspBlob(true);
using (var rsa = System.Security.Cryptography.RSA.Create())
{
rsa.KeySize = CryptoCommonHeap.RSAEncryptionKeySize;
rsaCryptoServiceProvider.ImportCspBlob(keyContainerBlob);
var privateKeyParameters = rsaCryptoServiceProvider.ExportParameters(true).ToPrivateKeyParameters();
var privateKeyParametersJson = JsonConvert.SerializeObject(privateKeyParameters);
PrivateKeyParametersJson = privateKeyParametersJson;
}
}
finally
{
// Setting This If Do Not Want To Store The File Persistently
//rsaCryptoServiceProvider.PersistKeyInCsp = false;
}
}
catch (Exception exception)
{
LogErrorToDatabase(ModuleName, "GenerateKeyAndSaveInKeyStore", exception);
}
我希望有人能告诉我从另一台机器恢复 RSA 密钥容器的正确方法..
我自己弄清楚了如何正确恢复密钥容器。我没有将密钥容器直接从服务器 A 复制到服务器 B,而是以 PEM 格式将私钥从服务器 A 导出到服务器 B,然后以编程方式进行恢复。
依赖关系:Org.Bouncycastle
首先您需要导出密钥容器中现有密钥的私钥,您必须确保 RSACryptoServiceProvider 加载了您想要的密钥容器信息
//Create the CspParameters object and set the key container name used to store the RSA key pair.
var parameters = new CspParameters {KeyContainerName = containerName, Flags = UseMachineKeyStore};
// Create a new instance of RSACryptoServiceProvider that accesses
// the key container Key Container Name.
using var rsaCryptoServiceProvider = new RSACryptoServiceProvider(parameters);
然后使用这个导出密钥:
private string ExportKey(RSACryptoServiceProvider rsa) {
var writer = new StringWriter();
var pemWriter = new PemWriter(writer);
var rsaKeyPair = DotNetUtilities.GetRsaKeyPair(rsa);
pemWriter.WriteObject(rsaKeyPair.Private);
return writer.ToString();
}
现在您将拥有 PEM 内容并将其保存到适当的位置:
-----BEGIN RSA PRIVATE KEY-----
MIICXwIBAAKBgQDCmI8XFUlZUwoGXl42GNzY2o6exeA51/7U0UF4u5+AAbS+h3xD
Pk1BQ5rlzwOu+a2SrbNnGlH5j/6n+kQqLcBdwVdHAF6CFaPmKf7xUEqKwo2RCoG9
zNYB5gc4youdppr4K7uLDQoVvM9xUVi09n2zg3KSigLpX3WM5k4lJWOiOQIDAQAB
AoGBAL6X58ZHDhFT+MSmFwZLMbufzQKLcoOVH73XupWCxsT8ZsgaMUY3NjmO+p7N
NKFjYHMCeG2qZNHXDCgAQlVBfF9fvA3SulymyYoHEAGY1ghAnky7PjuESYmCFDes
6BlyMBfjNtAPkvSA/VZi00VOuCl7Vg4FJLOesmZzHdoaflIlAkEA+W5NU3l+z5+d
rZkw86v+ZvmuDNv77Bh5DZJ1SjQ6uiWCV7LmMOc6eOETmV0d25UkBdAU4KpfRFXg
zcEh548t9wJBAMe4jVQFMjv2L35Kr0jsSEi+O3OPNn7UTNYWlCwv0FnzB3YBMFvA
ULDYmtduaBqchzqqleWrOGK8dOeiUyj+ZU8CQQCsMlX31tyRAaSdgDCnSIntFVnv
Tr9wksSfdgi7Haudbt+5I6x+/mMDqH8bVYmTWjbwPGLtZzE1wAPeiAKcFeCpAkEA
hW+OLRaTq3Ad5xjq56PF36QJgHmshSw+ccMAGE2RvKcc0wCUWJiy0JTHTyvarfzq
dI3IPHwa3gzfZmsTeI4PDQJBAI+LvqZzxzwf01DWgDqiJzKwt+bejtdfnPqQhjRD
rcZcM550Iwy0PCdrRTswDbloNhCfcyi1HXIvZTydMXzOueU=
-----END RSA PRIVATE KEY-----
然后根据PEM文件中的密钥信息在Server B重新生成密钥容器
public bool PrivateKeyRecovery(string pem)
{
try
{
//read key info
PemReader pr = new PemReader(new StringReader(pem));
var paramObject = pr.ReadObject();
AsymmetricCipherKeyPair KeyPair = (AsymmetricCipherKeyPair)paramObject;
RSAParameters rsaParams = DotNetUtilities.ToRSAParameters((RsaPrivateCrtKeyParameters)KeyPair.Private);
//prepare key name and csp parameters
var keyContainerName = "RestoredContainer" + DateTime.Now.ToString("yyyyMddhmm");
var parameters = new CspParameters { KeyContainerName = keyContainerName, Flags = UseMachineKeyStore };
//import csp parameters into new instance of RSACryptoServiceProvider
RSACryptoServiceProvider csp = new RSACryptoServiceProvider(parameters);
csp.ImportParameters(rsaParams);
//exporting new key container
var keyContainerBlob = csp.ExportCspBlob(true);
csp.ImportCspBlob(keyContainerBlob);
}
catch (Exception exception)
{
//your error handling
}
return false;
}
现在您可以通过将新生成的密钥容器加载到 RSACryptoServiceProvider 来在服务器 B 中解密来自服务器 A 的数据。
我的项目需要密钥恢复功能,系统管理员可以在其中上传 RSA 密钥容器 在灾难恢复的情况下恢复它
当前的实现是当管理员上传备份 RSA 密钥容器文件时,应用程序会将其移动到位于 C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys[=12 的 RSA 密钥容器文件夹中=]
我试图将密钥容器从服务器恢复到我的本地机器
来自服务器的密钥容器 :
a953858192ce652ca077837fd55e8ea2_06454689-ae14-440b-aa53-c2eaac321be6
粗体部分是Server Machine ID
当 RSACryptoServiceProvider 尝试访问容器时,它会创建一个新容器,因为密钥名称不包含我的本地机器 ID,导致无法从服务器解密加密数据。
我尝试将机器 ID 重命名为我的本地机器 ID
a953858192ce652ca077837fd55e8ea2_fbf0b515-e8c9-450d-bc0c-4bcb55cbd342
RSACryptoService 抛出错误:
"Key not valid for use in specified state."
C#中的代码实现:
try{
// Create the CspParameters object and set the key container name used to store the RSA key pair.
var parameters = new CspParameters {KeyContainerName = containerName, Flags = UseMachineKeyStore};
// Create a new instance of RSACryptoServiceProvider that accesses
// the key container Key Container Name.
using var rsaCryptoServiceProvider = new RSACryptoServiceProvider(parameters); // error thrown "Key not valid for use in specified state."
try
{
var keyContainerBlob = rsaCryptoServiceProvider.ExportCspBlob(true);
using (var rsa = System.Security.Cryptography.RSA.Create())
{
rsa.KeySize = CryptoCommonHeap.RSAEncryptionKeySize;
rsaCryptoServiceProvider.ImportCspBlob(keyContainerBlob);
var privateKeyParameters = rsaCryptoServiceProvider.ExportParameters(true).ToPrivateKeyParameters();
var privateKeyParametersJson = JsonConvert.SerializeObject(privateKeyParameters);
PrivateKeyParametersJson = privateKeyParametersJson;
}
}
finally
{
// Setting This If Do Not Want To Store The File Persistently
//rsaCryptoServiceProvider.PersistKeyInCsp = false;
}
}
catch (Exception exception)
{
LogErrorToDatabase(ModuleName, "GenerateKeyAndSaveInKeyStore", exception);
}
我希望有人能告诉我从另一台机器恢复 RSA 密钥容器的正确方法..
我自己弄清楚了如何正确恢复密钥容器。我没有将密钥容器直接从服务器 A 复制到服务器 B,而是以 PEM 格式将私钥从服务器 A 导出到服务器 B,然后以编程方式进行恢复。
依赖关系:Org.Bouncycastle
首先您需要导出密钥容器中现有密钥的私钥,您必须确保 RSACryptoServiceProvider 加载了您想要的密钥容器信息
//Create the CspParameters object and set the key container name used to store the RSA key pair.
var parameters = new CspParameters {KeyContainerName = containerName, Flags = UseMachineKeyStore};
// Create a new instance of RSACryptoServiceProvider that accesses
// the key container Key Container Name.
using var rsaCryptoServiceProvider = new RSACryptoServiceProvider(parameters);
然后使用这个导出密钥:
private string ExportKey(RSACryptoServiceProvider rsa) {
var writer = new StringWriter();
var pemWriter = new PemWriter(writer);
var rsaKeyPair = DotNetUtilities.GetRsaKeyPair(rsa);
pemWriter.WriteObject(rsaKeyPair.Private);
return writer.ToString();
}
现在您将拥有 PEM 内容并将其保存到适当的位置:
-----BEGIN RSA PRIVATE KEY-----
MIICXwIBAAKBgQDCmI8XFUlZUwoGXl42GNzY2o6exeA51/7U0UF4u5+AAbS+h3xD
Pk1BQ5rlzwOu+a2SrbNnGlH5j/6n+kQqLcBdwVdHAF6CFaPmKf7xUEqKwo2RCoG9
zNYB5gc4youdppr4K7uLDQoVvM9xUVi09n2zg3KSigLpX3WM5k4lJWOiOQIDAQAB
AoGBAL6X58ZHDhFT+MSmFwZLMbufzQKLcoOVH73XupWCxsT8ZsgaMUY3NjmO+p7N
NKFjYHMCeG2qZNHXDCgAQlVBfF9fvA3SulymyYoHEAGY1ghAnky7PjuESYmCFDes
6BlyMBfjNtAPkvSA/VZi00VOuCl7Vg4FJLOesmZzHdoaflIlAkEA+W5NU3l+z5+d
rZkw86v+ZvmuDNv77Bh5DZJ1SjQ6uiWCV7LmMOc6eOETmV0d25UkBdAU4KpfRFXg
zcEh548t9wJBAMe4jVQFMjv2L35Kr0jsSEi+O3OPNn7UTNYWlCwv0FnzB3YBMFvA
ULDYmtduaBqchzqqleWrOGK8dOeiUyj+ZU8CQQCsMlX31tyRAaSdgDCnSIntFVnv
Tr9wksSfdgi7Haudbt+5I6x+/mMDqH8bVYmTWjbwPGLtZzE1wAPeiAKcFeCpAkEA
hW+OLRaTq3Ad5xjq56PF36QJgHmshSw+ccMAGE2RvKcc0wCUWJiy0JTHTyvarfzq
dI3IPHwa3gzfZmsTeI4PDQJBAI+LvqZzxzwf01DWgDqiJzKwt+bejtdfnPqQhjRD
rcZcM550Iwy0PCdrRTswDbloNhCfcyi1HXIvZTydMXzOueU=
-----END RSA PRIVATE KEY-----
然后根据PEM文件中的密钥信息在Server B重新生成密钥容器
public bool PrivateKeyRecovery(string pem)
{
try
{
//read key info
PemReader pr = new PemReader(new StringReader(pem));
var paramObject = pr.ReadObject();
AsymmetricCipherKeyPair KeyPair = (AsymmetricCipherKeyPair)paramObject;
RSAParameters rsaParams = DotNetUtilities.ToRSAParameters((RsaPrivateCrtKeyParameters)KeyPair.Private);
//prepare key name and csp parameters
var keyContainerName = "RestoredContainer" + DateTime.Now.ToString("yyyyMddhmm");
var parameters = new CspParameters { KeyContainerName = keyContainerName, Flags = UseMachineKeyStore };
//import csp parameters into new instance of RSACryptoServiceProvider
RSACryptoServiceProvider csp = new RSACryptoServiceProvider(parameters);
csp.ImportParameters(rsaParams);
//exporting new key container
var keyContainerBlob = csp.ExportCspBlob(true);
csp.ImportCspBlob(keyContainerBlob);
}
catch (Exception exception)
{
//your error handling
}
return false;
}
现在您可以通过将新生成的密钥容器加载到 RSACryptoServiceProvider 来在服务器 B 中解密来自服务器 A 的数据。