C#(NET6) - 从PFX创建Keypair(公共证书/私钥)
我想导出PFX(公共 +私有部分)以分开文件( *.cer, *.key)。 PFX可能(或可能不)受密码保护。
我试图实现自己的目标,这在证书(公共)方面很好,但是使用私钥会引起问题。
我的bootastrap类如下:
public class CertBootstrap
{
private readonly FileInfo CertificateFile;
private readonly SecureString CertificatePassword;
public bool HasPasswordBeenSet { get; private set; } = false;
public X509Certificate2 Certificate { get; private set; }
public CertBootstrap(FileInfo certificationFile, string password)
{
if(!certificationFile.Exists)
{
throw new FileNotFoundException(certificationFile.FullName);
}
CertificateFile = certificationFile;
HasPasswordBeenSet = true;
CertificatePassword = ConvertPassword(password);
}
public CertBootstrap(FileInfo certificationFile)
{
if(!certificationFile.Exists)
{
throw new FileNotFoundException(certificationFile.FullName);
}
CertificateFile = certificationFile;
HasPasswordBeenSet = false;
}
public CertBootstrap(string certificationFullFileName, string password)
{
var certificateFile = new FileInfo(certificationFullFileName);
if(certificateFile == null || !certificateFile.Exists)
{
throw new FileNotFoundException(certificationFullFileName);
}
CertificateFile = certificateFile;
HasPasswordBeenSet = true;
CertificatePassword = ConvertPassword(password);
}
public CertBootstrap(string certificationFullFileName)
{
var certificateFile = new FileInfo(certificationFullFileName);
if(certificateFile == null || !certificateFile.Exists)
{
throw new FileNotFoundException(certificationFullFileName);
}
CertificateFile = certificateFile;
HasPasswordBeenSet = false;
}
public bool VerifyPassword(string password)
{
try
{
byte[] fileContent = File.ReadAllBytes(CertificateFile.FullName);
var certificate = new X509Certificate2(fileContent, password);
}
catch(CryptographicException ex)
{
if((ex.HResult & 0xFFFF) == 0x56)
{
return false;
}
;
throw;
}
return true;
}
private static SecureString ConvertPassword(string password)
{
var secure = new SecureString();
foreach(char c in password)
{
secure.AppendChar(c);
}
return secure;
}
public void LoadBootstrap()
{
LoadBootstrap(X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet);
}
public void LoadBootstrap(X509KeyStorageFlags keyStorageFlags)
{
this.Certificate = this.HasPasswordBeenSet ? new X509Certificate2(this.CertificateFile.FullName, this.CertificatePassword, keyStorageFlags) : new X509Certificate2(this.CertificateFile.FullName);
}
private static RSA ExportPrivateKeyCoreNet5Net6(RSA privateKey)
{
var password = Encoding.UTF8.GetBytes(Guid.NewGuid().ToString());
PbeParameters pPar = new PbeParameters(PbeEncryptionAlgorithm.Aes256Cbc, HashAlgorithmName.SHA256, 100_000);
try
{
byte[] tempG = privateKey.ExportEncryptedPkcs8PrivateKey(password, pPar);
using(RSA exportRewriter = RSA.Create())
{
exportRewriter.ExportParameters(true);
exportRewriter.ImportEncryptedPkcs8PrivateKey(password, tempG, out _);
return exportRewriter;
}
}
catch(Exception e)
{
//catch this error
string em = e.Message;
throw;
}
}
private static byte[] ExportPrivateKey(RSA privateKey)
{
try
{
return privateKey.ExportPkcs8PrivateKey();
}
catch(CryptographicException)
{
}
return ExportPrivateKeyCoreNet5Net6(privateKey).ExportRSAPublicKey();
}
public byte[] GeneratePrivateKeyPem()
{
byte[] privateCertKeyBytes = ExportPrivateKey(this.Certificate.GetRSAPrivateKey());
char[] newPemData = PemEncoding.Write("PRIVATE KEY", privateCertKeyBytes);
return newPemData.Select(c => (byte)c).ToArray();
}
public byte[] GenerateCertificatePem()
{
var certData = Certificate.RawData;
var newPemData = PemEncoding.Write("CERTIFICATE", certData);
return newPemData.Select(c => (byte)c).ToArray();
}
public FileInfo SaveCertificate()
{
var newData = GenerateCertificatePem();
var oldFile = Path.GetFileNameWithoutExtension(CertificateFile.FullName);
var newCertPemFile = new FileInfo($@"{CertificateFile.DirectoryName}\{oldFile}.cer");
return SaveNewCertFile(newCertPemFile, newData);
}
public FileInfo SavePrivateKey()
{
var newData = GeneratePrivateKeyPem();
var oldFile = Path.GetFileNameWithoutExtension(CertificateFile.FullName);
var newPrivateKeyPemFile = new FileInfo($@"{CertificateFile.DirectoryName}\{oldFile}.key");
return SaveNewCertFile(newPrivateKeyPemFile, newData);
}
public FileInfo SaveNewCertFile(FileInfo newFile, byte[] data)
{
File.WriteAllBytes(newFile.FullName, data);
return newFile;
}
}
有了它,我试图保存私有部分:
// (...)
CertBootstrap certBootstrap = new CertBootstrap("simple.pfx");
certBootstrap.LoadBootstrap();
// (...)
certBootstrap.SavePrivateKey();
所有这些最终都以:“不支持的请求的操作”。
我发现类似的线程:,试图执行相同的操作(导出 - >用密码导入)。但没有帮助。
你能指出我的propper方向吗?我很可能缺少一些东西,但是现在没有想法。
先感谢您。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论