anipassion.com

[CC][API] Cryptographie Délocalisée

Voir le sujet précédent Voir le sujet suivant Aller en bas

[CC][API] Cryptographie Délocalisée

Message par Thomasims le Mer 17 Aoû - 18:01

Bonjour, je vais vous présenter ce que je vais appeler mon API de Cryptographie délocalisée (notez le nom très original) :

Le principe est simple: minimiser les opérations du côté LUA pour:

  • Améliorer la vitesse des opérations. 
  • Réduire l'impact sur le serveur MC.
  • Utiliser les fonctions de Crypto optimisées d'un environnement moins restreint que celui de CC.

Pour atteindre ce but, j'ai choisi de coder une simple page PHP qui répond à des requêtes POST.
L'API fait simplement des requêtes à la page et le serveur web prend en charge tous les calculs 'lourds'.
Le code LUA prend en charge lui toutes les spécificités de l'appel à la page pour diminuer au maximum la complexité de l'API.

Sans plus attendre, voici le code CC:
Spoiler:

Pastebin: ZRpFhBbF
Code:
local host = "- EDIT: Je peux pas encore poster de liens ^^ (Il est dans le pastebin)-"

--TODO:
-- /

local function request(host, data)
 local postdata = ""
 for k,v in pairs(data) do
 postdata = postdata .. "&" .. textutils.urlEncode(k) .. "=" .. textutils.urlEncode(v)
 end
 postdata = postdata:sub(2)
 local ret = http.post(host, postdata)
 local data = ret.readAll()
 ret.close()
 return data
end

function generate()
 local data = request(host, {
 func = "generate"
 })
 return textutils.unserialise(data)
end

function encrypt(data, key)
 if not data then error("No data given") end
 if not key then error("No key given") end
 if not type(key)=="string" then error("Key must be a string") end
 if data=="" then return "" end
 local ret = request(host, {
 func = "encrypt",
 data = textutils.serialise(data),
 key = key
 })
 if ret=="" then error("Error during encryption") end
 return ret
end

function decrypt(crypted, key)
 if not crypted then error("No data given") end
 if not key then error("No key given") end
 if not type(key)=="string" then error("Key must be a string") end
 if not type(crypted)=="string" then error("Crypted data must be a string") end
 if crypted=="" then return "" end
 local ret = request(host, {
 func = "decrypt",
 data = crypted,
 key = key
 })
 if ret=="" then error("Error during decryption") end
 return textutils.unserialise(ret)
end

function sign(data, key)
 if not data then error("No data given") end
 if not key then error("No key given") end
 if not type(key)=="string" then error("Key must be a string") end
 local ret = request(host, {
 func = "sign",
 data = textutils.serialise(data),
 key = key
 })
 if ret=="ERROR" then error("Error during signature") end
 return ret
end

function verify(signed, original, key)
 if not data then error("No data given") end
 if not original then error("No test given") end
 if not key then error("No key given") end
 if not type(key)=="string" then error("Key must be a string") end
 if not type(signed)=="string" then error("Signature must be a string") end
 local ret request(host, {
 func = "verify",
 data = signed,
 original = textutils.serialise(original),
 key = key
 })
 if ret=="ERROR" then error("Error during verification") end
 return ret == "1"
end
Et la doc:
doc:

