2011-01-04 5 views
0

Ich versuche, mit einem C# -Client in https://www.interactivebrokers.com/sso/Login einzuloggen. Es ist ein Schritt, der einen SHA1-Hash aus dem Benutzernamen & Passwort (https://www.interactivebrokers.com/sso/Templates/javascript/myxyz.js, Linie 203) beinhaltet die Schaffung:SHA1: Übersetzen von JavaScript-Implementierung in C#

innerHash = CalcSHA1(username + ":" + password); 

Dies nennt (https://www.interactivebrokers.com/sso/Templates/javascript/sha1.js, Zeile 113)

calcSHA1Blks(str2blks_SHA1(str); 

und str2blks_SHA1() ist definiert (https://www.interactivebrokers.com/sso/Templates/javascript/sha1.js, Zeile 28) als

/* 
* Convert a string to a sequence of 16-word blocks, stored as an array. 
* Append padding bits and the length, as described in the SHA1 standard. 
*/ 
function str2blks_SHA1(str) 
{ 
    var nblk = ((str.length + 8) >> 6) + 1; 
    var blks = new Array(nblk * 16); 
    for(var i = 0; i < nblk * 16; i++) blks[i] = 0; 
    for(i = 0; i < str.length; i++) 
    blks[i >> 2] |= str.charCodeAt(i) << (24 - (i % 4) * 8); 
    blks[i >> 2] |= 0x80 << (24 - (i % 4) * 8); 
    blks[nblk * 16 - 1] = str.length * 8; 
    return blks; 
} 

ich bin nicht alles, was mit SHA1 Sachen vertraut, so kann ich nicht sagen, Wenn was in Str2blks_SHA1() ist, ist Standard Zeug, das automatisch in SHA1CryptoServiceProvider.ComputeHash() getan wird, oder wenn es etwas ist, was ich explizit tun muss. Ich habe versucht:

SHA1CryptoServiceProvider.ComputeHash(Encoding.UTF8.GetBytes(userName + ":" + password)) 

das gleiche Benutzername & Passwort in Javascript und in .net, und es scheint ein anderes Ergebnis zu erzeugen.

Dann habe ich versucht, diese Funktion str2blks_SHA1() zu C# portieren, aber ich verstehe nicht, wie man ein Array von Bytes (blks) (was SHA1CryptoServiceProvider.ComputeHash() erfordert), wie es scheint wie jedes Array-Element in blks könnte größer sein als ein Byte (nur bei str.length * 8)) ...

Also, gibt es bereits einige SHA1-Implementierung, die das Gleiche wie diese Javascript-Implementierung zur Verfügung stellt? Oder wenn ich das wirklich selbst implementieren muss, wie portiere ich str2blks_SHA1()?

Dank

+4

Wenn möglich, sollten Sie niemals eigene kryptografische Routinen implementieren. Es gibt so viele mögliche Seitenkanalangriffe auf sie, dass Sie fast sicher sind, kryptografische Sicherheit zu verlieren. – templatetypedef

Antwort

1

Diese JavaScript-Implementierung ähnelt dem standardmäßigen SHA-1-Auffüllalgorithmus von RFC 3174. Ich erhalte die gleichen Ergebnisse (ohne Berücksichtigung kleinere Formatierung Unterschiede) ab:

// JavaScript 
calcSHA1("[email protected]:p4ssw0rd"); 

wie ich aus:

// C# 
using (SHA1 hash = SHA1.Create()) 
    Console.WriteLine(BitConverter.ToString(
     hash.ComputeHash(Encoding.ASCII.GetBytes("[email protected]:p4ssw0rd")))); 

Welche Daten Sie liefern und was (verschiedene) Ergebnisse erhalten Sie?

(Beachten Sie, dass ich mich nicht wundern würde, wenn Ihr Benutzername oder Passwort Nicht-ASCII-Zeichen enthält, dass das JavaScript ein anderes Ergebnis als C# generiert, weil es anscheinend keine UTF-8-Konvertierung durchführt Insbesondere scheint es anzunehmen, dass jedes Zeichen nur aus einem Byte besteht.

+0

Sie haben Recht, es funktioniert. Ich habe versucht, die Ergebnisse mit einem BigInteger zu vergleichen; Das Byte-Array-Ergebnis von ComputeHash() muss umgekehrt werden, bevor es an den Konstruktor von BigInteger übergeben wird, und dann stimmen die beiden Ergebnisse überein. Hmm ... Habe ich Recht, dass es das Bytearray ist, das umgekehrt werden muss, und nicht die Zeichenkette von der Javascriptversion? (um sicherzustellen, dass alles noch für BigInteger.ModPow() und all diese Dinge funktioniert) – Jimmy

+0

Wenn Sie die SHA-1-Ausgabe als 160-Bit-Zahl behandeln möchten, möchten Sie sie normalerweise in Big-Endian-Reihenfolge interpretieren .Da der konstruierte BigInteger so dokumentiert ist, dass er ein Byte-Array in Little-Endian-Reihenfolge verwendet, ist es korrekt, dass das C# -Byte-Array umgekehrt werden muss, damit der BigInteger den gewünschten Wert hat. –

0

Haben Sie SHA1 des InputBlockSize oder OutputBlockSize versucht Einstellung?