none
How to use C#(managed code) rewrite Cryptography API( unmanaged code)

    Question

  • Dear all:
    I have a application use VC6 to encrypt and decrypt data. But now I need rewrite the application in C# code, ask the code is managed.
    I don't know how can rewrite it . Can you help me? The code in C lanauage is follwoing:  
    BOOL DecryptFile(char *pData, int *piDataLen, char *pPswd)
    {
     HCRYPTPROV hCryptProv;
     HCRYPTKEY hKey;
     HCRYPTHASH hHash;
     PBYTE pbKeyBlob = NULL;
     DWORD dwCount;

     // Get a handle to the default provider.
     if( ! CryptAcquireContext(&hCryptProv, NULL, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT) )
     {
      if (GetLastError() == NTE_BAD_KEYSET)
      {
       if ( ! CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET) )
        return false;
      }
      else
       return false;
     }

     // Decrypt the file with a session key derived from a password.
     
     // Create a hash object.
     if( ! CryptCreateHash(hCryptProv, CALG_MD5, 0, 0, &hHash) )
      return false;
      
     // Hash in the password data.
     if( ! CryptHashData(hHash, (BYTE *)pPswd, strlen(pPswd), 0) )
      return false;

     // Derive a session key from the hash object.
     if( ! CryptDeriveKey(hCryptProv, ENCRYPT_ALGORITHM, hHash, KEYLENGTH, &hKey) )
      return false;

     // Destroy the hash object.
     if( ! (CryptDestroyHash(hHash)) )
      return false;
     hHash = 0;
     
     // The decryption key is now available, either having been imported
     // from a BLOB read in from the source file or having been created
     // using the password. This point in the program is not reached if
     // the decryption key is not available.
      
     // Decrypt data.
     //dwCount = *((unsigned long*)pData);
     if( ! CryptDecrypt(hKey, 0, true, 0, (BYTE*)(pData), (unsigned long*)piDataLen) )
      return false;

     *piDataLen = dwCount;
     
     // Free memory.
     if ( pbKeyBlob )
       free(pbKeyBlob); 
     
     // Destroy session key.
     if ( hKey )
     {
      if(!(CryptDestroyKey(hKey)))
       return false;
     }

     // Release provider handle.
     if ( hCryptProv )
     {
      if(!(CryptReleaseContext(hCryptProv, 0)))
       return false;
     }

     return true;
    } // end Decryptfile

    Monday, February 08, 2010 8:08 AM