Fonction
Paramètres
valeur Retournée
generate
/-une table contenant les clés 'public' et 'private'
encrypt
(à utiliser avec decrypt)
-un valeur à encrypter (tout type)
-une clé publique (string)
-les données encryptées (string)
decrypt
(à utiliser avec encrypt)
-une valeur encryptée (string)
-la clé privée (string)
-la valeur décryptée (tout type)
sign
(à utiliser avec verify)
-une valeur pour créer la signature (tout type)
-une clé privée (string)
-Le hash de la valeur, encrypté avec la clé (string)
verify
(à utiliser avec sign)
-le hash encrypté de sign (string)
-la valeur originale (tout type)
-la clé publique (string)
-si la valeur correspond à la signature (booléen)
PS: désolé pour le formattage horrible
Comme vous pouvez le voir, la page PHP est hébergée sur mon VPS, ce qui peut poser problème (Je n'incite jamais les gens à me faire confiance dans ce genre de cas  Rolling Eyes )
Pour remédier à ça, je vous incite vivement à héberger vous même la page PHP (ça m'arrange, ça diminue le load sur mon VPS  Very Happy )
Attention, c'est pas joli:

Pastebin: 0jXBPteP
Code:
<?php
 if(!isset($_POST['func'])) {exit('{}');}
 $config = array(
 "digest_alg" => "sha512",
 "private_key_bits" => 1024,
 "private_key_type" => OPENSSL_KEYTYPE_RSA,
 );
 
 //Crédit à gutzmer[..] pour ces 2 fonctions (- Voir le pastebin -)
 function base64url_encode($data) {
 return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
 }
 function base64url_decode($data) {
 return base64_decode(str_pad(strtr($data, '-_', '+/'), strlen($data) % 4, '=', STR_PAD_RIGHT));
 }
 
 function encrypt($data, $keytext) {
 $key = openssl_get_publickey($keytext);
 if($key===false) {
 return '';
 }
 openssl_seal($data, $crypted, $keys, array($key));
 $encoded = base64url_encode(base64url_encode($crypted).':'.base64url_encode($keys[0]));
 openssl_free_key($key);
 return $encoded;
 }
 function decrypt($crypted, $keytext) {
 $key = openssl_get_privatekey($keytext);
 if($key===false) {
 return '';
 }
 $decoded = explode(':',base64url_decode($crypted));
 openssl_open(base64url_decode($decoded[0]), $data, base64url_decode($decoded[1]), $key);
 openssl_free_key($key);
 return $data;
 }
 function sign($data, $keytext) {
 $key = openssl_get_privatekey($keytext);
 if($key===false) {
 return '';
 }
 $datasig = base64url_encode(openssl_digest($data, "SHA256"));
 $ok = openssl_private_encrypt($datasig, $signed, $key);
 openssl_free_key($key);
 return $ok?base64url_encode($signed):'ERROR';
 }
 function verify($data, $signed, $keytext) {
 $key = openssl_get_publickey($keytext);
 if($key===false) {
 return '';
 }
 $datasig = base64url_encode(openssl_digest($data, "SHA256"));
 $ok = openssl_public_decrypt(base64url_decode($signed), $testsig, $key);
 openssl_free_key($key);
 return $ok?($datasig==$testsig?1:0):'ERROR';
 }
 switch($_POST['func']) {
 case 'encrypt':
 if(!isset($_POST['data']) || !isset($_POST['key'])) {exit('');}
 $key = base64url_decode($_POST['key']);
 echo encrypt($_POST['data'], $key);
 break;
 case 'decrypt':
 if(!isset($_POST['data']) || !isset($_POST['key'])) {exit('');}
 $key = base64url_decode($_POST['key']);
 echo decrypt($_POST['data'], $key);
 break;
 case 'generate':
 $keys = openssl_pkey_new($config);
 openssl_pkey_export($keys, $private);
 $public = openssl_pkey_get_details($keys)["key"];
 echo('{private="' . base64url_encode($private) . '",public="' . base64url_encode($public) . '"}');
 break;
 case 'sign':
 if(!isset($_POST['data']) || !isset($_POST['key'])) {exit('');}
 $key = base64url_decode($_POST['key']);
 echo sign($_POST['data'], $key);
 break;
 case 'verify':
 if(!isset($_POST['data']) || !isset($_POST['key']) || !isset($_POST['original'])) {exit('');}
 $key = base64url_decode($_POST['key']);
 echo verify($_POST['original'], $_POST['data'], $key);
 break;
 }
?>


Dernière édition par Thomasims le Mer 17 Aoû - 19:21, édité 1 fois
avatar
Thomasims

Messages : 2
Date d'inscription : 11/08/2016
Age : 20
Localisation : Belgique

Revenir en haut Aller en bas

Re: [CC][API] Cryptographie Délocalisée

Message par skypop le Mer 17 Aoû - 19:15

Tu peux faire un meilleur usage de LUA dans le contrôle et la gestion des erreurs.
Par exemple, pour une série comme ça :
Code:
 if not data then error("No data given") end
 if not original then error("No test given") end
 if not key then error("No key given") end
 if not type(key)=="string" then error("Key must be a string") end
 if not type(signed)=="string" then error("Signature must be a string") end

Tu devrais pouvoir utiliser la fonction assert()
Code:
assert(data, "No data given")
assert(original, "No test given")
assert(key, "No key given")
assert(type(key)=="string", "Key must be a string")
assert(type(signed)=="string", "Signature must be a string")
Si le premier paramètre est false ou nil, une erreur est émise avec le message indiqué en second paramètre. Enfin le message est optionnel.

ref: https://www.lua.org/pil/8.3.html

Enfin, la fonction error() peut prendre un second paramètre qui par défaut est à 1 et correspond au level : à quelle ligne de quel programme l'erreur doit être signalée.
Tel quel, si un utilisateur de ton api commet une erreur, en retour il lui sera signalé que l'erreur proviens de l'api, et non du programme où l'utilisateur a commis l'erreur.
Pour que le signalement de l'erreur soit plus cohérent, il suffirait d'indiquer le level 2 :
Exemple :
Code:
function encrypt(data, key)
 if not data then error("No data given",2) end
 if not key then error("No key given",2) end
-- ...
Ainsi, si l'utilisateur oublie un des deux arguments c'est la ligne de son programme qui lui sera signalée, et non celle de l'API.

On peut aussi faire en sorte qu'il ne soit pas fait mention de la ligne ou du fichier, en indiquant le level 0 (zéro)
Jusque là je croyais que c'était -1, qui fonctionne aussi enfin maintenant je le sais Very Happy

réf: https://www.lua.org/pil/8.5.html

Enfin je ne crois pas que assert() gère le level. Mais l'une sinon l'autre de ces deux astuces devrait bien te servir Wink
avatar
skypop

Messages : 94
Date d'inscription : 25/07/2016

Revenir en haut Aller en bas

Voir le sujet précédent Voir le sujet suivant Revenir en haut


 
Permission de ce forum:
Vous ne pouvez pas répondre aux sujets dans ce forum