Déchiffrer les retours API avec votre clé secrète

Pour des raisons de sécurité et afin de garantir la confidentialité des échanges pour vos clients, les retours API d’AR24 sont chiffrés. Vous trouverez ci-dessous la marche à suivre pour déchiffrer et exploiter les retours obtenus.

1. Faire un appel à l’API

Lors des appels à l’API, il est nécessaire de nous transmettre le paramètre date. Ce paramètre doit contenir la date courante au format YYYY-MM-DD HH:MM:SS avec un delta compris entre le moment de l’appel à l’API et +10min. (Exemple lors du chargement de cette page : )
Veuillez notez qu’il faut donc être synchronisé avec notre serveur qui utilise le fuseau horaire d’Europe Centrale (UTC+1, et UTC+2 en heure d’été).

Il est important pour vous de sauvegarder cette donnée qui sera utilisée pour déchiffrer le retour API que vous obtiendrez. Ce paramètre permet de se prémunir d’une attaque par rejeu.

2. Déchiffrer un retour API

Le retour API est chiffré en utilisant le standard AES256 avec l’utilisation de votre private_key (clé privée transmise avec votre token à la création de votre accès API) et le paramètre date renseigné lors de l’appel à l’API.

Voici un exemple en PHP pour déchiffrer le retour chiffré WwBOU6s8DaMWmYdctBJwfuoujFgVygBUjhsbdf8eWqQ= :

$output = 'WwBOU6s8DaMWmYdctBJwfuoujFgVygBUjhsbdf8eWqQ='; /* Le retour chiffré que nous allons déchiffrer */
$date = '2021-05-26 14:00:00'; /* La date qui doit correspondre à la date exacte transmise lors de l'appel */
$private_key = '7X9gx9E3Qx4EiUdB63nc'; /* Votre clé privée obtenue lors de la création de votre accès à l'API */
$key = hash('sha256', $date.$private_key); /* Création de la clé en concaténant la date et la clé privée */
$iv = mb_strcut(hash('sha256', hash('sha256', $private_key)), 0, 16, 'UTF-8'); /* Création du vecteur d'initialisation (2x hash de la clé privée) en prenant 16 octets */
echo(openssl_decrypt($output, 'aes-256-cbc', $key, false, $iv)); /* Affichage du retour en utilisant openssl_decrypt */

Le JSON {status: "SUCCESS"} s’affiche.

Attention à ne pas confondre votre token qui correspond à votre clé d’accès à l’API et votre clé privée qui vous sert à déchiffrer les retours API.

Les valeurs key et iv sont, dans certains langages (JAVA par exemple), la représentation hexa du hash obtenus (la fonction hash en PHP possède un argument « binary » à false par défaut dans notre exemple de code).

Dans l’exemple PHP, l’iv passé en paramètre de la fonction openssl_decrypt est automatiquement tronqué à 16 octets par la fonction. La valeur de key passé en paramètre est également automatiquement tronquée à 32 octets.
Si votre langage n’effectue pas ces transformations automatiquement, vous devrez tronquer l’iv et la key avant de les utiliser.

Le mode utilisé pour les fonctions openSSL est CBC (aes-256-cbc, la valeur par défaut en PHP dans l’exemple).
Enfin le padding utilisé est PKCS#7 (valeur par défaut en PHP mais pas forcément dans d’autres langages).

3. Utiliser Postman avec le chiffrement

Postman est un outil qui sert à exécuter des appels HTTP directement depuis une interface graphique. Il est généralement utilisé pour manipuler et tester les différentes routes d’une API dans le but de comprendre comment celle-ci fonctionne, avant de se lancer dans la phase de développement.

Le chiffrement de nos retours est susceptible de complexifier la découverte de notre API, c’est pour cela que nous vous avons préparé une configuration de Postman vous permettant de déchiffrer automatiquement les retours.

Comment pré-remplir automatiquement le paramètre date attendu lors de chaque appel ?

Comme évoqué précédemment, pour permettre le chiffrement vous devez systématiquement transmettre un champ date correspondant à la date courante (Heure française : UTC+1 en hiver et UTC+2 en été).

