locked
How to utilize the info from Windows::Security::Cryptography::Certificates::GetCertificateBlob()?

    Question

  • Hi, Dear all,

     

    I am a freshman to the cryptography. It seems that there is no exact information about it. I totally have no idea what we could utilize the certificate blob this function provides. I think we could get much useful info from it as MSDN says it is "the ASN.1 DER encoded certificate blob". Would you please give me any hint on how to get those info?

     

    Thanks!

    Thursday, May 22, 2014 10:41 PM

Answers

  • Hi B0L,

    For (1), it doesn't need to be a C# runtime component, I just pasted the C# code because I had it handy :) , you can implement the exact same code in C++ (or WinJS too)....

    For (2), the buffer (or the byte content) is just the representation of the certificate and has the Public Key present at a specific offset if you wanted to compare it with some hardcoded bytes to do some sort of comparison. If you just want to encrypt data based on the public key, you don't really need the buffer, you can just encrypt a string using the cryptographic key of the certificate using code like this, which is in C#, but totally doable in C++.

                    Uri serverUri = new Uri(https://somewebserver_out_there/);
                    HttpClient httpClient = new HttpClient();
                    HttpResponseMessage httpResponseMessage = await httpClient.GetAsync(serverUri);
                    Certificate aCertificate = httpResponseMessage.RequestMessage.TransportInformation.ServerCertificate;
                    IBuffer certBlob = aCertificate.GetCertificateBlob();
                    byte[] bCert = certBlob.ToArray();
                    int length;
    
                    // Assume Cert contains RSA public key
                    // Find matching OID in the certificate and return public key
                    byte[] rsaOID = EncodeOID("1.2.840.113549.1.1.1"); // 
                    int index = FindX509PubKeyIndex(bCert, rsaOID, out length);
    
                    // Found X509PublicKey in certificate so copy it.
                    if (index > -1)
                    {
                        byte[] X509PublicKey = new byte[length];
                        Array.Copy(bCert, index, X509PublicKey, 0, length);
                    }
                    // X509PublicKey now contains the Public Key which you can use for any type of validation....
    
                    // or you could just encrypt data using the public key
                    var cryptographicKey = Windows.Security.Cryptography.Core.PersistedKeyProvider.OpenPublicKeyFromCertificate(aCertificate, "SHA1", CryptographicPadding.RsaOaep);                
                    IBuffer unEncrypted = CryptographicBuffer.ConvertStringToBinary("hello world", BinaryStringEncoding.Utf8);
                    IBuffer Encrypted = CryptographicEngine.Encrypt(cryptographicKey, unEncrypted, null); 


    Windows Store Developer Solutions, follow us on Twitter: @WSDevSol|| Want more solutions? See our blog


    Thursday, June 05, 2014 1:55 AM
    Moderator

All replies

  • Hi B0L,

    I'm not familiar with this API, but I guess, probably use DataReader class is a good option since the API return type is a IBuffer interface. FromBuffer | fromBuffer method might help you.

    And I also find some documentation about ASN.1 Type System, probably can helps.

    Anyway, I agree there should be some more explanation for this API, I will report this to our seniors to see if it could be possible in the feature.

    --James


    <THE CONTENT IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED>
    Thanks
    MSDN Community Support

    Please remember to "Mark as Answer" the responses that resolved your issue. It is a common way to recognize those who have helped you, and makes it easier for other visitors to find the resolution later.

    Friday, May 23, 2014 10:06 AM
    Moderator
  • Hello, James, I really appreciate your reply! I will also do some investigation about it, and looking forward for your good news.... Thanks.

    Friday, May 23, 2014 10:11 AM
  • @B0L,

    The GetCertificateBlob will return you the cryptographic buffer of the Certificate you are working with. Based on this cryptographic buffer, you can use it to get the Public Key of the certificate if you want to, but it all really depends on the scenario you are trying to achieve.

    So, lets go back to the scenario of what you are trying to accomplish by retrieving the certificate blob. If you can give more details on what your end goal is, we should be able to help you correctly.

    An example of retrieving the public key of the certificate is to follow the approach here: http://blogs.msdn.com/b/winsdk/archive/2013/04/14/how-to-get-a-cryptographic-public-key-from-a-certificate-in-a-windows-store-application.aspx and use this modified code to retrieve the public key:

                    Certificate aCertificate = //... some way of creating your certificate
                    IBuffer certBlob = aCertificate.GetCertificateBlob();
                    byte[] bCert = certBlob.ToArray();
                    int length;
    
                    // Assume Cert contains RSA public key
                    // Find matching OID in the certificate and return public key
                    byte[] rsaOID = EncodeOID("1.2.840.113549.1.1.1"); // 
                    int index = FindX509PubKeyIndex(bCert, rsaOID, out length);
    
                    // Found X509PublicKey in certificate so copy it.
                    if (index > -1)
                    {
                        byte[] X509PublicKey = new byte[length];
                        Array.Copy(bCert, index, X509PublicKey, 0, length);
                    }
                    // X509PublicKey now contains the Public Key which you can use for any type of validation....


    Windows Store Developer Solutions, follow us on Twitter: @WSDevSol|| Want more solutions? See our blog

    Wednesday, June 04, 2014 5:31 PM
    Moderator
  • Hi, Prashant, I really appreciate your reply.

     

    1. If I want to get the public key, does it mean that I need to create a runtime component written in C#, then consume it in my C++ App?

    2. Could we get more info from the blob? I asked this because I totally have no idea what we could get from it.

     

    Thank you all!

    Thursday, June 05, 2014 1:40 AM
  • Hi B0L,

    For (1), it doesn't need to be a C# runtime component, I just pasted the C# code because I had it handy :) , you can implement the exact same code in C++ (or WinJS too)....

    For (2), the buffer (or the byte content) is just the representation of the certificate and has the Public Key present at a specific offset if you wanted to compare it with some hardcoded bytes to do some sort of comparison. If you just want to encrypt data based on the public key, you don't really need the buffer, you can just encrypt a string using the cryptographic key of the certificate using code like this, which is in C#, but totally doable in C++.

                    Uri serverUri = new Uri(https://somewebserver_out_there/);
                    HttpClient httpClient = new HttpClient();
                    HttpResponseMessage httpResponseMessage = await httpClient.GetAsync(serverUri);
                    Certificate aCertificate = httpResponseMessage.RequestMessage.TransportInformation.ServerCertificate;
                    IBuffer certBlob = aCertificate.GetCertificateBlob();
                    byte[] bCert = certBlob.ToArray();
                    int length;
    
                    // Assume Cert contains RSA public key
                    // Find matching OID in the certificate and return public key
                    byte[] rsaOID = EncodeOID("1.2.840.113549.1.1.1"); // 
                    int index = FindX509PubKeyIndex(bCert, rsaOID, out length);
    
                    // Found X509PublicKey in certificate so copy it.
                    if (index > -1)
                    {
                        byte[] X509PublicKey = new byte[length];
                        Array.Copy(bCert, index, X509PublicKey, 0, length);
                    }
                    // X509PublicKey now contains the Public Key which you can use for any type of validation....
    
                    // or you could just encrypt data using the public key
                    var cryptographicKey = Windows.Security.Cryptography.Core.PersistedKeyProvider.OpenPublicKeyFromCertificate(aCertificate, "SHA1", CryptographicPadding.RsaOaep);                
                    IBuffer unEncrypted = CryptographicBuffer.ConvertStringToBinary("hello world", BinaryStringEncoding.Utf8);
                    IBuffer Encrypted = CryptographicEngine.Encrypt(cryptographicKey, unEncrypted, null); 


    Windows Store Developer Solutions, follow us on Twitter: @WSDevSol|| Want more solutions? See our blog


    Thursday, June 05, 2014 1:55 AM
    Moderator
  • Hi, Prashant, Thank you very much! I've initially thought that FindX509PubKeyIndex is provided in C# but later found that you've provided us the implementation. :)

     

    Thank you all!

    Thursday, June 05, 2014 2:12 AM
  • Hi, Parashant,

     

    One more thing: I saw that you mentioned several times that "Assume Cert contains RSA public key". Does it mean that the (RSA)public key might not exist (or empty)? If yes, would you please tell me those scenarios that it would not exist(or empty)?

     

    Thanks!

    Thursday, June 05, 2014 2:37 AM