Зашифровать в VB.NET и расшифровать в PHP

Я пытаюсь написать функцию на PHP и VB.NET, которая использует Triple DES для передачи ОБА направления зашифровали данные. Проблема в том, что когда я пытаюсь расшифровать строку, зашифрованную в VB.NET с помощью PHP, я получаю сообщение об ошибке, в котором говорится, что размер блока IV должен совпадать.

Класс, который я написал в VB.NET, выглядит следующим образом и полностью функционален, поскольку он безупречно шифрует и расшифровывает свои собственные блоки.

    Imports System
    Imports System.Text
    Imports System.IO
    Imports System.Security.Cryptography

    Public Class Cipher

        Dim method As TripleDESCryptoServiceProvider
        Dim key As Byte()

        Public Property Password() As String
            Get
                Return System.Text.Encoding.Unicode.GetString(Key)
            End Get
            Set(value As String)
                key = System.Text.Encoding.Unicode.GetBytes(value)
            End Set
        End Property

        Public Function Encrypt(data As String) As String
            Dim ms As New System.IO.MemoryStream

            ' Create the encoder to write to the stream.
            Dim dataBytes() As Byte = System.Text.Encoding.Unicode.GetBytes(data)
            Dim encStream As New CryptoStream(ms, method.CreateEncryptor(), System.Security.Cryptography.CryptoStreamMode.Write)

            ' Use the crypto stream to write the byte array to the stream.
            encStream.Write(dataBytes, 0, dataBytes.Length)
            encStream.FlushFinalBlock()

            ' IV and Ciphered string are each Base64'd and seperated by a comma, then the whole result is Base64'd
            Return Convert.ToBase64String(System.Text.Encoding.Unicode.GetBytes(Convert.ToBase64String(method.IV) & "," & Convert.ToBase64String(ms.ToArray)))
        End Function

        Public Function Decrypt(data As String) As String
            ' Convert the encrypted text string to a byte array.

            Dim partDecoded As String = System.Text.Encoding.Unicode.GetString(Convert.FromBase64String(data))
            Dim dataBytes() As Byte

            If InStr(partDecoded, ",") > 0 Then

                Dim parts() As String = Split(partDecoded, ",")

                ' Get IV from first part
                method.IV = Convert.FromBase64String(parts(0))

                ' Get ciphered data from second part
                dataBytes = Convert.FromBase64String(parts(1))

                ' Create the stream.
                Dim ms As New System.IO.MemoryStream
                ' Create the decoder to write to the stream.
                Dim decStream As New CryptoStream(ms, method.CreateDecryptor(), System.Security.Cryptography.CryptoStreamMode.Write)

                ' Use the crypto stream to write the byte array to the stream.
                decStream.Write(dataBytes, 0, dataBytes.Length)
                decStream.FlushFinalBlock()

                ' Convert the plaintext stream to a string.
                Return System.Text.Encoding.Unicode.GetString(ms.ToArray)
            Else
                Return False
            End If

        End Function

        Public Sub New()
            method = New TripleDESCryptoServiceProvider
            method.Mode = CipherMode.CFB
            method.GenerateIV()
        End Sub
    End Class

Пример использования вышеуказанного класса

    Dim c As New Cipher
    c.Password = "12345"

    Dim encrypted As String = c.Encrypt("hello")
    Debug.Print(encrypted)

    Dim decrypted As String = c.Decrypt(encrypted)
    Debug.Print(decrypted)

Теперь у меня также есть следующий код PHP, который ТАКЖЕ работает (сам по себе)

    class Cipher {
        private $iv;
        private $securekey;

        function __construct($key) {
            $this->securekey = $key;
        }

        function encrypt($string) {
            $this->iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_3DES, MCRYPT_MODE_CFB),MCRYPT_DEV_RANDOM);
            $encrypted = base64_encode(mcrypt_encrypt(MCRYPT_3DES, $this->securekey, $string, MCRYPT_MODE_CFB, $this->iv));
            return base64_encode(base64_encode($this->iv) . ',' . $encrypted);
        }

        function decrypt($string) {
            $decrypt = base64_decode($string);
            if(strpos($decrypt,',') > 0) {
                $decrypt = explode(',', $decrypt);
                $this->iv = base64_decode($decrypt[0]);
                return trim(mcrypt_decrypt(MCRYPT_3DES, $this->securekey, base64_decode($decrypt[1]), MCRYPT_MODE_CFB, $this->iv));
            } else {
                return false;
            }
        }
    }

