Zum Inhalt springen

POST-Request und seine X-API-SIGNATURE


tom_taler

Empfohlene Beiträge

Guten Tag geehrte Fachwissende,

ich beschäftige mich in geraumer Zeit mit der Programmierung mithilfe der API-v4 von bitcoin.de. Ich habe bis jetzt einige Hürden auf mich nehmen müssen die sich aber immer bezahlt gemacht haben. Alle GET-Requests funktionieren tadellos. Seit wenigen Tagen beschäftige ich mich auch mit dem POST-Request. Ich versuche einen createOrder abzusetzen aber immer wieder mit der Rückmeldung 'Invalid Signature'. Ich habe bereits mehrere Kombinationen versucht. Ich habe im Header neben den 3 X-API-xxx auch einen Content-Type und den Content-Length mitgesendet. Des Weiteren habe ich den post_encoded_query_string  als string und als hex übertragen. Die einzelnen Parameter waren voneinander natürlich durch '&' getrennt und die Parameter waren aufsteigend sortiert gewesen. der MD5 wird ebenfalls korrekt berechnet. Ich habe die Beispiel-Querys aus der Doku von bitcoin.de in meiner Programmierung MD5-Encodiert und das Resultat war das selbe wie in den Dokus. Es ist einfach demotivierend ständig den Error-Code 'Invalid signature' zu lesen.

Hat Jemand bitte für mich Tipps was noch im Raume stehen könnte?

 

Mit freundlichen Grüßen

Thomas

Link zu diesem Kommentar
Auf anderen Seiten teilen

Okay Leute,

hat sich erledigt. Habe durch herumprobieren es selber hinbekommen. Für diejenigen die in Node.js programmieren, hier die Hilfestellung mit Beispieldaten einer createOrder:

const query_str = require('querystring');

const post_parameter = {
	max_amount_currency_to_trade: 0.005,
	price: 45000.75,
	type: 'sell'
}

const query_string = query_str.stringify(post_parameter);

Die Konstante query_string kann nun md5-codiert werden um es dann weiter nach den Vorgaben in den API-Docs zu verarbeiten. Die Konstante query_string wird anschließend noch als content übertragen. Das drumherum müsst ihr euch schon selber zusammen basteln ;)

 

LG

Thomas

Link zu diesem Kommentar
Auf anderen Seiten teilen

  • 1 Monat später...

Hallo tom_taler,

ich war sehr froh, einen Beitrag zu finden, in dem genau mein Problem beschrieben wird. Auch bei mir funktionieren alle GET-Requests jedoch die POSTs schlagen mit "Invalid Signature" fehl. In meinen Tests sind die Ergebnisse jedoch exakt wie in den Beispieldaten der Doku.

Ich habe versucht deine Lösung für meine Kotlin-Anwendung zu übernehmen aber bin damit leider noch nicht erfolgreich gewesen.

Ich frage mich auch, wieso diese Änderung in deinem Programm überhaupt notwendig war, wenn auch deine Testergebnisse mit den Beispieldaten aus der Doku übereingestimmt haben. Waren nach der Änderung deine Testergebnisse anders als in der Doku beschrieben, was bedeuten würde, dass die Beispiele in der Doku falsch sind? Wenn nicht, verstehe ich nicht, was die Änderung bewirkt hat...

Leider habe ich es in Kotlin/Java nicht geschaft, meine POSTs zum Laufen zu bringen. Obwohl es eine andere Programmeirsprache ist, hättest du vielleicht eine Idee, wie man deine Lösung anwenden könnte?

Aktuell bekomme ich mit dem POST-Beispiel aus der Doku folgende Ergebnisse:

apiSecret = MY_API_SECRET
apiKey = MY_API_KEY
method = POST
postParams = {type=buy, max_amount=5.3, price=255.5}
uri = https://api.bitcoin.de/v4/btceur/orders
nonce = 1234567

query_string = max_amount=5.3&price=255.5&type=buy
md5_hashed_url_encoded_query_string = 5f4aece1d75c7adfc5ef346216e9bb11
hmac_data = POST#https://api.bitcoin.de/v4/btceur/orders?max_amount=5.3&price=255.5&type=buy#MY_API_KEY#1234567#5f4aece1d75c7adfc5ef346216e9bb11
hmac = deb87f84bd26baa89172c60b0a7a4f8fdf8ed4677cb06a5e70267f1dfa51b806

Wahrscheinlich muss ich auch die Codierung des query_string vornehmen. Ich verstehe aber nicht ganz, welches Ergebnis sich dadurch wie ändern muss.

 

