2016-04-29 20 views
1

Ich arbeite an einem ETL-Prozess (kein Primärschlüssel -> keine Transaktionsreplikation) zwischen Oracle und SQL Server und verwenden einen MD5-Hash, um Unterschiede zwischen den Quell- und Zieldatenbanken zu erkennen.SQL Server HASHBYTES und Extended Ascii

Dies funktioniert für die Datensätze, in denen die Daten in die ersten 127 ASCII-Zeichen fallen. Aber wenn es 'extended ASCII'-Zeichen wie , ° oder © gibt, funkt die Funktion HASHBYTES von SQL Server diese Zeichen in einer nicht standardmäßigen Weise (d. H. Anders als die DBMS_CRYPTO.Hash von Oracle, die .Net-Kryptographiebibliothek usw.).

Also, wenn ich laufen diese in Oracle:

select rawtohex(
DBMS_CRYPTO.Hash (
    UTL_I18N.STRING_TO_RAW ('°', 'AL32UTF8'), 
    2) 
) from dual; 

ich: 4723EB5AA8B0CD28C7E09433839B8FAE.

Und wenn ich dies in SQL Server ausgeführt wird:

SELECT HASHBYTES('md5', '°'); 

ich: EC655B6DA8B9264A7C7C5E1A70642FA7

Und wenn ich diesen C# Code ausführen:

string password = "°"; 

// byte array representation of that string 
byte[] encodedPassword = new UTF8Encoding().GetBytes(password); 

// need MD5 to calculate the hash 
byte[] hash = ((HashAlgorithm) CryptoConfig.CreateFromName("MD5")).ComputeHash(encodedPassword); 

// string representation (similar to UNIX format) 
string encoded = BitConverter.ToString(hash) 
    // without dashes 
    .Replace("-", string.Empty) 
    // make lowercase 
    .ToLower(); 

ich 4723EB5AA8B0CD28C7E09433839B8FAE also das gleiche wie in Oracle und jedem Online-Tool, das ich verwendet habe.

Gibt es eine SQL-basierte Lösung für dieses Problem oder müsste ich eine CLR gespeicherte Prozedur erstellen und die Daten dort hash?


* Mir ist klar, dass der Begriff etwas umstritten ist

+1

MD5 ist MD5, wenn die Ausgabe unterscheidet, unterscheidet sich der Eingang - wenn die Eingaben sehen gleich aus, dann ist es ein Codierungsproblem bezüglich der binären Interpretation der Eingabe. Können Sie die Eingabe und Ausgabe eines solchen HASHBYTES() - Aufrufs zusammen mit dem erwarteten Ergebnis anzeigen? –

+1

SQL Server gibt Ihnen den Hash der Zeichenfolge zurück, interpretiert als ISO-8859-1, 'HASHBYTES ('md5', N '°');' würde Ihnen das UTF16-Ergebnis geben, wenn Sie das in Oracle verwenden können? –

+1

Mögliches Duplikat von [TSQL md5 hash anders als C# .NET md5] (http://stackoverflow.com/questions/27908449/tsql-md5-hash-different-to-c-sharp-net-md5) –

Antwort

0

ich beschlossen haben, um SQL Server Behandlung von erweiterten ASCII durch eine CLR-gespeicherte Prozedur implementieren, die das .Net Cryptographic Library verwenden:

using System; 
using System.Security.Cryptography; 
using System.Text; 
using Microsoft.SqlServer.Server; 

public class Functions 
{ 
    [SqlFunction] 
    public static string GetMD5Hash (string input) 
    { 
    var encodedPassword = new UTF8Encoding().GetBytes(input); 

    var hash = ((HashAlgorithm)CryptoConfig.CreateFromName("MD5")).ComputeHash(encodedPassword); 

    return BitConverter.ToString(hash).Replace("-", string.Empty); 
    } 
} 
2

Es gibt keine UTF-8-Unterstützung in MS SQL Server ab sofort. Aus diesem Grund unterscheiden sich Ihre Hashwerte immer, bis Sie die Quellzeichenfolge auf den häufigsten Nenner, in diesem Fall UTF-16 (wahrscheinlich), umstellen.