L
L
llexus2016-11-24 22:09:39
.NET
llexus, 2016-11-24 22:09:39

How to get Public Key of certificate identical to openssl output?

yes, it sounds pretty stupid. but it is.
suppose we have a crt.cer certificate in Base64,
then I run openssl x509 -in crt.cer -pubkey and get the output (for example, 294 bytes long):

MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A MIIBCgKCAQEAvUihVNnWYpu3uJmcLy PBecKu4ziVD7OIeZ + / V + + tJkXbc5 6OW8G + QDtJKuJkkuxGNLBNmLHbCyXsJ / US3kKkU7 / 7yK7jfWRNdqAKJdDTVxsWnxlo + / + 28ScGrAV6wK2bbK8GQBpsYRn1HKGCGceWIBCSqUfI7rwgwDnvqcW5PeivORd4 or5DdhgUMwiV5Vr2fvdcAiQR1CKgMphxO4 + OmZ4khpB / HT / xS4FscvfFsSBLM37jBMrnhY5yNKPeHZB2eYvehnnw22NFHJNksa + vVFXL9aJcZWJc / bqqlhlhL8eLdYSR / KA006PSInW8yWtd4IFVKJ1Moa41gCUZL81voQIDAQAB

Then I do the same in the UWP application code:
X509Certificate2 certificate = new X509Certificate2(certificateBlob);
var truePublicKey = Convert.ToBase64String(certificate.GetPublicKey());

the output is something like this (already 270 bytes long)
MIIBCgKCAQEAvUihVNnWYpu3uJmcLy + PBecKu4ziVD7OIeZ / V + tJkXbc5 + 6OW8G + QDtJKuJkkuxGNLBNmLHbCyXsJ / US3kKkU7 / 7yK7jfWRNdqAKJdDTVxsWnxlo + / 28ScGrAV6wK2bbK8GQBpsYRn1HKGCGceWIBCSqUfI7rwgwDnvqcW5PeivORd4 + or5DdhgUMwiV5Vr2fvdcAiQR1CKgMphxO4 + OmZ4khpB / HT / xS4FscvfFsSBLM37jBMrnhY5yNKPeHZB2eYvehnnw22NFHJNksa + vVFXL9aJcZWJc / bqqlhlhL8eLdYSR / KA006PSInW8yWtd4IFVKJ1Moa41gCUZL81voQIDAQAB

If you take a closer look, you can see that in the second case, a piece of data is cut off in front, but otherwise they are identical.
Using the online ASN1 data decoder, you can see that in the C # application "everything unnecessary is cut off", but this option does not suit me. Is it possible somehow to get an identical openssl result? (preferably without writing your own ASN encoder / decoder). Whatever I tried, it doesn’t work (And the key is needed exactly as in the first option, because the hash is then considered
PS: Using Chillkat, I managed to get the desired key, but it is not free. It is not suitable for my purposes.

Answer the question

In order to leave comments, you need to log in

1 answer(s)
L
llexus, 2017-02-22
@llexus

Alexey Nemiro , thanks for the tip! That's pretty much what happened. Might be useful to someone:

public static IEnumerable<string> GetPublicKeysList(IReadOnlyList<Certificate> serverCertificates)
        {
            for (var i = 0; i < serverCertificates.Count; i++)
            {
                string publicKey = null;
                try
                {
                    var certificate = new X509Certificate2(serverCertificates[0].GetCertificateBlob().ToArray());
                    var ms = new MemoryStream(certificate.RawData);
                    using (var reader = new BerReader(ms))
                    {
                        var asnCert = reader.ReadToEnd(true);
                        var pkNode = asnCert.ChildNodes[0].ChildNodes[0].ChildNodes[6]; // тут лежит сам ключ
                        byte[] pkBuffer = new byte[pkNode.Length + (pkNode.DataOffsetToStream - pkNode.StartPosition)];
                        ms.Seek(pkNode.StartPosition, SeekOrigin.Begin);
                        ms.Read(pkBuffer, 0, pkNode.Length + (int)(pkNode.DataOffsetToStream - pkNode.StartPosition)); // чтобы не потерять последние 4 байта
                        publicKey = Convert.ToBase64String(pkBuffer);
                    }
                }
                catch (Exception ex)
                {
                    throw new SecurityException($"Cant get public key {ex.Message}");
                }
                yield return publicKey;
            }
        }

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question