Hashing von Secret + Payload für SSO

Ich versuche, den offiziellen SSO-Leitfaden zu befolgen. Ich verwende Golang auf meinem Server und versuche, den HMAC-SHA256-Hash aus payload + secret mit sig abzugleichen, erhalte aber unterschiedliche Werte. Wie führen Sie die Hash-Berechnung durch? Zerlegen Sie das Payload in den rohen, nicht signierten Inhalt und hashen es erneut?

Wie sieht dein Code aus?

Hast du die Nutzlast Base64-kodiert?

Und hast du die Parameterreihenfolge richtig gewählt? Unterschiedliche Sprachen und Bibliotheken haben unterschiedliche Parameterreihenfolgen: (Schlüssel, Nachricht) oder (Nachricht, Schlüssel). Das ist es, was mich jedes Mal in die Irre führt.

1 „Gefällt mir“

Nach dem Parsen des payload scheint er standardmäßig in Base64 kodiert zu sein, aber der 256SHA-Hash des Base64-kodierten Payloads ist nicht korrekt. Ich verwende das Beispiel-Geheimnis und die URL aus dem ursprünglichen Beitrag.

Der folgende Code liefert mir folgende Ausgabe:

 payloadURL = bm9uY2U9Y2I2ODI1MWVlZmI1MjExZTU4YzAwZmYxMzk1ZjBjMGI=

sig = 2828aa29899722b35a2f191d34ef9b3ce695e0e6eeec47deb46d588d70c7cb56
payloadRaw = nonce=cb68251eefb5211e58c00ff1395f0c0b
payload256 = KCiqKYmXIrNaLxkdNO+bPOaV4Obu7EfetG1YjXDHy1Y=

Mein Code:

testURL := "http://www.example.com/discourse/sso?sso=bm9uY2U9Y2I2ODI1MWVlZmI1MjExZTU4YzAwZmYxMzk1ZjBjMGI%3D%0A&sig=2828aa29899722b35a2f191d34ef9b3ce695e0e6eeec47deb46d588d70c7cb56"	
	ssoSecret := "d836444a9e4084d5b224a60c208dce14"

	// Hole den Payload und die Signatur aus der URL-Abfrage
	u, err := url.Parse(testURL)
	if err != nil {
		log.Fatal(err)
	}

	q := u.Query()
	payloadURL := strings.Trim(fmt.Sprint(q["sso"]), "=[]")
	sig := strings.Trim(fmt.Sprint(q["sig"]), "[]")
	
	fmt.Printf("payloadURL = %s\n", payloadURL)
	fmt.Printf("sig = %s\n", sig)

	// Hole den Roh-Payload aus der Base64-Version
	payloadRaw, err := base64.StdEncoding.DecodeString(payloadURL)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("payloadRaw = %s\n", payloadRaw)
	
	key := []byte(ssoSecret)
	message := []byte(payloadURL)
	hash := hmac.New(sha256.New, key)
	hash.Write(message)
	payload256 := base64.StdEncoding.EncodeToString(hash.Sum(nil))
	if err != nil {
		log.Fatal(err)
	}
	
	fmt.Printf("payload256 = %s\n", payload256)

	// Die Signatur ist hex-kodiert, also kodiere den gehashten Payload ebenfalls hex, um ihn vergleichen zu können.
	//hashAsString := hex.EncodeToString(hash.Sum(nil))

	// Vergleiche den hex-kodierten Hash des Payloads mit der hex-kodierten Signatur
	if strings.Compare(payload256, sig) != 0 {
		log.Fatal(err)
	}

Update: Ich habe das Problem behoben, indem ich den resultierenden HMAC-SHA256-Hash in Hex kodiert habe (die Signatur ist ebenfalls hex-kodiert). Siehe auch diesen Beitrag, der besagt, dass die Beispiele im SSO-Leitfaden falsch sind. Daher habe ich diesen Code geändert:

key := []byte(ssoSecret)
message := []byte(payloadURL)
hash := hmac.New(sha256.New, key)
hash.Write(message)
payload256 := hex.EncodeToString(hash.Sum(nil))
if err != nil {
	log.Fatal(err)
}

Woher kommt payload256?

Entschuldigung, ich habe den OP mit saubererem Code aktualisiert.

Was macht dieses %0A dort direkt vor &sig? Das ist ein URL-kodierter Zeilenumbruch… deshalb gibt es eine leere Zeile in deiner Debug-Ausgabe, nachdem du die payloadURL ausgegeben hast – sie ist immer noch am Ende angehängt.

1 „Gefällt mir“

Gut erkannt! Ich habe das hier behoben, indem ich das Zeilenumbruchzeichen zu den .Trim()-Parametern hinzugefügt habe:

payloadURL := strings.Trim(fmt.Sprint(q["sso"]), "[]\n")

Meine Ausgabe lautet jetzt:

payloadURL = bm9uY2U9Y2I2ODI1MWVlZmI1MjExZTU4YzAwZmYxMzk1ZjBjMGI=
sig = 2828aa29899722b35a2f191d34ef9b3ce695e0e6eeec47deb46d588d70c7cb56
payloadRaw = nonce=cb68251eefb5211e58c00ff1395f0c0b
payload256 = HOFJT5RIS29qCSvpsVzMHNr7H4Rgo4OPuw4Ig8Q5BHE=

Du solltest prüfen, woher das Zeilenumbruchzeichen tatsächlich stammt, und verhindern, dass es hinzugefügt wird.

Außerdem sollte die Nutzlast mehr Name-Wert-Paare enthalten als nur die Nonce?

1 „Gefällt mir“

Das sind nur die Beispielangaben aus der Discourse SSO-Anleitung, daher kann ich nicht sagen, woher die neue Zeile kommt. Offenbar ist die Anleitung falsch (laut diesem Beitrag), und es scheint ein Kopier-/Einfügefehler im Beispiel vorzuliegen.

Vielleicht wurde ein wenig zu viel zwischen verschiedenen Versionen kopiert und eingefügt.

Aber wenn ich mir deinen Beitrag direkt über diesem ansehe, ist deine payloadURL nicht URL-kodiert und payload256 ist nicht hex-kodiert, sondern base64-kodiert.

Vielleicht kannst du deinen aktuellen Code und deine aktuelle Ausgabe erneut posten.

1 „Gefällt mir“