Пример использования PHP

    $c = new Cipher("12345");
    $encrypted = $c->encrypt("hello");
    echo 'Encrypted: ' . $encrypted . '<br />';

    $decrypted = $c->decrypt($encrypted);
    echo 'Decrypted: ' . $decrypted . '<br />';

    $vb = "MwBOAEoAOQBjAEgAcQAyAC8ASABzAD0ALABmAEUAOQBaAHYAVwBzAFUAYQB3AFYARwBGAHUANABLAGUAVgB3AFcAaABRAD0APQA=";
    echo 'VB.NET Dec: ' . $c->decrypt($vb);

Выше я включил в использование PHP строку Base64, созданную с помощью VB.NET, которая декодирует ИДЕАЛЬНО в VB.NET как переменная $vb.

Это сводит меня с ума, так как код правильный и функциональный - в обоих случаях - так что мне не хватает, и можете ли вы указать/исправить проблему. Я не хочу использовать Rijndael или исследовать другие методы шифрования, так как хорошо известно, что этот изначально работает на нескольких устройствах (iOS, Android, Windows, Linux и т. д.).


person Kraang Prime    schedule 12.07.2014    source источник
comment
почему не риандель? stackoverflow.com/a/2175331/3802940   -  person etr    schedule 12.07.2014
comment
медленно, а не на 100% на всех платформах. в этой статье также есть вещи, которые просто не соответствуют действительности, например, шифрование с уменьшенным битом из-за 3 проходов DES? .... сам алгоритм немного сложнее, чем 3 прохода той же механики. несмотря на это, tripledes де-факто -- rijandel не является. Замена этого на Rijandel может решить одну проблему, но создать дюжину других. Мне нужно решение этой проблемы под рукой... TripleDES. Почему он отлично работает в обоих случаях, но, несмотря на то, что они утверждают, что следуют RFC, а не друг другу. Один не следует, и я уверен, что это PHP.   -  person Kraang Prime    schedule 12.07.2014


Ответы (1)


Поскольку никто не смог предоставить полностью функциональное ДВУНАПРАВЛЕННОЕ решение, я взял на себя смелость предоставить его сообществу в этой статье.

Проблема в том, что PHP не соответствует стандартам, заставляя строки дополняться для соответствия. В настоящее время не существует известного способа надежно передать IV, если он генерируется случайным образом между .NET и PHP (если вы узнаете, как, или это изменится, пожалуйста, не стесняйтесь пересматривать это).

Ниже приведено ПОЛНОЕ решение для шифрования данных с использованием Triple DES способом, совместимым с .NET и PHP, который обеспечивает двунаправленную шифрованную связь Triple DES. Этот метод также совместим с Java, Delphi, Objective-C и многими другими языками, однако такой код здесь не будет предоставлен, поскольку это не решение опубликованного вопроса.


