Как расшифровать строку в C #, которая была зашифрована в Delphi - PullRequest
2 голосов
/ 31 мая 2010


у нас есть проект, написанный на Delphi, который мы хотим преобразовать в C #. Проблема в том, что у нас есть некоторые пароли и настройки, которые зашифрованы и записаны в реестр. Когда нам нужен указанный пароль, мы получаем его из реестра и расшифровываем, чтобы мы могли его использовать. Для преобразования в C # мы должны сделать то же самое, чтобы приложение также могли использовать пользователи, которые имеют старую версию и хотят обновить ее.
Вот код, который мы используем для шифрования / дешифрования строк в Delphi:

unit uCrypt;

interface

function EncryptString(strPlaintext, strPassword : String) : String;
function DecryptString(strEncryptedText, strPassword : String) : String;

implementation

uses
  DCPcrypt2, DCPblockciphers, DCPdes, DCPmd5;
const
  CRYPT_KEY = '1q2w3e4r5t6z7u8';

function EncryptString(strPlaintext) : String;
var
  cipher           : TDCP_3des;
  strEncryptedText : String;
begin
  if strPlaintext <> '' then
  begin
    try
      cipher := TDCP_3des.Create(nil);
      try
        cipher.InitStr(CRYPT_KEY, TDCP_md5);
        strEncryptedText := cipher.EncryptString(strPlaintext);
      finally
        cipher.Free;
      end;
    except
      strEncryptedText := '';
    end;
  end;

  Result := strEncryptedText;
end;

function DecryptString(strEncryptedText) : String;
var
  cipher           : TDCP_3des;
  strDecryptedText : String;
begin
  if strEncryptedText <> '' then
  begin
    try
      cipher := TDCP_3des.Create(nil);
      try
        cipher.InitStr(CRYPT_KEY, TDCP_md5);
        strDecryptedText := cipher.DecryptString(strEncryptedText);
      finally
        cipher.Free;
      end;
    except
      strDecryptedText := '';
    end;
  end;

  Result := strDecryptedText;
end;
end.

Так, например, когда мы хотим зашифровать строку asdf1234, мы получаем результат WcOb/iKo4g8=.
Теперь мы хотим расшифровать эту строку в C #. Вот что мы пытались сделать:

public static void Main(string[] args)
{
    string Encrypted = "WcOb/iKo4g8=";
    string Password = "1q2w3e4r5t6z7u8";
    string DecryptedString = DecryptString(Encrypted, Password);
}

public static string DecryptString(string Message, string Passphrase)
{
    byte[] Results;
    System.Text.UTF8Encoding UTF8 = new System.Text.UTF8Encoding();

    // Step 1. We hash the passphrase using MD5
    // We use the MD5 hash generator as the result is a 128 bit byte array
    // which is a valid length for the TripleDES encoder we use below

    MD5CryptoServiceProvider HashProvider = new MD5CryptoServiceProvider();
    byte[] TDESKey = HashProvider.ComputeHash(UTF8.GetBytes(Passphrase));

    // Step 2. Create a new TripleDESCryptoServiceProvider object
    TripleDESCryptoServiceProvider TDESAlgorithm = new TripleDESCryptoServiceProvider();

    // Step 3. Setup the decoder
    TDESAlgorithm.Key = TDESKey;
    TDESAlgorithm.Mode = CipherMode.ECB;
    TDESAlgorithm.Padding = PaddingMode.None;

    // Step 4. Convert the input string to a byte[]
    byte[] DataToDecrypt = Convert.FromBase64String(Message);

    // Step 5. Attempt to decrypt the string
    try
    {
        ICryptoTransform Decryptor = TDESAlgorithm.CreateDecryptor();
        Results = Decryptor.TransformFinalBlock(DataToDecrypt, 0, DataToDecrypt.Length);
    }
    finally
    {
        // Clear the TripleDes and Hashprovider services of any sensitive information
        TDESAlgorithm.Clear();
        HashProvider.Clear();
    }

    // Step 6. Return the decrypted string in UTF8 format
    return UTF8.GetString(Results);
}

