Freigeben über


'System.Security.Cryptography.CryptographicException - The index value is not valid'

While trying to extract the public key from a certificate you may get an exception that says: 'System.Security.Cryptography.CryptographicException - The index value is not valid'.

The exact error is CRYPT_E_INVALID_INDEX which means "The index value is not valid".

This happens if you try to get the public key using X509Certificate2::GetPublicKey method and the reason is you cannot use this method to get the public key. It has to be in a specific format.

First get a handle to an RSACryptoServiceProvider from the certificates public key and then export the CSP blob.

Example:

 RSACryptoServiceProvider PublicKey;
  
 PublicKey = (RSACryptoServiceProvider)Cert.PublicKey.Key;
  
 byte[] pbPublicKeyBlob = PublicKey.ExportCspBlob(false);
  
 A public key blob is defined as:
  
 BLOBHEADER blobheader;
  
 RSAPUBKEY rsapubkey;
  
 BYTE modulus[rsapubkey.bitlen / 8];

If you refer to the MSDN link https://msdn.microsoft.com/en-us/library/dd388945(VS.85).aspx, you will notice a function GetPublicKeyFromCertificate. This function GetPublicKeyFromCertificate expects the same blob minus the BLOBHEADER. This is the PUBLIC_KEY_VALUES structure that is defined as:

  
 typedef PUBLIC_KEY_VALUES struct
 {
  RSAPUBKEY rsapubkey;
  BYTE modulus[rsapubkey.bitlen / 8];
 }

To get the public key from the certificate you can use the SignedCms class as shown below.

Here in this code I am looking for version 3 certs that have no CA or extension. The BLOB actually had a certificate chain.

  
 X509Certificate2 Cert = new X509Certificate2();
 X509BasicConstraintsExtension BasicConstraints = new 
 X509BasicConstraintsExtension();
 string Oid = BasicConstraints.Oid.Value;
 SignedCms Pkcs7 = new SignedCms();
 Pkcs7.Decode(TestCert);
 for (int n = 0; n < Pkcs7.Certificates.Count; n++)
 {
 if ((Pkcs7.Certificates[n].Version == 3) && (null == 
 Pkcs7.Certificates[n].Extensions[Oid]))
 {
 Cert = Pkcs7.Certificates[n];
 break;
 }
 else if((Pkcs7.Certificates[n].Version == 3))
 {
 BasicConstraints = 
 (X509BasicConstraintsExtension)Pkcs7.Certificates[n].Extensions[Oid];
 if (BasicConstraints.CertificateAuthority == false)
 {
 Cert = Pkcs7.Certificates[n];
 break;
 }
 }
 }

Once you get the certificate you can use the code stated below to get the public key.

  
 RSACryptoServiceProvider PublicKey;
 PublicKey = (RSACryptoServiceProvider)Cert.PublicKey.Key;
 byte[] pbPublicKeyBlob = PublicKey.ExportCspBlob(false);

 

Shamik Misra