VB.NET Тройной класс DES

    Imports System
    Imports System.Text
    Imports System.IO
    Imports System.Security.Cryptography

    Public Class TripleDES

        Private bPassword As Byte()
        Private sPassword As String

        Public Sub New(Optional ByVal Password As String = "password")
            ' On Class Begin
            Me.Password = Password
        End Sub

        Public ReadOnly Property PasswordHash As String
            Get
                Dim UTF8 As System.Text.UTF8Encoding = New System.Text.UTF8Encoding
                Return UTF8.GetString(bPassword)
            End Get
        End Property

        Public Property Password() As String
            Get
                Dim UTF8 As System.Text.UTF8Encoding = New System.Text.UTF8Encoding
                Return sPassword
            End Get
            Set(value As String)
                Dim UTF8 As System.Text.UTF8Encoding = New System.Text.UTF8Encoding
                Dim HashProvider As MD5CryptoServiceProvider = New MD5CryptoServiceProvider()
                bPassword = HashProvider.ComputeHash(UTF8.GetBytes(value))
                sPassword = value
            End Set
        End Property

    #Region "Encrypt"

        ' Encrypt using Password from Property Set (pre-hashed)
        Public Function Encrypt(ByVal Message As String) As String
            Dim Results() As Byte
            Dim UTF8 As System.Text.UTF8Encoding = New System.Text.UTF8Encoding
            Using HashProvider As MD5CryptoServiceProvider = New MD5CryptoServiceProvider()
                Dim TDESKey() As Byte = bPassword
                Using TDESAlgorithm As TripleDESCryptoServiceProvider = New TripleDESCryptoServiceProvider() With {.Key = TDESKey, .Mode = CipherMode.ECB, .Padding = PaddingMode.PKCS7}
                    Dim DataToEncrypt() As Byte = UTF8.GetBytes(Message)
                    Try
                        Dim Encryptor As ICryptoTransform = TDESAlgorithm.CreateEncryptor
                        Results = Encryptor.TransformFinalBlock(DataToEncrypt, 0, DataToEncrypt.Length)
                    Finally
                        TDESAlgorithm.Clear()
                        HashProvider.Clear()
                    End Try
                End Using
            End Using
            Return Convert.ToBase64String(Results)
        End Function

        ' Encrypt using Password as byte array
        Private Function Encrypt(ByVal Message As String, ByVal Password() As Byte) As String
            Dim Results() As Byte
            Dim UTF8 As System.Text.UTF8Encoding = New System.Text.UTF8Encoding
            Using HashProvider As MD5CryptoServiceProvider = New MD5CryptoServiceProvider()
                Dim TDESKey() As Byte = HashProvider.ComputeHash(UTF8.GetBytes(UTF8.GetString(Password)))
                Using TDESAlgorithm As TripleDESCryptoServiceProvider = New TripleDESCryptoServiceProvider() With {.Key = TDESKey, .Mode = CipherMode.ECB, .Padding = PaddingMode.PKCS7}
                    Dim DataToEncrypt() As Byte = UTF8.GetBytes(Message)
                    Try
                        Dim Encryptor As ICryptoTransform = TDESAlgorithm.CreateEncryptor
                        Results = Encryptor.TransformFinalBlock(DataToEncrypt, 0, DataToEncrypt.Length)
                    Finally
                        TDESAlgorithm.Clear()
                        HashProvider.Clear()
                    End Try
                End Using
            End Using
            Return Convert.ToBase64String(Results)
        End Function

        ' Encrypt using Password as string
        Public Function Encrypt(ByVal Message As String, ByVal Password As String) As String
            Dim Results() As Byte
            Dim UTF8 As System.Text.UTF8Encoding = 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 Triple DES encoder we use below
            Using HashProvider As MD5CryptoServiceProvider = New MD5CryptoServiceProvider()
                Dim TDESKey() As Byte = HashProvider.ComputeHash(UTF8.GetBytes(Password))

                ' Step 2. Create a new TripleDESCryptoServiceProvider object

                ' Step 3. Setup the encoder
                Using TDESAlgorithm As TripleDESCryptoServiceProvider = New TripleDESCryptoServiceProvider() With {.Key = TDESKey, .Mode = CipherMode.ECB, .Padding = PaddingMode.PKCS7}
                    ' Step 4. Convert the input string to a byte[]

                    Dim DataToEncrypt() As Byte = UTF8.GetBytes(Message)

                    ' Step 5. Attempt to encrypt the string
                    Try
                        Dim Encryptor As ICryptoTransform = TDESAlgorithm.CreateEncryptor
                        Results = Encryptor.TransformFinalBlock(DataToEncrypt, 0, DataToEncrypt.Length)
                    Finally
                        ' Clear the Triple Des and Hashprovider services of any sensitive information
                        TDESAlgorithm.Clear()
                        HashProvider.Clear()
                    End Try
                End Using
            End Using

            ' Step 6. Return the encrypted string as a base64 encoded string
            Return Convert.ToBase64String(Results)
        End Function
    #End Region

    #Region "Decrypt"
        ' Decrypt using Password from Property (pre-hashed)
        Public Function Decrypt(ByVal Message As String) As String
            Dim Results() As Byte
            Dim UTF8 As System.Text.UTF8Encoding = New System.Text.UTF8Encoding
            Using HashProvider As MD5CryptoServiceProvider = New MD5CryptoServiceProvider()
                Dim TDESKey() As Byte = Me.bPassword
                Using TDESAlgorithm As TripleDESCryptoServiceProvider = New TripleDESCryptoServiceProvider() With {.Key = TDESKey, .Mode = CipherMode.ECB, .Padding = PaddingMode.PKCS7}
                    Dim DataToDecrypt() As Byte = Convert.FromBase64String(Message)
                    Try
                        Dim Decryptor As ICryptoTransform = TDESAlgorithm.CreateDecryptor
                        Results = Decryptor.TransformFinalBlock(DataToDecrypt, 0, DataToDecrypt.Length)
                    Finally
                        TDESAlgorithm.Clear()
                        HashProvider.Clear()
                    End Try
                End Using
            End Using
            Return UTF8.GetString(Results)
        End Function

        ' Decrypt using Password as Byte array
        Public Function Decrypt(ByVal Message As String, ByVal Password() As Byte) As String
            Dim Results() As Byte
            Dim UTF8 As System.Text.UTF8Encoding = New System.Text.UTF8Encoding
            Using HashProvider As MD5CryptoServiceProvider = New MD5CryptoServiceProvider()
                Dim TDESKey() As Byte = HashProvider.ComputeHash(UTF8.GetBytes(UTF8.GetString(Password)))
                Using TDESAlgorithm As TripleDESCryptoServiceProvider = New TripleDESCryptoServiceProvider() With {.Key = TDESKey, .Mode = CipherMode.ECB, .Padding = PaddingMode.PKCS7}
                    Dim DataToDecrypt() As Byte = Convert.FromBase64String(Message)
                    Try
                        Dim Decryptor As ICryptoTransform = TDESAlgorithm.CreateDecryptor
                        Results = Decryptor.TransformFinalBlock(DataToDecrypt, 0, DataToDecrypt.Length)
                    Finally
                        TDESAlgorithm.Clear()
                        HashProvider.Clear()
                    End Try
                End Using
            End Using
            Return UTF8.GetString(Results)
        End Function


        ' Decrypt using Password as string
        Public Function Decrypt(ByVal Message As String, ByVal Password As String) As String
            Dim Results() As Byte
            Dim UTF8 As System.Text.UTF8Encoding = New System.Text.UTF8Encoding

            ' Step 1. We hash the pass phrase using MD5
            ' We use the MD5 hash generator as the result is a 128-bit byte array
            ' which is a valid length for the Triple DES encoder we use below
            Using HashProvider As MD5CryptoServiceProvider = New MD5CryptoServiceProvider()
                Dim TDESKey() As Byte = HashProvider.ComputeHash(UTF8.GetBytes(Password))

                ' Step 2. Create a new TripleDESCryptoServiceProvider object
                ' Step 3. Setup the decoder
                Using TDESAlgorithm As TripleDESCryptoServiceProvider = New TripleDESCryptoServiceProvider() With {.Key = TDESKey, .Mode = CipherMode.ECB, .Padding = PaddingMode.PKCS7}

                    ' Step 4. Convert the input string to a byte[]
                    Dim DataToDecrypt() As Byte = Convert.FromBase64String(Message)
                    ' Step 5. Attempt to decrypt the string
                    Try
                        Dim Decryptor As ICryptoTransform = TDESAlgorithm.CreateDecryptor
                        Results = Decryptor.TransformFinalBlock(DataToDecrypt, 0, DataToDecrypt.Length)
                    Finally

                        ' Clear the Triple Des and Hash provider services of any sensitive information
                        TDESAlgorithm.Clear()
                        HashProvider.Clear()
                    End Try
                End Using
            End Using

            ' Step 6. Return the decrypted string in UTF8 format
            Return UTF8.GetString(Results)
        End Function

    #End Region

    End Class

