PostgreSQL - преобразование двоичных данных в Varchar - PullRequest
0 голосов
/ 05 сентября 2018

Мы работаем над миграцией баз данных из MSSQL в базу данных PostgreSQL. В ходе этого процесса мы столкнулись с ситуацией, когда в таблице содержится поле пароля типа NVARCHAR, и значение этого поля было преобразовано из типа VARBINARY и сохранено как тип NVARCHAR.

Например: если я выполню

SELECT HASHBYTES('SHA1','Password')` 

, затем возвращается 0x8BE3C943B1609FFFBFC51AAD666D0A04ADF83C9D и, в свою очередь, если это значение преобразуется в NVARCHAR, то возвращается текст в формате "䏉悱゚얿괚浦Њ鴼"

Поскольку мы знаем, что PostgreSQL не поддерживает VARBINARY, мы использовали вместо него BYTEA и возвращаем двоичные данные. Но когда мы пытаемся преобразовать эти двоичные данные в тип VARCHAR, возвращается шестнадцатеричный формат

Например: если тот же оператор выполняется в PostgreSQL

SELECT ENCODE(DIGEST('Password','SHA1'),'hex')

тогда возвращается 8be3c943b1609fffbfc51aad666d0a04adf83c9d.

Когда мы пытаемся преобразовать этот закодированный текст в тип VARCHAR, он возвращает тот же результат, что и 8be3c943b1609fffbfc51aad666d0a04adf83c9d

Можно ли получить тот же результат, который мы получили с сервера MSSQL? Поскольку они связаны с полями пароля, мы не намерены изменять значения. Подскажите пожалуйста что нужно сделать

Ответы [ 2 ]

0 голосов
/ 05 сентября 2018

затем возвращается 0x8BE3C943B1609FFFBFC51AAD666D0A04ADF83C9D и по очереди если это значение конвертируется в NVARCHAR, то возвращается текст в формате " 䏉 悱 ゚ 얿괚 浦 Њ 鴼"

Исходя из этого, MSSQL интерпретирует эти байты как текст, закодированный в UTF-16LE.

С PostgreSQL и использованием только встроенных функций вы не можете получить этот результат, потому что PostgreSQL вообще не использует или не поддерживает UTF-16, ни для чего. Он также не поддерживает нулевые байты в строках, и в UTF-16 есть нулевые байты.

Этот Q / A: UTF16 в шестнадцатеричном виде предлагает несколько решений.

Однако изменение вашей бизнес-логики, чтобы она не зависела от UTF-16, было бы вашим лучшим долгосрочным вариантом. Например, шестнадцатеричное представление проще и гораздо более переносимо.

0 голосов
/ 05 сентября 2018

Похоже, вы берете байтовый массив, содержащий криптографический хеш, и хотите преобразовать его в строку для сравнения строк. Это странный способ сравнения хешей, но он может оказаться возможным в зависимости от того, какую кодировку вы используете на стороне MSSQL.

Если у вас есть байтовый массив, который может быть преобразован в строку в используемой вами кодировке (например, не содержит недопустимых кодовых точек или последовательностей для этой кодировки), вы можете преобразовать байтовый массив. для строки следующим образом:

SELECT CONVERT_FROM(DIGEST('Password','SHA1'), 'latin1') AS hash_string;
         hash_string
-----------------------------
 \u008BãÉC±`\u009Fÿ¿Å\x1A­fm+
 \x04­ø<\u009D

Если вы используете Unicode, этот подход не будет работать вообще, поскольку случайные двоичные массивы не могут быть преобразованы в Unicode, потому что есть определенные последовательности, которые всегда недопустимы. Вы получите сообщение об ошибке:

# SELECT CONVERT_FROM(DIGEST('Password','SHA1'), 'utf-8');
ERROR:  invalid byte sequence for encoding "UTF8": 0x8b

Вот список допустимых кодировок строк в PostgreSQL . Узнайте, какую кодировку вы используете на стороне MSSQL, и попытайтесь сопоставить ее с PostgreSQL. Если вы можете, я бы порекомендовал изменить вашу бизнес-логику, чтобы сравнивать байтовые массивы напрямую, поскольку это будет менее подвержено ошибкам и должно быть значительно быстрее.

...