node-rsa und phpseclib

  • Hey ihr,


    ich melde mich mit einem Problem, was es ganz schön in sich hat. Ich sitze hier seit 19:00 und finde meinen Fehler nicht :(


    Ich habe einen Server, der auf node.js-Basis läuft. Ich möchte von diesem per request eine Anfrage an eine Webseite senden, die Webseite soll antworten.
    Dabei wird ein temporärer RSA-Schlüssel generiert, der öffentliche Schlüssel davon wird an den Webserver gesendet. Um zu beweisen, dass der Server wirklich der Server ist, unterschreibt er den öffentlichen Schlüssel und ein paar andere Daten mit einem Master-Schlüssel, der Client hat den zu den Master-Schlüssel passenden öffentlichen Schlüssel.


    Geladen wird der Schüssel beim Start wie folgt:

    JavaScript
    console.log("[RSA] Found. Importing it...");
    			AuthHelper.key = new NodeRSA(fs.readFileSync("./setup/private.key"), "pkcs1", {encryptionScheme: "pkcs1", signingScheme: "pkcs1-md5"});
    			console.log("[RSA] Keys imported!");



    Der Code zum Generieren des temporären Schlüssels:



    Die Daten, die er an den Server senden, stimmen mit denen überein, die der Client generiert. Das ganze sieht beispielsweise so aus:

    Code
    data: eyJrZXkiOiItLS0tLUJFR0lOIFBVQkxJQyBLRVktLS0tLVxuTUlHZU1BMEdDU3FHU0liM0RRRUJBUVVBQTRHTUFEQ0JpQUtCZ0g3cHJCNzFYQmc0K1U5ckZCM2h1eStKcXZCblxuU3IrdUVWM3ZRYlRodXlzWWV1TGErQXlwSTd4MWdVVkFmdUN1VEUvb0pMSDhUTlZtNjlyS2NNcFFWaGRDdVpHS1xuZDFudTY4Ky9LWjFtd1ZSRURGU0QyNlVMSjRKLzBZS2Q4WnRPb2hBMDRlSG9QZEVmd1pObWZHeElpM2tteThnL1xuUjBoVDgrWEFISmo4eTZodkFnTUJBQUU9XG4tLS0tLUVORCBQVUJMSUMgS0VZLS0tLS0iLCJ1dWlkIjoiMTg4ZTg0YjItNTg2Yy00ZmZkLTgzNWMtN2IyNmViM2E0NTRkIiwiZGF0ZSI6MTQ1MjI4ODMwMH0=
    signature: NJMGwDjaX3saFNgzlFGSVOOiQ2hNn5iUnHmILULOvElgt7ZRTzysIcmz+GHdgdaYFv4qsWKzpR+kfaDuu9gF6sMl3gSmStP9mZTz4l9ZtbJaWaYbN1m9PXBAdxfDES9Cu07o1UZ/H5W+hLrF5rpcq5xRuBvG/WLTGWQctSZvOrWhNRXl1jidoMrR7TsapqqqImXwRPBTYkrODcFoGv/5UAseanZoM3nad/CyVUSQIUepDMvr5ZHedL8FKddP9GecKrTFM49M6kXoAmfZCuVCVkXbD988Qdy/1KCjbgMeDCp8K//OWpGu0AGMcHiL6Zg1/mxXZz6ajeStyFy/J9pO4Q==


    In "data" steckt der temporäre öffentliche Schlüssel, die aktuelle Uhrzeit als *nix-Timestamp und eine UUID, die unwesentlich ist. Signature ist wohl selbsterklärend, das ist einfach nur die Signatur base64-kodiert.


    Clientseitig wird das ganze überprüft, doch bei der Überprüfung gibt phpseclib immer false zurück


    Die "typischen" Fehler bin ich schon durchgegangen

    • Die Daten werden erfolgreich und unverändert übertragen
    • Der öffentliche Schlüssel von dem Clienten passt zu dem Masterschlüssel des Servers
    • Der Server lädt den privaten Schlüssel erfolgreich
    • Der Client lädt den öffentlichen Schlüssel erfolgreich
    • Beide benutzen PKCS1 und md5. Einen Umstieg auf PKCS1 sha1 oder PKCS1 sha256 brachte keinen Erfolg.
    • Eine direkte Überprüfung der Signatur auf Serverseite ist natürlich erfolgreich

    Wenn ich das "@" in Zeile 9 weg nehme, also die entsprechende Fehlermeldung anzeigen lasse, gibt er nur einen Notice, dass die Signatur falsch ist.



    error_reporting ist auf E_ALL, er würde mir also eventuelle Fehler anzeigen. Selbes gilt für display_errors.


    Benutzt werden vom Server node.js, aktuellste Version, zusammen mit node-rsa.
    Der Client benutzt PHP mit der aktuellsten Version von phpseclib.
    Die Daten werden über HTTP übertragen, ich nutze dazu request in der aktuellsten Version und eine POST-Anfrage.
    Die Post-Anfrage wird wie folgt gesendet:

    JavaScript
    self.encryptionhelper = AuthHelper.createSignedRequest(self.get("uuid"));
    	request.post({
    		"url": "http://url.zur.php.seite/",
    		"form": {
    			"data": self.encryptionhelper.getData(),
    			"signature": self.encryptionhelper.getSignature()
    		}
    	}, function(error, response, body) {  });


    Als Antwort bekommt er "INVALID_POST_DATA" und der Client schreibt in die Log-Datei, dass die Signatur falsch ist.


    Kann mir einer einen Denkanstoß geben? :/



    EDIT: Hat sich erledigt. Sollte jemand ähnliche Probleme bekommen, die POST-Daten müssen erst zu UTF8 umgewandelt werden, also:

    PHP
    $_POST['data'] = utf8_encode($_POST['data']);
    	$_POST['signature'] = utf8_encode($_POST['signature']);
  • Auch wenn du das Problem gelöst hast, solltest du deine Indentation auf Leerzeichen statt Tabulator stellen und zum Zurückgeben der Daten eher Callbacks nutzen und nicht direkt eine neue Instanz erzeugen.

    Die Keys werden nur beim Starten erzeugt, daher macht es an sich während der Laufzeit keinen Unterschied, zudem habe ich bei node-rsa keinen Hinweis von der Existenz von Callbacks gefunden; neue Instanzen muss ich bei node-rsa erzeugen, weil pro Instanz nur ein Schlüsselpaar verwalten kann; und ich bin mehr Fan von Tabs als von Leerzeichen.
    Aber trotzdem Danke für die Hinweise :)