I am trying to create certificate request programmatically from existing public key. But I get an "The requested property value is empty. (Exception from HRESULT: 0x80094004)" exception. Here is my code:
private static string CreateCertRequestMessage(string encodedPublicKeyInfo)
{
CObjectId objAlg = new CObjectId();
objAlg.InitializeFromAlgorithmName(
ObjectIdGroupId.XCN_CRYPT_PUBKEY_ALG_OID_GROUP_ID,
ObjectIdPublicKeyFlags.XCN_CRYPT_OID_INFO_PUBKEY_ANY,
AlgorithmFlags.AlgorithmFlagsNone,
"RSA");
CX509PublicKey objPublicKey = new CX509PublicKey();
objPublicKey.Initialize(objAlg, encodedPublicKeyInfo, "", EncodingType.XCN_CRYPT_STRING_HEX);
Console.WriteLine(objPublicKey.Algorithm.FriendlyName);
Console.WriteLine(objPublicKey.Algorithm.Value);
Console.WriteLine(objPublicKey.Length);
Console.WriteLine(objPublicKey.EncodedKey);
var objPkcs10 = new CX509CertificateRequestCertificate();
objPkcs10.InitializeFromPublicKey(
X509CertificateEnrollmentContext.ContextUser,
objPublicKey,
string.Empty);
var objExtensionKeyUsage = new CX509ExtensionKeyUsage();
objExtensionKeyUsage.InitializeEncode(
CERTENROLLLib.X509KeyUsageFlags.XCN_CERT_DIGITAL_SIGNATURE_KEY_USAGE |
CERTENROLLLib.X509KeyUsageFlags.XCN_CERT_NON_REPUDIATION_KEY_USAGE |
CERTENROLLLib.X509KeyUsageFlags.XCN_CERT_KEY_ENCIPHERMENT_KEY_USAGE |
CERTENROLLLib.X509KeyUsageFlags.XCN_CERT_DATA_ENCIPHERMENT_KEY_USAGE);
objPkcs10.X509Extensions.Add((CX509Extension)objExtensionKeyUsage);
var objObjectId = new CObjectId();
var objObjectIds = new CObjectIds();
var objX509ExtensionEnhancedKeyUsage = new CX509ExtensionEnhancedKeyUsage();
objObjectId.InitializeFromValue("1.3.6.1.5.5.7.3.2");
objObjectIds.Add(objObjectId);
objX509ExtensionEnhancedKeyUsage.InitializeEncode(objObjectIds);
objPkcs10.X509Extensions.Add((CX509Extension)objX509ExtensionEnhancedKeyUsage);
string templateName = "MHM Template";
CX509ExtensionTemplateName template = new CX509ExtensionTemplateName();
template.InitializeEncode(templateName);
objPkcs10.X509Extensions.Add((CX509Extension)template);
var objDN = new CX500DistinguishedName();
var subjectName = "CN = shaunxu.me, OU = ADCS, O = Blog, L = Beijng, S = Beijing, C = CN";
objDN.Encode(subjectName, X500NameFlags.XCN_CERT_NAME_STR_NONE);
objPkcs10.Subject = objDN;
CObjectId objHash = new CObjectId();
objHash.InitializeFromAlgorithmName(
ObjectIdGroupId.XCN_CRYPT_HASH_ALG_OID_GROUP_ID,
ObjectIdPublicKeyFlags.XCN_CRYPT_OID_INFO_PUBKEY_ANY,
AlgorithmFlags.AlgorithmFlagsNone,
"SHA1");
objPkcs10.HashAlgorithm = objHash;
var objEnroll = new CX509Enrollment();
objEnroll.InitializeFromRequest(objPkcs10);
var strRequest = objEnroll.CreateRequest(EncodingType.XCN_CRYPT_STRING_BASE64);
return strRequest;
}
I successfully create request from private key. But I need to create request from public key. Please help me. What exactly I am missing here.
Thanks in advance
The purpose of a public-key certificate is to confirm the ownership of the key pair (private and public key). That means, when I present a certificate with my name on it to another party, the certification authority confirms (by signing the certificate) that the key pair in fact belongs to me. In particular, it means that I "own" the private key. (Ownership in this context means that I know it but nobody else does.)
In order to confirm this, the certification authority must be sure that I am in possession of the private key. So, any certification process must, at some point, involve the private key. I will not give away the private key but at least I have to use it in a challenge/response exchange. The public key is used to verify the validity of my response and thus the certification authority knows that I am having the private key.
Look at it a different way. The public key is publicly known. What use would it be to have a certificate that confirms that I am the "owner" of the public key? Everybody knows it, you cannot "own" the public key.