Import RSA public key from certificate

Our client has an RSA public key stored in a certificate.

We need this key encoded in our WinRT application, so we can encrypt the client part. However, we are having problems importing the key into an instance of the CryptographicKey class.

We use ImportPublicKey for the RSAP provider:

rsaProvider = AsymmetricKeyAlgorithmProvider.OpenAlgorithm(AsymmetricAlgorithmNames.RsaPkcs1); key = rsaProvider.ImportPublicKey(publicKeyBuffer); 

We tried to upload several things to publicKeyBuffer: certificate, public key exported from the certificate in several formats.

How do we load their public key?

0
source share
3 answers

I found this article in the MSDN forum very useful. Carlos Lopez posted some code to get the public key from a certificate encoded in Base64.

http://social.msdn.microsoft.com/Forums/en-US/17e1467a-2de7-47d2-8d8c-130518eaac68/how-to-use-a-x509-certificate-not-a-pfx-to-verify- a-signature

Here is the code:

 public static CryptographicKey GetCryptographicPublicKeyFromCert(string strCert) { int length; CryptographicKey CryptKey = null; byte[] bCert = Convert.FromBase64String(strCert); // 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); AsymmetricKeyAlgorithmProvider AlgProvider = AsymmetricKeyAlgorithmProvider.OpenAlgorithm(AsymmetricAlgorithmNames.RsaPkcs1); CryptKey = AlgProvider.ImportPublicKey(CryptographicBuffer.CreateFromByteArray(X509PublicKey)); } return CryptKey; } static int FindX509PubKeyIndex(byte[] Reference, byte[] value, out int length) { int index = -1; bool found; length = 0; for (int n = 0; n < Reference.Length; n++) { if ((Reference[n] == value[0]) && (n + value.Length < Reference.Length)) { index = n; found = true; for (int m = 1; m < value.Length; m++) { if (Reference[n + m] != value[m]) { found = false; break; } } if (found) break; else index = -1; } } if (index > -1) { // Find outer Sequence while (index > 0 && Reference[index] != 0x30) index--; index--; while (index > 0 && Reference[index] != 0x30) index--; } if (index > -1) { // Find the length of encoded Public Key if ((Reference[index + 1] & 0x80) == 0x80) { int numBytes = Reference[index + 1] & 0x7F; for (int m = 0; m < numBytes; m++) { length += (Reference[index + 2 + m] << ((numBytes - 1 - m) * 8)); } length += 4; } else { length = Reference[index + 1] + 2; } } return index; } static public byte[] EncodeOID(string szOID) { int[] OIDNums; byte[] pbEncodedTemp = new byte[64]; byte[] pbEncoded = null; int n, index, num, count; OIDNums = ParseOID(szOID); pbEncodedTemp[0] = 6; pbEncodedTemp[2] = Convert.ToByte(OIDNums[0] * 40 + OIDNums[1]); count = 1; for (n = 2, index = 3; n < OIDNums.Length; n++) { num = OIDNums[n]; if (num >= 16384) { pbEncodedTemp[index++] = Convert.ToByte(num / 16384 | 0x80); num = num % 16384; count++; } if (num >= 128) { pbEncodedTemp[index++] = Convert.ToByte(num / 128 | 0x80); num = num % 128; count++; } pbEncodedTemp[index++] = Convert.ToByte(num); count++; } pbEncodedTemp[1] = Convert.ToByte(count); pbEncoded = new byte[count + 2]; Array.Copy(pbEncodedTemp, 0, pbEncoded, 0, count + 2); return pbEncoded; } static public int[] ParseOID(string szOID) { int nlast, n = 0; bool fFinished = false; int count = 0; int[] dwNums = null; do { nlast = n; n = szOID.IndexOf(".", nlast); if (n == -1) fFinished = true; count++; n++; } while (fFinished == false); dwNums = new int[count]; count = 0; fFinished = false; do { nlast = n; n = szOID.IndexOf(".", nlast); if (n != -1) { dwNums[count] = Convert.ToInt32(szOID.Substring(nlast, n - nlast), 10); } else { fFinished = true; dwNums[count] = Convert.ToInt32(szOID.Substring(nlast, szOID.Length - nlast), 10); } n++; count++; } while (fFinished == false); return dwNums; } 
+1
source

Two things:

  • The key argument of ImportPublicKey is an IBuffer. The easiest way to get this is to use the ToBuffer Extension Method for byte [].
  • Use the ImportPublicKey override that accepts both IBuffer and CryptographicPublicKeyBlobType , in particular CryptographicPublicKeyBlobType.X509SubjectPublicKeyInfo. Go to the topic public key information field from the certificate.
0
source

For those who are banging their heads on how you can use the public key stored in the certificate in the WinRT application, let me ease your pain: you cannot, at least not directly.

The AsymmetricKeyAlgorithmProvider.ImportPublicKey function accepts IBuffer and CryptographicPublicKeyBlobType, KeyBlob (IBuffer) is the public key of the certificate, not the full certificate, only its public key.

But you cannot get the public key of the certificate without parsing it first, here's the problem: there is no way to parse the certificate on WinRT, given that the most used class for this task, X509Certificate, is not available and is not its namespace, but the means for certificates should only be used for web service connections.

The only workaround is to implement a certificate parser or migrate such functions from an open source project, such as Bouncy Castle . So, if you know one, leave it in the comments.

By the way, to export the public key from a certificate (in plain .NET) in a format that can be used in a WinRT application, use this:

 X509Certificate2 Certificate; .... byte[] CertificatePublicKey = Certificate.PublicKey.EncodedKeyValue.RawData; 

Then in a WinRT application use this:

 AsymmetricKeyAlgorithmProvider algorithm = AsymmetricKeyAlgorithmProvider.OpenAlgorithm(AsymmetricAlgorithmNames.RsaSignPkcs1Sha1); IBuffer KeyBuffer = CryptographicBuffer.DecodeFromBase64String(CertificatePublicKeyContent); CryptographicKey key = algorithm.ImportPublicKey(KeyBuffer, CryptographicPublicKeyBlobType.Pkcs1RsaPublicKey); 

Note that I first encoded the public key in base 64, but you can use raw binary data instead (there are more methods for this CryptographicBuffer class).

0
source

All Articles