Использование класса VB.NET Triple DES

    Dim tdes As New TripleDES("12345")
    Dim vbEncrypted = tdes.Encrypt("Encrypted using VB.NET")
    Dim phpEncrypted = "5Ittyr0+jiI7QQmPrvSVnMc9MEWQCjAN"

    Debug.Print("PHP Encrypted: " & phpEncrypted)
    Debug.Print("VB Encrypted: " & vbEncrypted)
    Debug.Print("PHP Encrypted (decrypted result): " & tdes.Decrypt(phpEncrypted))
    Debug.Print("VB Encrypted (decrypted result): " & tdes.Decrypt(vbEncrypted))

PHP Тройной класс DES

    class TripleDES {
        private $bPassword;
        private $sPassword;

        function __construct($Password) {
            $this->bPassword  = md5(utf8_encode($Password),TRUE);
            $this->bPassword .= substr($this->bPassword,0,8);
            $this->sPassword - $Password;
        }

        function Password($Password = "") {
            if($Password == "") {
                return $this->sPassword;
            } else {
                $this->bPassword  = md5(utf8_encode($Password),TRUE);
                $this->bPassword .= substr($this->bPassword,0,8);
                $this->sPassword - $Password;
            }
        }

        function PasswordHash() {
            return $this->bPassword;
        }

        function Encrypt($Message, $Password = "") {
            if($Password <> "") { $this->Password($Password); }
            $size=mcrypt_get_block_size('tripledes','ecb');
            $padding=$size-((strlen($Message)) % $size);
            $Message .= str_repeat(chr($padding),$padding);
            $encrypt  = mcrypt_encrypt('tripledes',$this->bPassword,$Message,'ecb');
            return base64_encode($encrypt);
        }

        function Decrypt($message, $Password = "") {
            if($Password <> "") { $this->Password($Password); }
            return trim(mcrypt_decrypt('tripledes', $this->bPassword, base64_decode($message), 'ecb'), ord(2));
        }

    }

