2015-10-29 10 views
0

У меня есть приложение, которое обменивается данными между приложением поставщика в шифровании TripleDES с использованием метода CBC по согласованному ключу и IV. Мое приложение - это приложение VB.NET, а приложение поставщика - веб-страница PHP. Странная вещь заключается в том, что я не могу сравниться с выходом приложения поставщика.Использование обычного текста как ключа и IV в PHP mcrypt

Ключ и исходный вектор предоставляются нам обоими в виде открытого текста. Самое забавное, что в приложении поставщика они не хешируют или не конвертируют ключ и IV в 256-битный ключ и 128 бит IV. Они просто используют формат открытого текста в своем коде, используя плагин mcrypt.

$key = 'plaintextkey'; 
$iv = 'plaintextIV' 
$enc = mcrypt_encrypt(MCRYPT_3DES, $key, $string, MCRYPT_MODE_CBC, $iv) 

И это привело к смешной текст, такие как:

 
û!‰+«°z0"üÐÑn 

Мои вопросы:

  1. следует исходный текст можно использовать в качестве параметра, как делает PHP реализации/новообращенного это в 256-битный символ?
  2. Если используется метод CBC, разве это не зависит от ранее зашифрованного текста ?
  3. есть ли результат TripleDES в моем формате? Потому что по мере того, как я искал в Интернете и никогда не видел, чтобы приведенное шифрование в такой форме.
+0

Тогда я предполагаю, что они предприняли довольно упрощенный подход. Попробуйте указать их на страницу [PHP Manual page] (http://php.net/manual/en/function.mcrypt-encrypt.php), где он предлагает правильный способ делать что-то, все это в примере, а не в описание функций mcrypt – RiggsFolly

+0

@RiggsFolly Итак, использование ключей и IV было неправильным? Я вижу, что в предыдущей версии PHP они добавили \ 0 padding. Предыдущие ключи и IV были дополнены байтами «\ 0» до следующего допустимого размера., Поэтому, если бы они использовали последний PHP, он бы вернул false? –

ответ

2

должен быть исходный текст используется в качестве параметра, как же PHP реализовать/преобразовать его в 256 битовый символ с?

Тройной DES и применение DES три раза с тремя (разными) DES-ключами. Один ключ DES имеет длину 56 бит и 64 бит с контролем четности. Итак, ключ 3DES должен состоять из трех разных DES ключей, которые должны привести к одному 192-битовому ключу.

Ключи должны иметь высокую энтропию, так что необходимо было бы сколотить значительную часть пространства клавиш. Если ключ является паролем, то это значительно проще, потому что пароли имеют встроенный формат и ограниченный набор символов. Вот почему ключ должен быть получен из паролей. Обычно это делается с помощью PBKDF2, bcrypt или scrypt (со случайно генерируемой солью и множеством итераций в тысячах или миллионах/с высоким коэффициентом стоимости).

Теперь mcrypt принял некоторые спорные решения. Например, он с радостью принял (в ранних версиях PHP) недопустимые ключи и IV, заполнив их 0x00 байт до следующего допустимого размера или обрезая их до следующего допустимого размера. Вот почему использование «plaintextkey» - не очень хорошая идея. Это приведет к 0x00 байт для некоторых байтов второго ключа и полных 0x00 байт для третьего ключа.

mcrypt является отказом и больше не должен использоваться. Вы можете использовать расширение OpenSSL в PHP или одну из многих хороших библиотек шифрования, таких как libsodium или defuse/php-encryption.

Если используется метод CBC, разве это не зависит от ранее зашифрованного текста?

Вы можете использовать последний блок зашифрованного текста как IV для следующего шифрования, но это только усложняет код шифрования. Вы действительно должны использовать случайный IV каждый раз и просто добавлять его к зашифрованному тексту. Он не должен быть секретным, а скорее непредсказуемым. Вы можете хранить его вместе с случайной солью раньше. Смотри также: Why use an Initialization Vector (IV)?

есть ли результат TripleDES в моем формате? Потому что, когда я искал в Интернете и никогда не видел, чтобы приведенное шифрование было в такой форме.

Современные шифры (с шифрованием формата сохраняющими является заметным исключением) производят шифртексты, которые должны быть indistinguishable from random "noise". Таким образом, вы можете получать непечатаемые символы, такие как \ x01 и многие другие, как часть зашифрованного текста. Вы хотите напечатать зашифрованный текст, тогда вам нужно закодировать в каком-то печатном формате в примере с использованием Hex или Base 64.

+0

Ничего себе, это очень помогает. Короче говоря, чтобы соответствовать результату поставщика, я должен добавить дополнение к нулям для моего ключа и вектора, не так ли? Я хотел сказать им, что mcrypt устарел, но я не говорю об этом. :( –

+1

Да, заполняя ключ до 24 байтов с помощью 0x00 байт и обрезая IV на первых 8 байтах, нужно делать все правильно. Имейте в виду, что mcrypt использует нулевое дополнение для открытого текста. Он автоматически добавит открытый текст к следующему краю от размера блока (8 байтов для 3DES). Хотя он не добавляет полный блок заполнения, если открытый текст уже кратен размеру блока. Это, вероятно, другое поведение, чем 'System.Security.Cryptography.PaddingMode .Zeros', который всегда добавляет хотя бы один байт для заполнения. Вы должны попробовать, потому что, как он работает на PHP, он все равно может быть совместим. –

+0

Чувак, я, наконец, сделал это. Большое спасибо за ваши ответы, и я обновите мой вопрос и моим решением. * Удаленный кулак на расстоянии * –

0

Спасибо за ответ Artjom за то, что вам нужно добавить несколько 0, пока ключ и IV не достигнут длины 24 и 8 соответственно. Вот коды VB.NET, если кому-то это нужно.

Dim byteKey As Byte() = System.Text.Encoding.UTF8.GetBytes("myplaintextkey") 
Dim byteVector As Byte() = System.Text.Encoding.UTF8.GetBytes("myplaintextiv") 

Dim base64Key As String = Convert.ToBase64String(byteKey) 
Dim base64Vector As String = Convert.ToBase64String(byteVector) 

Dim key As Byte() = Convert.FromBase64String(base64Key) 
Dim iv As Byte() = Convert.FromBase64String(base64Vector) 

Dim encryptor As SymmetricEncryptor = New SymmetricEncryptor() 'Note, this an internal library 

Try 
    encryptor.Provider = New System.Security.Cryptography.TripleDESCryptoServiceProvider 

    encryptor.Encoder = System.Text.Encoding.UTF8 
    encryptor.Provider.Mode = CipherMode.CBC 
    encryptor.Provider.Padding = PaddingMode.Zeros 

    'Add missing zeros to key and IV 
    If key.Length < 24 Then 
     Dim i As Integer = key.Length 
     ReDim Preserve key(23) 
     While i < 24 
      key(i) = 0 
      i += 1 
     End While 
    ElseIf key.Length > 24 Then 
     ReDim Preserve key(23) 
    End If 

    If iv.Length < 8 Then 
     Dim i As Integer = iv.Length 
     ReDim Preserve iv(8) 
     While i < 8 
      iv(i) = 0 
      i += 1 
     End While 
    ElseIf iv.Length > 8 Then 
     ReDim Preserve iv(8) 
    End If 
    encryptor.IV = iv 
    encryptor.Key = key 

    Dim output As String = encryptor.Encrypt(output) 

    Console.Write(output) 
Catch ex As Exception 
    Console.Write(ex.Message) 
End Try 

Я надеюсь, что это поможет кому-то и еще раз, спасибо Artjom!