Ну, результат отличается от ожидаемого результата. После того, как мы позвоним DecryptString(), мы ожидаем получить asdf1234, но мы получим что-то еще.
Кто-нибудь имеет представление о том, как правильно расшифровать это?
Заранее спасибо
Simon

EDIT:
Хорошо, спасибо всем за ваши предложения. Мы не смогли выяснить, как все это сделать в C #, поэтому мы решили взять нашу резервную версию, используя DLL-библиотеку Delphi с P / Invoke, как было предложено.

Ответы [ 5 ]

1 голос
/ 31 мая 2010

Что-то отличается между вашими реализациями Delphi и C # - где-то.

Я предлагаю вам выполнить расшифровку по тестовым данным на обоих языках и выводить промежуточные звенья на каждом этапе процесса: посмотрите, где они расходятся. В частности, вам нужно проверить полученный ключ 3DES и байтовый массив, переданный в качестве ввода в шифр.

1 голос
/ 31 мая 2010

Я бы порекомендовал другой подход. Вы должны P / Invoke исходный код, чтобы прочитать пароли обратно в первый раз , а затем повторно сохранить с использованием кода .net. Таким образом, вы можете избежать проблем с различными процедурами шифрования на двух платформах.

0 голосов
/ 20 апреля 2016
Imports System.IO
Imports System.Text
Imports System.Security.Cryptography

Public Class Crypto
    Private Shared DES As New TripleDESCryptoServiceProvider
    Private Shared MD5 As New MD5CryptoServiceProvider
    Private Shared Function MD5Hash(ByVal value As String) As Byte()
        Return MD5.ComputeHash(ASCIIEncoding.ASCII.GetBytes(value))
    End Function

    Public Shared Function Encrypt(ByVal stringToEncrypt As String, ByVal key As String) As String
        DES.Key = Crypto.MD5Hash(key)
        DES.Mode = CipherMode.ECB
        Dim Buffer As Byte() = ASCIIEncoding.ASCII.GetBytes(stringToEncrypt)
        Return Convert.ToBase64String(DES.CreateEncryptor().TransformFinalBlock(Buffer, 0, Buffer.Length))
    End Function

    Public Shared Function Decrypt(ByVal encryptedString As String, ByVal key As String) As String
        Try
            DES.Key = Crypto.MD5Hash(key)
            DES.Mode = CipherMode.ECB
            Dim Buffer As Byte() = Convert.FromBase64String(encryptedString)
            Return ASCIIEncoding.ASCII.GetString(DES.CreateDecryptor().TransformFinalBlock(Buffer, 0, Buffer.Length))
        Catch ex As Exception
            MessageBox.Show("Invalid Key", "Decryption Failed", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)

        End Try
    End Function
End Class
0 голосов
/ 31 мая 2010

DES - блочный шифр. И заполнение требуется для выполнения операций шифрования и дешифрования. Если исходные данные для шифрования не кратны длине 64 бита, для шифрования требуется заполнение. Если вы не дополняете данные, вы получите неожиданные результаты в зависимости от того, какая схема заполнения используется по умолчанию здесь и там.

Итак, если вы можете, вы должны перешифровать все пароли в Delphi, добавив их перед шифрованием. Популярная схема заполнения состоит в добавлении 0x80 к данным и добавлении столько 0x00, сколько необходимо, чтобы размер данных был кратен 8 байтам. После этого вы сможете убрать отступ после расшифровки.

0 голосов
/ 31 мая 2010

При просмотре исходного кода DCP выглядит, что InitStr () инициализирует шифр 3DES в режиме CBC либо с IV = EncryptECB (0000000000000000), либо с IV = EncryptECB (FFFFFFFFFFFFFFFF) (в зависимости от IFDEF) .

Однако, используя их, я все еще не могу воспроизвести значения из Delphi-кода.

Я бы посоветовал вам выполнить отладку по коду с каждой стороны и точно указать, как строки преобразуются в байты и какое значение код присваивает производному ключу и IV.

...