Использование класса PHP Triple DES

    $tdes = new TripleDES("12345");

    $phpEncrypted = $tdes->encrypt("Encrypted using PHP");
    $vbEncrypted = "5Ittyr0+jiI7QQmPrvSVnP3s2CeoTJmF"; // Encrypted using VB.NET

    echo "PHP Encrypted: " . $phpEncrypted . '<br />';
    echo "VB Encrypted: " . $vbEncrypted . '<br />';
    echo "PHP Encrypted (decrypted result): " . $tdes->Decrypt($phpEncrypted) . '<br />';
    echo "VB Encrypted (decrypted result): " . $tdes->Decrypt($vbEncrypted) . '<br />';

Я сделал все, что мог, чтобы уровень удобства использования обоих классов был одинаковым, насколько естественно позволяли языки. Поскольку PHP не позволяет перегружать функции, мне пришлось использовать пароль как необязательный параметр, который является строковым значением. Решение VB.NET имеет дополнительное переопределение, позволяющее передавать байтовое значение строки пароля в функциях шифрования/дешифрования. Пример кода, представленный для демонстрации использования каждого из них, показывает наиболее упрощенную форму создания экземпляра объекта, который оба класса позволяют устанавливать пароль при создании объекта.

Всем, кто ломал себе голову, пытаясь найти РАБОТАЮЩЕЕ двунаправленное решение для Triple DES (и не хотел, чтобы его навязывали в коробку, на которую все, кажется, указывают -- Rijndael), то это решение для вас, и вы можете перестать биться головой о стену.

Добавлен перевод на C# класса VB.NET TripleDES

Класс C# ( Добавлено 11 января 2017 г. )

using System;
using System.Security.Cryptography;

public class TripleDES {

    private byte[] bPassword;

    private string sPassword;
    public TripleDES( string Password = "password" ) {
        // On Class Begin
        this.Password = Password;
    }

    public string PasswordHash {
        get {
            System.Text.UTF8Encoding UTF8 = new System.Text.UTF8Encoding();
            return UTF8.GetString( bPassword );
        }
    }

    public string Password {
        get {
            System.Text.UTF8Encoding UTF8 = new System.Text.UTF8Encoding();
            return sPassword;
        }
        set {
            System.Text.UTF8Encoding UTF8 = new System.Text.UTF8Encoding();
            MD5CryptoServiceProvider HashProvider = new MD5CryptoServiceProvider();
            bPassword = HashProvider.ComputeHash( UTF8.GetBytes( value ) );
            sPassword = value;
        }
    }

    #region "Encrypt"

    // Encrypt using Password from Property Set (pre-hashed)
    public string Encrypt( string Message ) {
        byte[] Results = null;
        System.Text.UTF8Encoding UTF8 = new System.Text.UTF8Encoding();
        using ( MD5CryptoServiceProvider HashProvider = new MD5CryptoServiceProvider() ) {
            byte[] TDESKey = bPassword;
            using ( TripleDESCryptoServiceProvider TDESAlgorithm = new TripleDESCryptoServiceProvider { Key = TDESKey, Mode = CipherMode.ECB, Padding = PaddingMode.PKCS7 } ) {
                byte[] DataToEncrypt = UTF8.GetBytes( Message );
                try {
                    ICryptoTransform Encryptor = TDESAlgorithm.CreateEncryptor();
                    Results = Encryptor.TransformFinalBlock( DataToEncrypt, 0, DataToEncrypt.Length );
                } finally {
                    TDESAlgorithm.Clear();
                    HashProvider.Clear();
                }
            }
        }
        return Convert.ToBase64String( Results );
    }

