У меня есть приложение, которое обменивается данными между приложением поставщика в шифровании TripleDES с использованием метода CBC по согласованному ключу и IV. Мое приложение представляет собой приложение VB.NET, а приложение производителя представляет собой веб-страницу PHP. Странно то, что я не могу соответствовать выводу приложения вендора.
Ключ и начальный вектор даны нам обоим в виде открытого текста. Самое смешное, что в приложении производителя они не хэшируют и не преобразуют ключ и IV в 256-битный ключ и 128-битный IV. Они просто используют формат открытого текста в своем коде, используя Mcrypt плагин в PHP.
$key = 'plaintextkey';
$iv = 'plaintextIV'
$enc = mcrypt_encrypt(MCRYPT_3DES, $key, $string, MCRYPT_MODE_CBC, $iv)
И это привело к забавному тексту, такому как:
û! ‰ + «° z0" üÐÑn
Мои вопросы:
должен ли открытый текст использоваться в качестве параметра, как PHP реализует / преобразовывает его в 256-битный символ?
Тройной DES и применение DES трижды с тремя (разными) ключами DES. Один ключ DES имеет длину 56 бит и 64 бит с четностью. Итак, ключ 3DES должен состоять из трех разные Ключи DES, которые должны давать один 192-битный ключ.
Предполагается, что ключи имеют высокую энтропию, так что потребуется перебор значительного количества пространства ключей. Если ключ является паролем, то это значительно проще, потому что пароли имеют собственный формат и ограниченный набор символов. Вот почему ключ должен быть получен из паролей. Обычно это делается с помощью PBKDF2, bcrypt или scrypt (со случайно сгенерированной солью и большим количеством итераций в тысячах или миллионах / с высокой стоимостью).
Теперь Mcrypt принял несколько сомнительных решений. Например, он с радостью принял (в более ранних версиях PHP) недопустимые ключи и IV, дополнив их 0x00 байтами до следующего допустимого размера или обрезав их до следующего допустимого размера. Вот почему использование «открытого текста» не очень хорошая идея. Это приведет к 0x00 байтов для некоторых байтов второго ключа и полных 0x00 байтов для третьего ключа.
mcrypt не используется и больше не должен использоваться. Вы можете использовать расширение OpenSSL в PHP или одну из многих хороших библиотек шифрования, таких как libsodium или defuse / php-encryption.
если используется метод CBC, не должен ли он зависеть от ранее зашифрованного текста?
Вы можете использовать последний блок зашифрованного текста в качестве IV для следующего шифрования, но это только усложняет код шифрования. Вы действительно должны использовать случайный IV каждый раз и просто добавлять его к зашифрованному тексту. Это не должно быть секретом, а скорее непредсказуемым. Вы можете хранить его вместе со случайной солью из ранее. Смотрите также: Зачем использовать вектор инициализации (IV)?
есть ли результат TripleDES в моем данном формате? Потому что, когда я искал в интернете и никогда не видел, в результате шифрование в такой форме.
Современные шифры (при этом сохраняющее формат шифрование является заметным исключением) создают шифротексты, которые должны быть неотличимый от случайного «шума». Таким образом, вы можете получить непечатаемые символы, такие как \ x01 и многие другие, как часть зашифрованного текста. Вы хотите напечатать зашифрованный текст, затем вам нужно кодировать в какой-нибудь печатный формат, например, используя Hex или Base 64.
Спасибо ответу Artjom за упоминание о том, что вам нужно добавить несколько нулей, пока ключ и 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
Надеюсь, это кому-нибудь поможет и еще раз, спасибо Артём!