title: RSACryptoServiceProvider.ImportParameters throws System.Security.Cryptography.CryptographicException: Bad Data
body: <p>While upgrading a Windows Forms application from the .NET 1.1 framework to the .NET 3.5 framework, I have an issue with the <code>RSACryptoServiceProvider</code>. In a database I have stored binary files which contains an encrypted signature (SHA1 hash) and I have a public key stored in the filesystem as a text document containing a hexadecimal string. I have no issues in reading the file from the filesystem and getting the public key coded in a certificate.</p>
  
  <p>From the public key I get the modules and exponent field as part of the public key. I assign these values to a new instance of the <code>RSAParameters</code> object. Next I create a new instance of the <code>RSACryptoServiceProvider</code> class and call the <code>ImportParameters</code>. In that call the 3.5 code throws an exception. Note that the 1.1 code has no issues at all.</p>
  
  <p>Does anyone know if the byte arrays given to the properties of the RSAParameters needs to be converted, so I can use them in the 3.5 code also? I already tried to reversing the array or converting the byte array to BigInteger, but that is not solving my problems.</p>
  
  <p>For reference the full stacktrace:</p>
  
  <pre><code>System.Security.Cryptography.CryptographicException: Bad Data.
  
     at System.Security.Cryptography.CryptographicException.ThrowCryptogaphicException(Int32 hr)
     at System.Security.Cryptography.Utils._ImportKey(SafeProvHandle hCSP, Int32 keyNumber, CspProviderFlags flags, Object cspObject, SafeKeyHandle&amp; hKey)
     at System.Security.Cryptography.RSACryptoServiceProvider.ImportParameters(RSAParameters parameters)
  </code></pre>
  
  <p>Source code where it until the error:
                  //------------------------------------------------------------------*
                  // Verify certificates.                                             *
                  //------------------------------------------------------------------*</p>
  
  <pre><code>            // verify the CA certificate (output = public key van CA)
              byte[] lv_PkCA = VerifyCertificate(byte[], in_PkEUR);
  
              // verify the VU certificate (output = public key van VU)
              byte[] lv_PkVU = VerifyCertificate(byte[], lv_PkCA);
  
  
              //------------------------------------------------------------------
              // Verify the signatures
              //------------------------------------------------------------------
  
              // calculate hash with the SHA1 algorithm
              SHA1 lv_HashAlgoritm = new SHA1CryptoServiceProvider();
  
              byte[] lv_Modulus  = new byte[128];
              byte[] lv_Exponent = new byte[8];
              Buffer.BlockCopy(lv_PkVU, lv_PkVU.Length - 128 - 8, lv_Modulus , 0, lv_Modulus.Length);
              Buffer.BlockCopy(lv_PkVU, lv_PkVU.Length - 8      , lv_Exponent, 0, lv_Exponent.Length);
  
              // init RSA parameters
              RSAParameters lv_RSAKeyInfo = new RSAParameters();
              lv_RSAKeyInfo.Modulus  = lv_Modulus;
              lv_RSAKeyInfo.Exponent = lv_Exponent;
  
              // init RSA algoritme
              RSACryptoServiceProvider lv_RSA = new RSACryptoServiceProvider();
              lv_RSA.ImportParameters(lv_RSAKeyInfo);
  </code></pre>
  
  <p>For more reference, the content of the VerifyCertificate method.</p>
  
  <pre><code>private byte[] VerifyCertificate(
      byte[] in_Certificate,
      byte[] in_PublicKey)
  {
      byte[] lv_CHR      = new byte[8];
      byte[] lv_Modulus  = new byte[128];
      byte[] lv_Exponent = new byte[8];
      Buffer.BlockCopy(in_PublicKey, in_PublicKey.Length - 128 - 8 - 8, lv_CHR     , 0, lv_CHR.Length);
      Buffer.BlockCopy(in_PublicKey, in_PublicKey.Length - 128 - 8    , lv_Modulus , 0, lv_Modulus.Length);
      Buffer.BlockCopy(in_PublicKey, in_PublicKey.Length - 8          , lv_Exponent, 0, lv_Exponent.Length);
  
      byte[] lv_Signature = new byte[128];
      byte[] lv_Cn        = new byte[58];
      byte[] lv_CAR       = new byte[8];
      Buffer.BlockCopy(in_Certificate,   0, lv_Signature, 0, lv_Signature.Length);
      Buffer.BlockCopy(in_Certificate, 128, lv_Cn       , 0, lv_Cn.Length);
      Buffer.BlockCopy(in_Certificate, 186, lv_CAR      , 0, lv_CAR.Length);
  
      for (int lv_Index = 0; lv_Index &lt; lv_CAR.Length; lv_Index++)
      {
          if (lv_CAR[lv_Index] != lv_CHR[lv_Index])
              throw new Exception("Validation error: CAR not in public key.");
      }
  
      BigInteger lv_BiModulus   = new BigInteger(lv_Modulus);
      BigInteger lv_BiExponent  = new BigInteger(lv_Exponent);
      BigInteger lv_BiSignature = new BigInteger(lv_Signature);
      byte[] lv_Sr = lv_BiSignature.modPow(lv_BiExponent, lv_BiModulus).getBytes(lv_Signature.Length);
  
      if (lv_Sr.Length != 128)
          throw new Exception("The certificate coult not be validated: size of signature should be 128 bytes.");
      if ((lv_Sr[0]   != (byte)0x6A) ||
          (lv_Sr[127] != (byte)0xBC))
          throw new Exception("The certificate coult not be validated: invalid format.");
  
      byte[] lv_Cr = new byte[106];
      byte[] lv_H  = new byte[20];
      Buffer.BlockCopy(lv_Sr,   1, lv_Cr, 0, lv_Cr.Length);
      Buffer.BlockCopy(lv_Sr, 107, lv_H , 0, lv_H.Length);
  
      byte[] lv_C = new byte[164];
      Buffer.BlockCopy(lv_Cr, 0, lv_C,   0, lv_Cr.Length);
      Buffer.BlockCopy(lv_Cn, 0, lv_C, 106, lv_Cn.Length);
  
      // bereken de Hash van de public key
      SHA1CryptoServiceProvider lv_SHA1 = new SHA1CryptoServiceProvider();
      byte[] lv_Hash = lv_SHA1.ComputeHash(lv_C);
  
      // vergelijk de berekende hash met de hash in het certificaat
      if (lv_Hash.Length != lv_H.Length)
          throw new Exception("The certificate coult not be verified: hash length invalid.");
      for (int lv_Index = 0; lv_Index &lt; lv_Hash.Length; lv_Index++)
      {
          if (lv_Hash[lv_Index] != lv_H[lv_Index])
              throw new DiantaException("The certificate coult not be verified: hash not invalid.");
      }
  
      return lv_C;
  }
  </code></pre>
  
  <p>Thanks for your help in advance.</p>
  
  <p>Kind regards,</p>
  
  <p>René</p>