    // Encrypt using Password as byte array
    private string Encrypt( string Message, byte[] Password ) {
        byte[] Results = null;
        System.Text.UTF8Encoding UTF8 = new System.Text.UTF8Encoding();
        using ( MD5CryptoServiceProvider HashProvider = new MD5CryptoServiceProvider() ) {
            byte[] TDESKey = HashProvider.ComputeHash( UTF8.GetBytes( UTF8.GetString( Password ) ) );
            using ( TripleDESCryptoServiceProvider TDESAlgorithm = new TripleDESCryptoServiceProvider { Key = TDESKey, Mode = CipherMode.ECB, Padding = PaddingMode.PKCS7 } ) {
                byte[] DataToEncrypt = UTF8.GetBytes( Message );
                try {
                    ICryptoTransform Encryptor = TDESAlgorithm.CreateEncryptor();
                    Results = Encryptor.TransformFinalBlock( DataToEncrypt, 0, DataToEncrypt.Length );
                } finally {
                    TDESAlgorithm.Clear();
                    HashProvider.Clear();
                }
            }
        }
        return Convert.ToBase64String( Results );
    }

    // Encrypt using Password as string
    public string Encrypt( string Message, string Password ) {
        byte[] Results = null;
        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 Triple DES encoder we use below
        using ( MD5CryptoServiceProvider HashProvider = new MD5CryptoServiceProvider() ) {
            byte[] TDESKey = HashProvider.ComputeHash( UTF8.GetBytes( Password ) );

            // Step 2. Create a new TripleDESCryptoServiceProvider object

            // Step 3. Setup the encoder
            using ( TripleDESCryptoServiceProvider TDESAlgorithm = new TripleDESCryptoServiceProvider { Key = TDESKey, Mode = CipherMode.ECB, Padding = PaddingMode.PKCS7 } ) {
                // Step 4. Convert the input string to a byte[]

                byte[] DataToEncrypt = UTF8.GetBytes( Message );

                // Step 5. Attempt to encrypt the string
                try {
                    ICryptoTransform Encryptor = TDESAlgorithm.CreateEncryptor();
                    Results = Encryptor.TransformFinalBlock( DataToEncrypt, 0, DataToEncrypt.Length );
                } finally {
                    // Clear the Triple Des and Hashprovider services of any sensitive information
                    TDESAlgorithm.Clear();
                    HashProvider.Clear();
                }
            }
        }

        // Step 6. Return the encrypted string as a base64 encoded string
        return Convert.ToBase64String( Results );
    }
    #endregion

    #region "Decrypt"
    // Decrypt using Password from Property (pre-hashed)
    public string Decrypt( string Message ) {
        byte[] Results = null;
        System.Text.UTF8Encoding UTF8 = new System.Text.UTF8Encoding();
        using ( MD5CryptoServiceProvider HashProvider = new MD5CryptoServiceProvider() ) {
            byte[] TDESKey = this.bPassword;
            using ( TripleDESCryptoServiceProvider TDESAlgorithm = new TripleDESCryptoServiceProvider { Key = TDESKey, Mode = CipherMode.ECB, Padding = PaddingMode.PKCS7 } ) {
                byte[] DataToDecrypt = Convert.FromBase64String( Message );
                try {
                    ICryptoTransform Decryptor = TDESAlgorithm.CreateDecryptor();
                    Results = Decryptor.TransformFinalBlock( DataToDecrypt, 0, DataToDecrypt.Length );
                } finally {
                    TDESAlgorithm.Clear();
                    HashProvider.Clear();
                }
            }
        }
        return UTF8.GetString( Results );
    }

    // Decrypt using Password as Byte array
    public string Decrypt( string Message, byte[] Password ) {
        byte[] Results = null;
        System.Text.UTF8Encoding UTF8 = new System.Text.UTF8Encoding();
        using ( MD5CryptoServiceProvider HashProvider = new MD5CryptoServiceProvider() ) {
            byte[] TDESKey = HashProvider.ComputeHash( UTF8.GetBytes( UTF8.GetString( Password ) ) );
            using ( TripleDESCryptoServiceProvider TDESAlgorithm = new TripleDESCryptoServiceProvider { Key = TDESKey, Mode = CipherMode.ECB, Padding = PaddingMode.PKCS7 } ) {
                byte[] DataToDecrypt = Convert.FromBase64String( Message );
                try {
                    ICryptoTransform Decryptor = TDESAlgorithm.CreateDecryptor();
                    Results = Decryptor.TransformFinalBlock( DataToDecrypt, 0, DataToDecrypt.Length );
                } finally {
                    TDESAlgorithm.Clear();
                    HashProvider.Clear();
                }
            }
        }
        return UTF8.GetString( Results );
    }