Es würde mich sehr freuen, wenn mir bei diesem Problem nochmal behilflich sein könntest! Vielen Dank!!

Link zu diesem Kommentar
Auf anderen Seiten teilen

In einem weiteren Beitrag habe ich gelesen, dass bei einem Post zusätzlich die Parameter im Body mitgegeben werden müssen. Dies habe ich auch probiert und dabei die Query-Prameter bei der Generierung der URL weggelassen. Leider führt auch dies zu einer "Invalid Signature".

Link zu diesem Kommentar
Auf anderen Seiten teilen

In einem weiteren Beitrag habe ich gelesen, dass bei einem Post zusätzlich die Parameter als Body übergeben werden müssen. Dies habe ich ausprobiert und dabei bei der URL-Generierung die Query-Parameter weggelassen. Leider führt auch dies zu "Invalid Signature".

Link zu diesem Kommentar
Auf anderen Seiten teilen

Zur Vollständigkeit ist hir noch mein Kotlin Code. Bei der Generierung der URI (buildUri) habe ich wie gesagt alternativ die Query-Parameter weggelassen.

import org.apache.commons.codec.binary.Hex
import java.math.BigInteger
import java.security.MessageDigest
import javax.crypto.Mac
import javax.crypto.spec.SecretKeySpec

class BitcoinDeRequestEncryption {
    internal fun convertPostParamsToQueryString(params: Map<String, String>) =
        params.toSortedMap().map { it.key + "=" + it.value }.joinToString("&")

    internal fun buildUri(params: Map<String, String>, requestType: String, uri: String): String {
        val querySeperator = if (params.isNotEmpty()) {
            "?"
        } else {
            ""
        }
        return "$uri$requestType$querySeperator${convertPostParamsToQueryString(params)}"
    }

    internal fun buildMd5HashForPostParams(postParams: Map<String, String>): String {
        val md = MessageDigest.getInstance("MD5")
        return BigInteger(1, md.digest(((convertPostParamsToQueryString(postParams))).toByteArray())).toString(16).padStart(32, '0')
    }

    internal fun buildHmacData(method: String,
                               getParams: Map<String, String>,
                               postParams: Map<String, String>,
                               requestType: String,
                               apiKey: String,
                               nonce: String,
                               uri: String) =
        "$method#${
            buildUri(if (getParams.isEmpty()) {
                postParams
            } else {
                getParams
            }, requestType, uri)
        }#${apiKey}#${nonce}#${buildMd5HashForPostParams(postParams)}"

    fun createSignature(apiSecret: String,
                        method: String,
                        getParams: Map<String, String>,
                        postParams: Map<String, String>,
                        requestType: String,
                        apiKey: String,
                        nonce: String,
                        uri: String): String {
        when (method) {
            "POST" -> {
                assert(postParams.isNotEmpty())
                assert(getParams.isEmpty())
            }
            "GET"  -> {
                assert(postParams.isEmpty())
            }
        }
        val hmacData = buildHmacData(method, getParams, postParams, requestType, apiKey, nonce, uri)
        val sha256Hmac = Mac.getInstance("HmacSHA256")
        val secretKey = SecretKeySpec(apiSecret.toByteArray(), "HmacSHA256")
        sha256Hmac.init(secretKey)
        return Hex.encodeHexString(sha256Hmac.doFinal(hmacData.toByteArray()))
    }
}

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ich konnte mein Problem lösen. Es war ein Fehler in der Übergabe des Bodys.

Die Signatur funktioniert für POST, wenn man im oben angegeben Coding in der Methode buildUri folgendes ändert:

return "$uri$requestType

Allerding benötigt man die Query-Parameter für GET.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Erstelle ein Benutzerkonto oder melde Dich an, um zu kommentieren

Du musst ein Benutzerkonto haben, um einen Kommentar verfassen zu können

Benutzerkonto erstellen

Neues Benutzerkonto für unsere Community erstellen. Es ist einfach!

Neues Benutzerkonto erstellen

Anmelden

Du hast bereits ein Benutzerkonto? Melde Dich hier an.

Jetzt anmelden
×
×
  • Neu erstellen...

Wichtige Information

Wir haben Cookies auf Deinem Gerät platziert. Das hilft uns diese Webseite zu verbessern. Du kannst die Cookie-Einstellungen anpassen, andernfalls gehen wir davon aus, dass Du damit einverstanden bist, weiterzumachen.