Vous trouverez ci-dessous un script qui sera exécuté automatiquement avant l’envoi d’une requête et qui pré-remplira une variable globale {{currentdate}}.

var moment = require('moment');

var time = moment();

/* If necessary you can add a time difference, you must be synchronized with French time. */
//time.add(1,'hours');

pm.globals.set('currentdate', time.format(("YYYY-MM-DD HH:mm:ss")));

Ce script est a renseigner dans la partie « Pre-request Script », cependant nous vous recommandons de l’éditer directement dans la collection Postman pour que celui-ci soit actif sur l’ensemble de vos routes (Clique droit / trois points verticaux, « Edit », puis l’onglet « Pre-request Scripts »).
En savoir plus sur les Pre-request scripts chez Postman

Comment déchiffrer automatiquement en console ?

Pour déchiffrer nos retours, vous aurez besoin de renseigner votre clé privée directement dans le code, ou dans une variable globale {{private_key}}.

Vous trouverez ci-dessous un script qui permet d’automatiquement déchiffrer le résultat de vos requêtes puis de l’afficher dans l’onglet « Test Results » de la requête et dans la console Postman (« View », « Show Postman Console » / Alt+Ctrl+C).

/* Private_key */
var private_key = '';

/* Take the private_key from the variables if not defined above */
if(private_key === '') {
    private_key = pm.globals.get('private_key');
}

/* Decrypts the result if the private key is set */
if(private_key !== undefined) {
    /* Get encrypted result */
    var encrypted_result = responseBody;
    //console.log('encrypted result : '+encrypted_result);

    /* Get date sent */
    if(pm.request.method == 'GET') {
        var date = decodeURI(pm.request.url.query.toObject().date);
    }
    else {
    var date = pm.request.body.formdata.get("date");
    }
    //console.log('date sent : '+date);

    /* Key (Passphrase) */
    var key = CryptoJS.SHA256(date + private_key).toString().substring(0, 32);
    //console.log('key : '+key);
    key = CryptoJS.enc.Hex.parse(key);

    /* IV (Initialization Vector) */
    var iv = CryptoJS.SHA256(CryptoJS.SHA256(private_key.toString(CryptoJS.enc.Hex)).toString(CryptoJS.enc.Hex)).toString(CryptoJS.enc.Hex).substring(0, 16);
    //console.log('iv : '+iv);
    iv = CryptoJS.enc.Hex.parse(iv);

    /* Decrypt */
    var decrypted = CryptoJS.AES.decrypt(
        encrypted_result ,CryptoJS.enc.Utf8.parse(key),
        {
            iv: CryptoJS.enc.Utf8.parse(iv),
            mode: CryptoJS.mode.CBC,
            padding: CryptoJS.pad.Pkcs7
        }
    );

    /* Print result */
    if(decrypted.toString().length > 0) {
        try {
            var res = JSON.parse(decrypted.toString(CryptoJS.enc.Utf8));
            console.log('✔️ Decrypted result :');
            console.log(res);
 
            pm.test("✔️ Decrypted result available in Postman Console (Alt+Ctrl+C) and below", function(){
                pm.expect(1).to.eql(1);
            });
            pm.test(decrypted.toString(CryptoJS.enc.Utf8), function(){
                pm.expect(1).to.eql(1);
            });
        } catch (error) {
            console.log('⚠️ Decryption : failed');

            pm.test("⚠️ Error while decrypting result", function(){
                pm.expect(1).to.eql(1);
            });
        }
    }
    else {
            console.log('⚠️ Decryption : failed');
            
            pm.test("⚠️ Error while decrypting result", function(){
                pm.expect(1).to.eql(1);
            });
    }
}

Ce script est a renseigner dans la partie « Test », cependant nous vous recommandons de l’éditer directement dans la collection Postman pour que celui-ci soit actif sur l’ensemble de vos routes. Pour ce faire, Dans la partie « Collections » survolez le titre de notre collection Postman pour voir apparaitre le symbole d’édition (trois points horizontaux), cliquez dessus et dans le menu qui apparaît, cliquez sur « Edit ». Rendez-vous dans l’onglet « Tests » pour ajouter le code ci-dessus.
En savoir plus sur les Test scripts chez Postman

Vous ne trouvez pas votre réponse ? Contactez nous