    // Decrypt using Password as string
    public string Decrypt( string Message, string Password ) {
        byte[] Results = null;
        System.Text.UTF8Encoding UTF8 = new System.Text.UTF8Encoding();

        // Step 1. We hash the pass phrase using MD5
        // We use the MD5 hash generator as the result is a 128-bit byte array
        // which is a valid length for the Triple DES encoder we use below
        using ( MD5CryptoServiceProvider HashProvider = new MD5CryptoServiceProvider() ) {
            byte[] TDESKey = HashProvider.ComputeHash( UTF8.GetBytes( Password ) );

            // Step 2. Create a new TripleDESCryptoServiceProvider object
            // Step 3. Setup the decoder
            using ( TripleDESCryptoServiceProvider TDESAlgorithm = new TripleDESCryptoServiceProvider { Key = TDESKey, Mode = CipherMode.ECB, Padding = PaddingMode.PKCS7 } ) {

                // 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 Triple Des and Hash provider services of any sensitive information
                    TDESAlgorithm.Clear();
                    HashProvider.Clear();
                }
            }
        }

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

    #endregion
}
person Kraang Prime    schedule 12.07.2014
comment
Полезно и работает. Тем не менее, mcrypt будет удален из PHP в будущем (уже в следующей серии выпусков, т.е. 7.2), как вместо этого сделать расшифровку с использованием метода openssl_decrypt? - person W.M.; 22.12.2016
comment
@В.М. Учитывая, что 7.x медленно внедряется из-за количества приложений, которые он ломает, сообществу потребуется некоторое время, чтобы наверстать упущенное (cPanel, IonCube и т. д.). Я ищу более надежный метод шифрования данных при передаче, так как мне не нравится 3des (было хорошо много лет назад). Возможно, 3des лучше, чем отсутствие шифрования необработанных данных. Нужно иметь в виду обработку (клиент/сервер) и качество. Методы Openssl (в php) на данный момент немного медленнее. Проблема в том, что этот метод единственный (кажется), который работает на ios, droid, .net, php .. изначально (без стороннего дерьма) - person Kraang Prime; 22.12.2016
comment
contd -- ... которые понятны для каждой платформы. Можно зашифровать A в .net как B и расшифровать B в ios/droid/php, чтобы снова получить A. Кажется, что у большинства методов есть некоторые причуды при переводе при пересечении языковых границ (что, на мой взгляд, не должно иметь место, поскольку математика и протокол, установленные в качестве стандарта для этих шифров, должны были соблюдаться, и если это было на каждом, то они должны уметь переводить [расшифровывать] все, что шифруют другие) - person Kraang Prime; 22.12.2016
comment
Спасибо. Я изучаю это, так как я просто не хочу, чтобы мое приложение не работало из-за удаления mcrypt из PHP в будущем. Должен признать, этот вопрос шифрования/дешифрования на разных языках программирования кажется сложным. - person W.M.; 22.12.2016
comment
@В.М. - У меня есть метод, несколько работающий с использованием сертификатов для шифрования данных с сервера с использованием закрытого ключа и расшифровки на стороне клиента с использованием открытого ключа. в обзоре кода . См. корректировки в решении для повышения производительности. Надеюсь это поможет :) - person Kraang Prime; 06.01.2017
comment
@KraangPrime Я искал что-то подобное, так как я очень новичок, пока я тестировал ваш код (зашифрованный в VB.NET и расшифрованный в PHP), я получил два дополнительных пустых места в конце расшифрованной строки (pastebin.com/BEZRusfW) - person Hayat Hasan; 15.10.2017
comment
@Hayat - я обновил код PHP, чтобы учесть это. Не уверен, что вызывает это, но эти пробелы на самом деле были управляющим символом STX ( char # 2 ). В метод добавлена ​​обрезка, чтобы удалить их из результата расшифровки. - person Kraang Prime; 18.10.2017