저는 일부 인증서 서명 도구를 사용하고 있으며 현재 목표는 기존 인증서를 발급자로 사용하여 새 인증서를 생성하는 메서드를 만드는 것입니다. 인증서를 생성하는 방법은 다음과 같습니다.인증서에서 수동 설치 및 코드에서 설치하는 것의 차이점은 무엇입니까?
public X509Certificate2 CreateCertificate(string subjectName, TimeSpan certificateLifespan, X509Certificate2 issuer = null)
{
var nameFormat = "CN={0}";
var subject = string.Format(nameFormat, subjectName);
// create DN for subject and issuer
var dn = new CX500DistinguishedName();
dn.Encode(subject);
var privateKey = new CX509PrivateKey
{
ProviderName = "Microsoft Strong Cryptographic Provider",
Length = 2048,
KeySpec = X509KeySpec.XCN_AT_KEYEXCHANGE,
KeyUsage = X509PrivateKeyUsageFlags.XCN_NCRYPT_ALLOW_DECRYPT_FLAG |
X509PrivateKeyUsageFlags.XCN_NCRYPT_ALLOW_KEY_AGREEMENT_FLAG,
MachineContext = true,
ExportPolicy = X509PrivateKeyExportFlags.XCN_NCRYPT_ALLOW_PLAINTEXT_EXPORT_FLAG
};
privateKey.Create();
var hashobj = new CObjectId();
hashobj.InitializeFromAlgorithmName(ObjectIdGroupId.XCN_CRYPT_HASH_ALG_OID_GROUP_ID,
ObjectIdPublicKeyFlags.XCN_CRYPT_OID_INFO_PUBKEY_ANY,
AlgorithmFlags.AlgorithmFlagsNone, "SHA512");
var cert = new CX509CertificateRequestCertificate();
cert.InitializeFromPrivateKey(X509CertificateEnrollmentContext.ContextMachine, privateKey, "");
cert.Subject = dn;
if (issuer == null)
cert.Issuer = dn;
else
{
var signerCertificate = new CSignerCertificate();
signerCertificate.Initialize(true, X509PrivateKeyVerify.VerifyNone, EncodingType.XCN_CRYPT_STRING_HEXRAW, issuer.GetRawCertDataString());
cert.SignerCertificate = signerCertificate;
}
cert.NotBefore = DateTime.Now.Date;
cert.NotAfter = cert.NotBefore + certificateLifespan;
cert.HashAlgorithm = hashobj;
cert.Encode();
var enroll = new CX509Enrollment();
enroll.InitializeFromRequest(cert);
enroll.CertificateFriendlyName = subjectName;
var csr = enroll.CreateRequest();
enroll.InstallResponse(InstallResponseRestrictionFlags.AllowUntrustedCertificate,
csr, EncodingType.XCN_CRYPT_STRING_BASE64, "");
//InstallResponse automatically installs certificate to My store. We should remove it, and manage it manually.
using(var store = new X509Store(StoreName.My, StoreLocation.LocalMachine))
{
store.Open(OpenFlags.ReadWrite);
var certificate = store.Certificates.OfType<X509Certificate2>().FirstOrDefault(
c => c.Subject.StartsWith(subject, StringComparison.Ordinal));
if (certificate != null)
store.Remove(certificate);
store.Close();
}
//Self-signed certificates are also authomatically installed to Intermediate Authority store
if(issuer == null)
{
using (var store = new X509Store(StoreName.CertificateAuthority, StoreLocation.LocalMachine))
{
store.Open(OpenFlags.ReadWrite);
var certificate = store.Certificates.OfType<X509Certificate2>().FirstOrDefault(
c => c.Subject.StartsWith(subject, StringComparison.Ordinal));
if (certificate != null)
store.Remove(certificate);
store.Close();
}
}
var base64encoded = enroll.CreatePFX("", PFXExportOptions.PFXExportChainWithRoot);
return new X509Certificate2(Convert.FromBase64String(base64encoded), "",
X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet);
}
사실 루트 인증서를 수동으로 설치하거나 인증서 관리자를 사용하는 경우에만 완벽하게 작동합니다. 하지만 코드에서 임베디드 리소스의 인증서를 설치하려고합니다.
private void AddCertificateToStore(X509Certificate2 certificate, StoreName storeName)
{
using (var store = new X509Store(storeName, StoreLocation.LocalMachine))
{
store.Open(OpenFlags.ReadWrite);
store.Add(certificate);
store.Close();
}
}
:
var bytes = new BinaryReader(stream).ReadBytes((int)stream.Length);
var root = new X509Certificate2(bytes, RootCertificatePassword);
그리고 여기에 인증서 설치를위한 나의 방법이다 : 나는 그것을 다음 방법을 초기화 다음
protected Stream ExtractResourceStream(string embeddedResourcePath)
{
var assembly = GetType().Assembly;
var pathConverted = embeddedResourcePath.Replace("\\", ".");
var matchingResources = assembly.GetManifestResourceNames()
.Where(n => n.EndsWith(pathConverted, StringComparison.InvariantCultureIgnoreCase))
.ToArray();
var resource = matchingResources.FirstOrDefault();
if (resource == null)
throw new InvalidOperationException(string.Format("Resource {0} not found.", embeddedResourcePath));
if (matchingResources.Length > 1)
throw new InvalidOperationException(string.Format("Resource {0} found more than once.", embeddedResourcePath));
return assembly.GetManifestResourceStream(resource);
}
: 여기
는 스트림에 포함 된 인증서를 추출하는 나의 방법이다루트 인증서가 올바르게 설치되어있는 것 같습니다. 그러나 "키를 찾을 수 없습니다"라는 예외가 발생합니다. signerCertificate.Initialize
에 전화를 걸면 두 번째 인증서가 생성됩니다.
암호로 보호되는 PFX 루트 인증서를 사용하고 있습니다.
내 질문은 - 수동으로 인증서를 설치하고 스트림에서 코드로 설치하는 것의 차이점은 무엇입니까? 코드에 설치하는 동안 일부 기능이 누락 되었습니까?