Answers

  • Here is a raw conversion of your code, including the missing dwCount initialization.

            public const uint PROV_RSA_FULL = 1;
            public const uint CRYPT_VERIFYCONTEXT = 0xF0000000;
            public const uint CRYPT_NEWKEYSET = 0x00000008;
            public enum ALG_ID
            {
                CALG_MD5 = 0x00008003
            }
            [DllImport("advapi32.dll")]
            [return: MarshalAs(UnmanagedType.Bool)]
            public static extern bool CryptAcquireContext(out IntPtr phProv, string pszContainer, string pszProvider, uint dwProvType, uint dwFlags);
            [DllImport("advapi32.dll")]
            [return: MarshalAs(UnmanagedType.Bool)]
            public static extern bool CryptCreateHash(IntPtr hProv, ALG_ID Algid, IntPtr hKey, uint dwFlags, out  IntPtr phHash);
            [DllImport("advapi32.dll")]
            [return: MarshalAs(UnmanagedType.Bool)]
            public static extern bool CryptHashData(IntPtr hHash, byte[] pbData, int dwDataLen, uint dwFlags);
            [DllImport("advapi32.dll")]
            [return: MarshalAs(UnmanagedType.Bool)]
            public static extern bool CryptDeriveKey(IntPtr hProv, ALG_ID Algid, IntPtr hBaseData, uint dwFlags, ref IntPtr phKey);
            [DllImport("advapi32.dll")]
            [return: MarshalAs(UnmanagedType.Bool)]
            public static extern bool CryptDestroyHash(IntPtr hHash);
            [DllImport("advapi32.dll")]
            [return: MarshalAs(UnmanagedType.Bool)]
            public static extern bool CryptDecrypt(IntPtr hKey, IntPtr hHash, [MarshalAs(UnmanagedType.Bool)]bool Final, uint dwFlags, byte[] pbData, ref int pdwDataLen);
            [DllImport("advapi32.dll")]
            [return: MarshalAs(UnmanagedType.Bool)]
            public static extern bool CryptDestroyKey(IntPtr hKey);
            [DllImport("advapi32.dll")]
            [return: MarshalAs(UnmanagedType.Bool)]
            public static extern bool CryptReleaseContext(IntPtr hProv, uint dwFlags);
    
            const string MS_DEF_PROV = "Microsoft Base Cryptographic Provider v1.0";
            const uint NTE_BAD_KEYSET = 0x80090016;
    
            public static unsafe bool DecryptFile(byte[] pData, ref int piDataLen, byte[] pPswd)
            {
                IntPtr hCryptProv;
                IntPtr hKey;
                IntPtr hHash;
                int dwCount;
    
                // Get a handle to the default provider. 
                if (!CryptAcquireContext(out hCryptProv, null, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
                {
                    if (Marshal.GetLastWin32Error() == NTE_BAD_KEYSET)
                    {
                        if (!CryptAcquireContext(out hCryptProv, null, null, PROV_RSA_FULL, CRYPT_NEWKEYSET))
                            return false;
                    }
                    else
                        return false;
                }
    
                // Decrypt the file with a session key derived from a password. 
    
                // Create a hash object. 
                if (!CryptCreateHash(hCryptProv, ALG_ID.CALG_MD5, IntPtr.Zero, 0, out hHash))
                    return false;
    
                // Hash in the password data. 
                if (!CryptHashData(hHash, pPswd, pPswd.Length, 0))
                    return false;
    
                // Derive a session key from the hash object. 
                if (!CryptDeriveKey(hCryptProv, ENCRYPT_ALGORITHM, hHash, KEYLENGTH, ref hKey))
                    return false;
    
                // Destroy the hash object. 
                if (!(CryptDestroyHash(hHash)))
                    return false;
                hHash = IntPtr.Zero;
    
                // The decryption key is now available, either having been imported
                // from a BLOB read in from the source file or having been created 
                // using the password. This point in the program is not reached if 
                // the decryption key is not available.
    
                // Decrypt data. 
                //dwCount = *((unsigned long*)pData);
                if (!CryptDecrypt(hKey, IntPtr.Zero, true, 0, pData, ref piDataLen))
                    return false;
    
                piDataLen = dwCount;
    
                // Destroy session key. 
                if (hKey != IntPtr.Zero)
                {
                    if (!(CryptDestroyKey(hKey)))
                        return false;
                }
    
                // Release provider handle. 
                if (hCryptProv != IntPtr.Zero)
                {
                    if (!(CryptReleaseContext(hCryptProv, 0)))
                        return false;
                }
    
                return true;
            } // end Decryptfile
    
    • Marked as answer by Karry_Wong Tuesday, February 09, 2010 3:52 AM
    Monday, February 08, 2010 1:29 PM

All replies

  • You can write a bridge dll across Managed and Unmaged code

    Follow these links

    http://www.codeproject.com/KB/dotnet/bridge.aspx

    http://www.codeproject.com/KB/cs/essentialpinvoke.aspx

    http://blogs.microsoft.co.il/blogs/sasha/archive/2008/02/16/net-to-c-bridge.aspx




    Knowledge is like light; It spreads only when you have clear and transparent mind. - Sreedhar
    Monday, February 08, 2010 8:31 AM
  • Thank you , D.Sreedhar. But I want to my project is all managed code, not call dll. And I hope my project can work in 32bit and 64bit machine by setting 'Any CPU'. I really do not have to 2 dlls , one for 32bit , another for 64bit. 
    Monday, February 08, 2010 8:44 AM
  • Why is that line commented?

    //dwCount = *((unsigned long*)pData);
    Monday, February 08, 2010 11:07 AM
  • Here is a raw conversion of your code, including the missing dwCount initialization.

            public const uint PROV_RSA_FULL = 1;
            public const uint CRYPT_VERIFYCONTEXT = 0xF0000000;
            public const uint CRYPT_NEWKEYSET = 0x00000008;
            public enum ALG_ID
            {
                CALG_MD5 = 0x00008003
            }
            [DllImport("advapi32.dll")]
            [return: MarshalAs(UnmanagedType.Bool)]
            public static extern bool CryptAcquireContext(out IntPtr phProv, string pszContainer, string pszProvider, uint dwProvType, uint dwFlags);
            [DllImport("advapi32.dll")]
            [return: MarshalAs(UnmanagedType.Bool)]
            public static extern bool CryptCreateHash(IntPtr hProv, ALG_ID Algid, IntPtr hKey, uint dwFlags, out  IntPtr phHash);
            [DllImport("advapi32.dll")]
            [return: MarshalAs(UnmanagedType.Bool)]
            public static extern bool CryptHashData(IntPtr hHash, byte[] pbData, int dwDataLen, uint dwFlags);
            [DllImport("advapi32.dll")]
            [return: MarshalAs(UnmanagedType.Bool)]
            public static extern bool CryptDeriveKey(IntPtr hProv, ALG_ID Algid, IntPtr hBaseData, uint dwFlags, ref IntPtr phKey);
            [DllImport("advapi32.dll")]
            [return: MarshalAs(UnmanagedType.Bool)]
            public static extern bool CryptDestroyHash(IntPtr hHash);
            [DllImport("advapi32.dll")]
            [return: MarshalAs(UnmanagedType.Bool)]
            public static extern bool CryptDecrypt(IntPtr hKey, IntPtr hHash, [MarshalAs(UnmanagedType.Bool)]bool Final, uint dwFlags, byte[] pbData, ref int pdwDataLen);
            [DllImport("advapi32.dll")]
            [return: MarshalAs(UnmanagedType.Bool)]
            public static extern bool CryptDestroyKey(IntPtr hKey);
            [DllImport("advapi32.dll")]
            [return: MarshalAs(UnmanagedType.Bool)]
            public static extern bool CryptReleaseContext(IntPtr hProv, uint dwFlags);
    
            const string MS_DEF_PROV = "Microsoft Base Cryptographic Provider v1.0";
            const uint NTE_BAD_KEYSET = 0x80090016;
    
            public static unsafe bool DecryptFile(byte[] pData, ref int piDataLen, byte[] pPswd)
            {
                IntPtr hCryptProv;
                IntPtr hKey;
                IntPtr hHash;
                int dwCount;
    
                // Get a handle to the default provider. 
                if (!CryptAcquireContext(out hCryptProv, null, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
                {
                    if (Marshal.GetLastWin32Error() == NTE_BAD_KEYSET)
                    {
                        if (!CryptAcquireContext(out hCryptProv, null, null, PROV_RSA_FULL, CRYPT_NEWKEYSET))
                            return false;
                    }
                    else
                        return false;
                }
    
                // Decrypt the file with a session key derived from a password. 
    
                // Create a hash object. 
                if (!CryptCreateHash(hCryptProv, ALG_ID.CALG_MD5, IntPtr.Zero, 0, out hHash))
                    return false;
    
                // Hash in the password data. 
                if (!CryptHashData(hHash, pPswd, pPswd.Length, 0))
                    return false;
    
                // Derive a session key from the hash object. 
                if (!CryptDeriveKey(hCryptProv, ENCRYPT_ALGORITHM, hHash, KEYLENGTH, ref hKey))
                    return false;
    
                // Destroy the hash object. 
                if (!(CryptDestroyHash(hHash)))
                    return false;
                hHash = IntPtr.Zero;
    
                // The decryption key is now available, either having been imported
                // from a BLOB read in from the source file or having been created 
                // using the password. This point in the program is not reached if 
                // the decryption key is not available.
    
                // Decrypt data. 
                //dwCount = *((unsigned long*)pData);
                if (!CryptDecrypt(hKey, IntPtr.Zero, true, 0, pData, ref piDataLen))
                    return false;
    
                piDataLen = dwCount;
    
                // Destroy session key. 
                if (hKey != IntPtr.Zero)
                {
                    if (!(CryptDestroyKey(hKey)))
                        return false;
                }
    
                // Release provider handle. 
                if (hCryptProv != IntPtr.Zero)
                {
                    if (!(CryptReleaseContext(hCryptProv, 0)))
                        return false;
                }
    
                return true;
            } // end Decryptfile
    
    • Marked as answer by Karry_Wong Tuesday, February 09, 2010 3:52 AM
    Monday, February 08, 2010 1:29 PM
  • It might be easier to use the .Net RSACryptoServiceProvider()
    jon.stromer.galley
    Monday, February 08, 2010 4:38 PM
  • Thank you Louis  and  jgallye. I know use  RSACryptoServiceProvider() , my problem is I don't know how to set the parameters about RSACryptoServiceProvider.
    Tuesday, February 09, 2010 3:50 AM
  • This might get you started:

    public void RSA_GenerateDummyKeys(ref string publicKey, ref string privateKey)
    {
        using (RSACryptoServiceProvider RSA = new RSACryptoServiceProvider()) {
            publicKey = RSA.ToXmlString(false);
            privateKey = RSA.ToXmlString(true);
        }
    }
    
    public string RSA_Encrypt(string message, string publicKey)
    {
        byte[] Encrypted = null;
        
        using (RSACryptoServiceProvider RSA = new RSACryptoServiceProvider()) {
            RSA.FromXmlString(publicKey);
            Encrypted = RSA.Encrypt(Encoding.Unicode.GetBytes(message), false);
        }
        
        return System.Convert.ToBase64String(Encrypted);
    }
    
    public string RSA_Decrypt(string message, string privateKey)
    {
        byte[] Encrypted = System.Convert.FromBase64String(message);
        string Decryption = null;
        
        using (RSACryptoServiceProvider RSA = new RSACryptoServiceProvider()) {
            RSA.FromXmlString(privateKey);
            Decryption = Encoding.Unicode.GetString(RSA.Decrypt(Encrypted, false));
        }
        
        return Decryption;
    }
    
    
    public void Main()
    {
        string RSAKey_Public = string.Empty;
        string RSAKey_Private = string.Empty;
        
        RSA_GenerateDummyKeys(RSAKey_Public, RSAKey_Private);
        
        string message = "This is a test";
        var encryption = RSA_Encrypt(message, RSAKey_Public);
        var decryption = RSA_Decrypt(encryption, RSAKey_Private);
        
        
        Console.WriteLine("==================================");
        Console.WriteLine("Message:");
        Console.WriteLine(message);
        Console.WriteLine("==================================");
        Console.WriteLine("");
        Console.WriteLine("");
        
        Console.WriteLine("==================================");
        Console.WriteLine("Encryption:");
        Console.WriteLine(encryption);
        Console.WriteLine("==================================");
        Console.WriteLine("");
        Console.WriteLine("");
        
        Console.WriteLine("==================================");
        Console.WriteLine("Decryption:");
        Console.WriteLine(decryption);
        Console.WriteLine("==================================");
        Console.WriteLine("");
        Console.WriteLine("");
        
        Console.WriteLine("Strike a key");
            
        Console.ReadKey();
    }
    


    jon.stromer.galley
    Tuesday, February 09, 2010 5:12 AM
  • // Decrypt the file with a session key derived from a password.

                // Create a hash object.
                if (!CryptCreateHash(hCryptProv, ALG_ID.CALG_MD5, IntPtr.Zero, 0, out hHash))
                    return false;

                // Hash in the password data.
                if (!CryptHashData(hHash, pPswd, pPswd.Length, 0)) return false;


    RSACryptoServiceProvider() where set the key hash by md5 ?
    Tuesday, February 09, 2010 5:46 AM
  • I add that to the example this morning.  Need to pay the bills first :-)
    jon.stromer.galley
    Tuesday, February 09, 2010 1:40 PM
  • Hi Louis,

    Is it possible to pm or email you, I have a similar issue which I need some guidance with..Thanks

    Tuesday, July 22, 2014 3:26 PM