# Signature

# Préface

Cette section contient des informations sur la maniĂšre d'utiliser ce document.

# Conventions utilisées dans ce document

Ce document utilise les conventions de notation pour BASE64URL(OCTETS), UTF8(CHAÎNE), ASCII(CHAÎNE), et || dĂ©finies dans la RFC 75151 (opens new window).

Les conventions suivantes sont utilisées dans ce document pour identifier les types d'information spécifiés.

Type d'information Convention Exemple
ÉlĂ©ments de l'API, tels que les ressources Gras /authorization
Variables Italique entre accolades {ID}
Termes du glossaire Italique à la premiÚre occurrence; définis dans le Glossaire Le but de l'API est de permettre des transactions financiÚres interopérables entre un Payeur (un payeur de fonds électroniques dans une transaction de paiement) situé dans un FSP (entité fournissant un service financier numérique à un utilisateur final) et un Bénéficiaire (un destinataire des fonds électroniques dans une transaction de paiement) situé dans un autre FSP.
Documents de rĂ©fĂ©rence Italique Les informations utilisateur ne doivent gĂ©nĂ©ralement pas ĂȘtre utilisĂ©es par les implĂ©mentations de l'API ; les mesures de sĂ©curitĂ© dĂ©taillĂ©es dans Signature de l'API et Chiffrement de l'API doivent ĂȘtre utilisĂ©es Ă  la place.

# Informations sur les versions du document

Version Date Description des changements
1.1 2020-05-19 Cette version contient les changements suivants : 1. Les sections 3.1, 3.2 et 3.3 ont été mises à jour selon « Solution Proposal 12 - Clarify usage of FSPIOP-Destination ». 2. Les éléments ExtensionList dans la section 4 ont été mis à jour en fonction du problÚme Interpretation of the Data Model for the ExtensionList element (opens new window), pour corriger le modÚle de données de l'objet extensionList.
1.0 2018-03-13 Version initiale

# Introduction

Ce document dĂ©taille les mĂ©thodes de sĂ©curitĂ© Ă  implĂ©menter pour l'Open API pour l'interopĂ©rabilitĂ© des FSP (ci-aprĂšs dĂ©nommĂ©e l'API) afin de garantir l’intĂ©gritĂ© et la non-rĂ©pudiation entre le client API et le serveur API.

En sĂ©curitĂ© de l'information, l’intĂ©gritĂ© des donnĂ©es signifie maintenir et assurer l'exactitude et la complĂ©tude des donnĂ©es sur tout leur cycle de vie. Pour l'API, l'intĂ©gritĂ© des donnĂ©es signifie qu'un message API ne peut ĂȘtre modifiĂ© de maniĂšre non autorisĂ©e ou non dĂ©tectĂ©e par les parties impliquĂ©es dans la communication API.

Dans les termes juridiques, la non-rĂ©pudiation signifie qu'une personne s'engage Ă  remplir ses obligations contractuelles. Cela signifie aussi qu'une des parties Ă  une transaction ne peut pas nier avoir reçu la transaction, pas plus que l'autre partie ne peut nier l’avoir envoyĂ©e. Pour l'API, la non-rĂ©pudiation signifie qu’un client API ne peut pas nier avoir envoyĂ© un message API Ă  une contrepartie. JSON Web Signature (JWS), telle que dĂ©finie dans la RFC 75152 (opens new window), doit ĂȘtre appliquĂ©e Ă  l'API pour garantir l'intĂ©gritĂ© et la non-rĂ©pudiation du message, soit pour des champs composants d'une charge utile API, soit pour la totalitĂ© de celle-ci. À chaque fois qu'un client API envoie un message API Ă  une contrepartie, le client API doit signer le message Ă  l'aide de sa clĂ© privĂ©e. AprĂšs que la contrepartie a reçu le message API, elle doit valider la signature avec la clĂ© publique du client API. Seul le message HTTP request d'une API doit ĂȘtre signĂ© ; toute rĂ©ponse API HTTP NE DOIT PAS ĂȘtre signĂ©e.

Note : La clĂ© publique correspondante doit soit ĂȘtre partagĂ©e Ă  l'avance avec la contrepartie, soit ĂȘtre rĂ©cupĂ©rĂ©e par la contrepartie (par exemple via l'autoritĂ© de certification du systĂšme local).

Comme les frais d'intermĂ©diaire ne sont pas supportĂ©s dans la version courante de l'API, les intermĂ©diaires impliquĂ©s dans le transit du message API ne peuvent pas modifier la charge utile du message API. Ainsi, la signature au niveau de la charge utile complĂšte est utilisĂ©e pour protĂ©ger l'intĂ©gritĂ© de l'ensemble du message API de bout en bout. Peu importe le nombre d'intermĂ©diaires, la charge utile originale ne peut pas ĂȘtre modifiĂ©e. Le destinataire final du message API doit valider la signature gĂ©nĂ©rĂ©e par le client API original en se basant sur la charge utile reçue.

Note : La nĂ©cessitĂ© pour les intermĂ©diaires d’effectuer la validation de la signature en transit dĂ©pend de l’implĂ©mentation interne de chaque intermĂ©diaire ou du systĂšme local.

Note : Dans une future version de l'API, les frais d’intermĂ©diaire pourraient ĂȘtre pris en charge ; la signature au niveau du champ pourrait alors aussi ĂȘtre prise en charge. Cependant, ces deux fonctionnalitĂ©s sont hors du pĂ©rimĂštre de cette version de l'API.


# Spécification Open API pour l'interopérabilité des FSP

La spécification Open API pour l'interopérabilité des FSP inclut les documents suivants.

# Documents logiques

# Documents de liaison REST asynchrone

# Intégrité des données, confidentialité et non-répudiation

# Documents généraux


# Définition de la signature API

Cette section présente la technologie utilisée par la signature API, y compris le format d'échange de données pour la signature d'un message API et le mécanisme utilisé pour générer et vérifier une signature.

# ModÚle de données de la signature

L'API utilise un paramĂštre d'en-tĂȘte HTTP personnalisĂ© FSPIOP-Signature pour reprĂ©senter la signature produite par le client API initiateur pour le message API. Le modĂšle de donnĂ©es de ce paramĂštre est dĂ©crit dans le Tableau 1.

Note : Actuellement, l'API ne prend pas en charge les intermĂ©diaires dans un message API ; seul l'initiateur du message peut signer un message. Si cela est requis Ă  l'avenir, un nouveau paramĂštre d'en-tĂȘte HTTP personnalisĂ© sera dĂ©fini, mais cela est hors pĂ©rimĂštre pour cette version de l'API.

# Tableau 1
Nom Cardinalité Type Description
protectedHeader 1 ChaĂźne(1..32768)
Cet Ă©lĂ©ment indique les paramĂštres d'en-tĂȘte HTTP protĂ©gĂ©s par la signature. Sa valeur doit ĂȘtre BASE64URL(UTF8(JWS Protected Header)).

Selon la spĂ©cification JWS, le paramĂštre d'en-tĂȘte alg doit ĂȘtre prĂ©sent pour identifier l'algorithme cryptographique utilisĂ© pour sĂ©curiser le JWS.

Un paramĂštre personnalisĂ© FSPIOP-URI reprĂ©sentant le chemin d'URI et les paramĂštres de requĂȘte du message de requĂȘte HTTP de l'API doit ĂȘtre prĂ©sent.

Un paramĂštre personnalisĂ© FSPIOP-HTTP-Method contenant la mĂ©thode HTTP utilisĂ©e dans le message HTTP doit ĂȘtre prĂ©sent.

Un paramĂštre personnalisĂ© FSPIOP-Source indiquant le systĂšme qui a envoyĂ© la requĂȘte API doit ĂȘtre prĂ©sent.

Le paramĂštre d'en-tĂȘte HTTP personnalisĂ© FSPIOP-Destination est obligatoire dans protectedHeader si le FSP de destination est connu par l'initiateur du message. Sinon, cet en-tĂȘte ne doit pas ĂȘtre protĂ©gĂ© car il peut ĂȘtre modifiĂ© par les systĂšmes intermĂ©diaires. Voir DĂ©finition de l'API pour plus d'informations sur les services pour lesquels l'en-tĂȘte FSPIOP-Destination est optionnel.
signature 1 Chaßne(1..512) Cet élément représente la signature. Sa valeur fait partie de la sérialisation JWS : BASE64URL(JWS Signature).

Tableau 1 – ModĂšle de donnĂ©es du champ d'en-tĂȘte HTTP FSPIOP-Signature

# Génération d'une signature

Pour crĂ©er la signature d'un message API, on effectue les Ă©tapes suivantes. L’ordre des Ă©tapes n’est pas significatif lorsque les entrĂ©es et sorties ne dĂ©pendent pas les unes des autres.

  1. Créer le contenu à utiliser comme JWS Payload. Puisque la signature est actuellement au niveau de la charge utile complÚte, le corps complet HTTP du message API est le JWS Payload.

  2. Calculer la valeur encodée du payload : BASE64URL(JWS Payload).

  3. Créer l'objet ou les objets JSON contenant les paramÚtres désirés pour le JWS Protected Header.

    A. Le paramĂštre alg du JWS Protected Header doit ĂȘtre prĂ©sent. Dans l’API, les algorithmes disponibles pour la signature sont RS256, RS384, RS512. Une clĂ© d’une taille de 2048 bits ou supĂ©rieure doit ĂȘtre utilisĂ©e avec ces algorithmes.

    B. Les autres paramĂštres enregistrĂ©s dans l’IANA JSON Web Signature and Encryption Header Parameters3 (opens new window) sont optionnels.

    C. Le paramĂštre personnalisĂ© FSPIOP-URI doit ĂȘtre inclus dans le JWS Protected Header pour protĂ©ger le chemin d'URI et les paramĂštres de requĂȘte des API.

    D. Le paramĂštre personnalisĂ© FSPIOP-HTTP-Method doit ĂȘtre inclus dans le JWS Protected Header pour protĂ©ger la mĂ©thode HTTP de la requĂȘte.

    E. Le paramĂštre FSPIOP-Source doit ĂȘtre prĂ©sent, sa valeur provenant du paramĂštre d'en-tĂȘte HTTP correspondant FSPIOP-Source.

    F. Le paramĂštre FSPIOP-Destination doit ĂȘtre prĂ©sent si le FSP de destination est connu par l'initiateur du message, et sa valeur doit ĂȘtre la mĂȘme que le paramĂštre d'en-tĂȘte HTTP FSPIOP-Destination.

    G. Il est recommandĂ© d'inclure d'autres paramĂštres d’en-tĂȘte HTTP des APIs dans le JWS Protected Header, mais ils sont optionnels.

  4. Calculer la valeur encodĂ©e de l'en-tĂȘte : BASE64URL(UTF8(JWS Protected Header)).

  5. Calculer la signature JWS selon la spécification JWS en utilisant la sortie des étapes 2 et 4.

  6. Calculer la valeur encodée de la signature : BASE64URL(JWS Signature).

  7. Calculer la valeur pour le paramĂštre d'en-tĂȘte HTTP FSPIOP-Signature tel que dĂ©crit dans la section ModĂšle de donnĂ©es de la signature. La valeur de ce FSPIOP-Signature est une chaĂźne de sĂ©rialisation d’objet JSON.

Note : Si JSON Web Encryption (JWE) est utilisĂ© pour chiffrer certains champs de la charge utile (voir « Chiffrement »), alors le client API doit tout d’abord chiffrer les champs concernĂ©s, remplacer leur texte en clair par le texte chiffrĂ© encodĂ© dans la charge utile, puis enfin signer la charge utile.

# Validation de la signature

Lors de la validation de la signature d'une requĂȘte API, on effectue les Ă©tapes suivantes. L’ordre des Ă©tapes n’est pas significatif lorsque les entrĂ©es et sorties ne dĂ©pendent pas les unes des autres. Si l’une des Ă©tapes Ă©choue, alors la signature ne peut pas ĂȘtre validĂ©e.

  1. Analyser le paramĂštre d’en-tĂȘte HTTP FSPIOP-Signature pour obtenir les composants protectedHeader et signature.

  2. Utiliser BASE64URL pour dĂ©coder la reprĂ©sentation encodĂ©e du JWS Protected Header. VĂ©rifier que la sĂ©quence d’octets rĂ©sultante est une reprĂ©sentation UTF-8 d’un objet JSON complĂštement valide conforme au format JSON Data Interchange, dĂ©fini dans la RFC 71594 (opens new window).

  3. Vérifier les paramÚtres du JWS Protected Header.

    a) Le paramĂštre alg doit ĂȘtre prĂ©sent et sa valeur doit ĂȘtre l'une de RS256, RS384, RS512.

    b) Les autres paramĂštres enregistrĂ©s dans l’IANA JSON Web Signature and Encryption Header Parameters sont optionnels.

    c) Le paramĂštre FSPIOP-URI doit ĂȘtre prĂ©sent et sa valeur doit correspondre exactement Ă  l'URL cible de la requĂȘte.

    d) Le paramĂštre FSPIOP-HTTP-Method doit ĂȘtre prĂ©sent et sa valeur doit ĂȘtre la mĂȘme que la mĂ©thode d'opĂ©ration de la requĂȘte.

    e) Le paramĂštre FSPIOP-Source doit ĂȘtre prĂ©sent, et sa valeur doit ĂȘtre la mĂȘme que celle du paramĂštre d’en-tĂȘte HTTP FSPIOP-Source.

    f) Si le paramĂštre FSPIOP-Destination est prĂ©sent dans le JWS Protected Header, alors sa valeur doit ĂȘtre la mĂȘme que celle du paramĂštre d’en-tĂȘte HTTP FSPIOP-Destination.

    g) S'il y a d'autres paramĂštres d'en-tĂȘte HTTP prĂ©sents dans le JWS Protected Header, leurs valeurs doivent ĂȘtre validĂ©es avec les valeurs d’en-tĂȘte HTTP correspondantes.

  4. Calculer la valeur encodée du payload : BASE64URL(JWS Payload). Actuellement, il s'agit du corps HTTP complet du message API.

  5. Valider la signature JWS contre JWS Signing Input ASCII(BASE64URL(UTF8(JWS Protected Header)) || '.' || BASE64URL(JWS Payload)) de la maniĂšre dĂ©finie par l’algorithme utilisĂ©, qui doit correspondre Ă  la valeur du paramĂštre d’en-tĂȘte alg.

  6. Consigner le résultat de la validation.


# Exemples de signatures API

Cette section utilise un processus de devis typique pour expliquer comment la signature API est implĂ©mentĂ©e via JWS. Les FSP de l’API peuvent vĂ©rifier que leur implĂ©mentation interne pour la signature API est correcte Ă  l’aide du scĂ©nario suivant.

Le cas de cette section utilise RS256 comme algorithme de signature. La clé RSA utilisée dans cet exemple de signature est représentée en format JSON Web Key (JWK), défini dans la RFC 75175 (opens new window), ci-dessous (avec retours à la ligne et indentation pour la présentation uniquement) :

{
    "kty": "RSA",
    "n": "ofgWCuLjybRlzo0tZWJjNiuSfb4p4fAkd_wWJcyQoTbji9k0l8W26mPddxHmfHQp-Vaw-4qPCJrcS2mJPMEzP1Pt0Bm4d4QlL-yRT-SFd2lZS-pCgNMsD1W_YpRPEwOWvG6b32690r2jZ47soMZo9wGzjb_7OMg0LOL-bSf63kpaSHSXndS5z5rexMdbBYUsLA9e-KXBdQOS-UTo7WTBEMa2R2CapHg665xsmtdVMTBQY4uDZlxvb3qCo5ZwKh9kG4LT6_I5IhlJH7aGhyxXFvUK-DWNmoudF8NAco9_h9iaGNj8q2ethFkMLs91kzk2PAcDTW9gb54h4FRWyuXpoQ",
    "e": "AQAB",
    "d": "Eq5xpGnNCivDflJsRQBXHx1hdR1k6Ulwe2JZD50LpXyWPEAeP88vLNO97IjlA7_GQ5sLKMgvfTeXZx9SE-7YwVol2NXOoAJe46sui395IW_GO-pWJ1O0BkTGoVEn2bKVRUCgu-GjBVaYLU6f3l9kJfFNS3E0QbVdxzubSu3Mkqzjkn439X0M_V51gfpRLI9JYanrC4D4qAdGcopV_0ZHHzQlBjudU2QvXt4ehNYTCBr6XCLQUShb1juUO1ZdiYoFaFQT5Tw8bGUl_x_jTj3ccPDVZFD9pIuhLhBOneufuBiB4cS98l2SR_RQyGWSeWjnczT0QU91p1DhOVRuOopznQ",
    "p": "4BzEEOtIpmVdVEZNCqS7baC4crd0pqnRH_5IB3jw3bcxGn6QLvnEtfdUdiYrqBdss1l58BQ3KhooKeQTa9AB0Hw_Py5PJdTJNPY8cQn7ouZ2KKDcmnPGBY5t7yLc1QlQ5xHdwW1VhvKn-nXqhJTBgIPgtldC-KDV5z-y2XDwGUc",
    "q": "uQPEfgmVtjL0Uyyx88GZFF1fOunH3-7cepKmtH4pxhtCoHqpWmT8YAmZxaewHgHAjLYsp1ZSe7zFYHj7C6ul7TjeLQeZD_YwD66t62wDmpe_HlB-TnBA-njbglfIsRLtXlnDzQkv5dTltRJ11BKBBypeeF6689rjcJIDEz9RWdc",
    "dp": "BwKfV3Akq5_MFZDFZCnW-wzl-CCo83WoZvnLQwCTeDv8uzluRSnm71I3QCLdhrqE2e9YkxvuxdBfpT_PI7Yz-FOKnu1R6HsJeDCjn12Sk3vmAktV2zb34MCdy7cpdTh_YVr7tss2u6vneTwrA86rZtu5Mbr1C1XsmvkxHQAdYo0",
    "dq": "h_96-mK1R_7glhsum81dZxjTnYynPbZpHziZjeeHcXYsXaaMwkOlODsWa7I9xXDoRwbKgB719rrmI2oKr6N3Do9U0ajaHF-NKJnwgjMd2w9cjz3_-kyNlxAr2v4IKhGNpmM5iIgOS1VZnOZ68m6_pbLBSp3nssTdlqvd0tIiTHU",
    "qi": "IYd7DHOhrWvxkwPQsRM2tOgrjbcrfvtQJipd-DlcxyVuuM9sQLdgjVk2oy26F0EmpScGLq2MowX7fhd_QJQ3ydy5cY7YIBi87w93IKLEdfnbJtoOPLUW0ITrJReOgo1cq9SbsxYawBgfp_gh6A5603k2-ZQwVK0JKSHuLFkuQ3U"
}

# Génération d'une signature exemple

Le texte de message ci-dessous est un exemple de POST /quotes sans signature, envoyé par le FSP Payeur vers un destinataire (retours à la ligne et indentation à des fins de présentation uniquement).

POST /quotes HTTP/1.1
Accept:application/vnd.interoperability.quotes+json;version=1.0
FSPIOP-Source:1234
FSPIOP-Destination:5678
Content-Length:975
Date:Tue, 23 May 2017 21:12:31 GMT
Content-Type:application/vnd.interoperability.quotes+json;version=1.0
{
    "amount": { "amount": "150", "currency": "USD" },"transactionType": {
        "scenario": "TRANSFER", "initiator": "PAYER","subScenario": "P2P Transfer across MM systems","initiatorType": "CONSUMER"
    },
    "transactionId": "36629a51-393a-4e3c-b347-c2cb57e1e1fc","quoteId": "59e331fa-345f-4554-aac8-fcd8833f7d50","expiration": "2017-05-24T08:40:00.000-04:00",
    "payer": {
        "personalInfo": {
            "dateOfBirth": "1986-02-14",
            "complexName": { "middleName": "Ben",
            "LastName": "Lee", "firstName": "Bill" } },
            "name": "Bill Lee",
            "partyIdInfo": { "fspId": "1234", "partyIdType": "MSISDN",
                "partySubIdOrType": "RegisteredCustomer","partyIdentifier": "16135551212" }
    },
    "payee": {
        "partyIdInfo": { "fspId": "5678",
        "partyIdType": "MSISDN",
        "partyIdentifier": "15295558888" }
    },
    "fees": { "amount": "1.5", "currency": "USD" },
    "extensionList": {
        "extension": [
            { "value": "value1", "key": "key1" },
            { "value": "value2", "key": "key2" },
            { "value": "value3", "key": "key3" }
        ]
    },
    "note": "this is a sample for POST /quotes",
    "geoCode": {
        "longitude": "125.520001", "latitude": "57.323889" },
    "amountType": "RECEIVE"
}

# Calcul de l'entrée de la signature

Conformément à la spécification JWS, l'entrée de la signature est BASE64URL(UTF8(JWS Protected Header)) || '.' || BASE64URL(JWS Payload).

En supposant que les paramĂštres d'en-tĂȘte HTTP Date et FSPIOP-Destination soient protĂ©gĂ©s par la signature, et que l'algorithme RS256 soit utilisĂ© pour signer le message, le JWS Protected Header est le suivant (indentation pour la prĂ©sentation uniquement) :

{
    "alg":"RS256",
    "FSPIOP-Destination":"5678",
    "FSPIOP-URI":"/quotes",
    "FSPIOP-HTTP-Method":"POST",
    "Date":"Tue, 23 May 2017 21:12:31 GMT",
    "FSPIOP-Source":"1234"
}

L'encodage de ce JWS Protected Header en BASE64URL(UTF8(JWS Protected Header)) donne :

eyJhbGciOiJSUzI1NiIsIkZTUElPUC1EZXN0aW5hdGlvbiI6IjU2NzgiLCJGU1BJT1AtVVJJIjoiL3F1b3RlcyIsIkZTUElPUC1IVFRQLU1ldGhvZCI6IlBPU1QiLCJEYXRlIjoiVHVlLCAyMyBNYXkgMjAxNyAyMToxMjozMSBHTVQiLCJGU1BJT1AtU291cmNlIjoiMTIzNCJ9

Dans ce cas, le JWS Payload est le corps HTTP décrit dans la section Génération d'une signature. En codant ce JWS Payload en BASE64URL(JWS Payload), on obtient :

eyJwYXllZSI6eyJwYXJ0eUlkSW5mbyI6eyJwYXJ0eUlkVHlwZSI6Ik1TSVNETiIsInBhcnR5SWRlbnRpZmllciI6IjE1Mjk1NTU4ODg4IiwiZnNwSWQiOiI1Njc4In19LCJhbW91bnRUeXBlIjoiUkVDRUlWRSIsInRyYW5zYWN0aW9uVHlwZSI6eyJzY2VuYXJpbyI6IlRSQU5TRkVSIiwiaW5pdGlhdG9yIjoiUEFZRVIiLCJzdWJTY2VuYXJpbyI6IlAyUCBUcmFuc2ZlciBhY3Jvc3MgTU0gc3lzdGVtcyIsImluaXRpYXRvclR5cGUiOiJDT05TVU1FUiJ9LCJub3RlIjoidGhpcyBpcyBhIHNhbXBsZSBmb3IgUE9TVCAvcXVvdGVzIiwiYW1vdW50Ijp7ImFtb3VudCI6IjE1MCIsImN1cnJlbmN5IjoiVVNEIn0sImZlZXMiOnsiYW1vdW50IjoiMS41IiwiY3VycmVuY3kiOiJVU0QifSwiZXh0ZW5zaW9uTGlzdCI6W3sidmFsdWUiOiJ2YWx1ZTEiLCJrZXkiOiJrZXkxIn0seyJ2YWx1ZSI6InZhbHVlMiIsImtleSI6ImtleTIifSx7InZhbHVlIjoidmFsdWUzIiwia2V5Ijoia2V5MyJ9XSwiZ2VvQ29kZSI6eyJsYXRpdHVkZSI6IjU3LjMyMzg4OSIsImxvbmdpdHVkZSI6IjEyNS41MjAwMDEifSwiZXhwaXJhdGlvbiI6IjIwMTctMDUtMjRUMDg6NDA6MDAuMDAwLTA0OjAwIiwicGF5ZXIiOnsicGVyc29uYWxJbmZvIjp7ImNvbXBsZXhOYW1lIjp7ImZpcnN0TmFtZSI6IkJpbGwiLCJtaWRkbGVOYW1lIjoiQmVuIiwiTGFzdE5hbWUiOiJMZWUifSwiZGF0ZU9mQmlydGgiOiIxOTg2LTAyLTE0In0sInBhcnR5SWRJbmZvIjp7InBhcnR5SWRUeXBlIjoiTVNJU0ROIiwicGFydHlTdWJJZE9yVHlwZSI6IlJlZ2lzdGVyZWRDdXN0b21lciIsInBhcnR5SWRlbnRpZmllciI6IjE2MTM1NTUxMjEyIiwiZnNwSWQiOiIxMjM0In0sIm5hbWUiOiJCaWxsIExlZSJ9LCJxdW90ZUlkIjoiNTllMzMxZmEtMzQ1Zi00NTU0LWFhYzgtZmNkODgzM2Y3ZDUwIiwidHJhbnNhY3Rpb25JZCI6IjM2NjI5YTUxLTM5M2EtNGUzYy1iMzQ3LWMyY2I1N2UxZTFmYyJ9

# Production de la signature

Utiliser la clé privée RSA fournie, le JWS Protected Header et le JWS Payload pour générer la signature, puis encoder la signature en BASE64URL(JWS Signature) donne :

dz2ntyS0_rDyA0pLeWluG--tBcYYrlvG99ffkXcEB-dz2ntyS0_rDyA0pLeWluG--tBcYYrlvG99ffkXcEB-uve5Qzvzyn0ZUi82J7h17RsdfHPuTnbEGvCeU9Y4Bg0nIZHGL4icswaaO09T5hPPYKBTzVQeHkokLmL4dXpHdr1ggSEpu3WEU3nfgOFGGAdOq355i1iGuDbhqm_lSfVHaqdVCEhkJ2Y_r2glO2QpdZrcbvsBV39derj_PlfISBBGjdh0dIPxnFIVcZuPHiq9Ha2MslrBHfqwFfNeU_xhErBd2PywkDQJbKOlfqdkmFC9bS8Ofx0O6Mg7qdFGw-QkseJTfp0HMbH1d9e6H0cocY8xfuDNGaZpOJhxiYtiPLg

# Reproduction de la requĂȘte API avec signature

Comme dĂ©crit dans la section ModĂšle de donnĂ©es de la signature, la signature API est reprĂ©sentĂ©e par un en-tĂȘte HTTP personnalisĂ© FSPIOP-Signature ; donc la requĂȘte API avec la signature dans ce cas ressemble à :

POST /quotes HTTP/1.1
FSPIOP-Destination:5678
Accept:application/vnd.interoperability.quotes+json;version=1.0
Content-Length:975
Date:Tue, 23 May 2017 21:12:31 GMT
FSPIOP-Source:1234
Content-Type:application/vnd.interoperability.quotes+json;version=1.0
FSPIOP-Signature: {"signature": "dz2ntyS0_rDyA0pLeWluG--tBcYYrlvG99ffkXcEBuve5Qzvzyn0ZUi82J7h17RsdfHPuTnbEGvCeU9Y4Bg0nIZHGL4icswaaO09T5hPPYKBTzVQeHkokLmL4dXpHdr1ggSEpu3WEU3nfgOFGGAdOq355i1iGuDbhqm_lSfVHaqdVCEhkJ2Y_r2glO2QpdZrcbvsBV39derj_PlfISBBGjdh0dIPxnFIVcZuPHiq9Ha2MslrBHfqwFfNeU_xhErBd2PywkDQJbKOlfqdkmFC9bS8Ofx0O6Mg7qdFGwQkseJTfp0HMbH1d9e6H0cocY8xfuDNGaZpOJhxiYtiPLg", "protectedHeader": "eyJhbGciOiJSUzI1NiIsIkZTUElPUC1EZXN0aW5hdGlvbiI6IjU2NzgiLCJGU1BJT1AtVVJJIjoiL3F1b3RlcyIsIkZTUElPUC1IVFRQLU1ldGhvZCI6IlBPU1QiLCJEYXRlIjoiVHVlLCAyMyBNYXkgMjAxNyAyMToxMjozMSBHTVQiLCJGU1BJT1AtU291cmNlIjoiMTIzNCJ9"
}
{
    "amount": { "amount": "150", "currency": "USD" },
    "transactionType": {
        "scenario": "TRANSFER", "initiator": "PAYER",
        "subScenario": "P2P Transfer across MM systems",
        "initiatorType": "CONSUMER" },
    "transactionId": "36629a51-393a-4e3c-b347-c2cb57e1e1fc",
    "quoteId": "59e331fa-345f-4554-aac8-fcd8833f7d50",
    "expiration": "2017-05-24T08:40:00.000-04:00",
    "payer": {
        "personalInfo": { "dateOfBirth": "1986-02-14",
            "complexName": { "middleName": "Ben",
                "LastName": "Lee", "firstName": "Bill" } },
        "name": "Bill Lee",
        "partyIdInfo": { "fspId": "1234", "partyIdType": "MSISDN",
            "partySubIdOrType": "RegisteredCustomer",
            "partyIdentifier": "16135551212" } },
    "payee": { "partyIdInfo": { "fspId": "5678",
        "partyIdType": "MSISDN",
        "partyIdentifier": "15295558888" } },
    "fees": { "amount": "1.5", "currency": "USD" },
    "extensionList": {
        "extension": [
            { "value": "value1", "key": "key1" },
            { "value": "value2", "key": "key2" },
            { "value": "value3", "key": "key3" }
        ]
    },
    "note": "this is a sample for POST /quotes",
    "geoCode": { "longitude": "125.520001", "latitude": "57.323889" },
    "amountType": "RECEIVE"
}

# Validation de la signature

AprÚs que le FSP Bénéficiaire ait reçu le message API POST /quotes du FSP Payeur, le FSP Bénéficiaire doit valider la signature signée par le FSP Payeur.

# Analyse de FSPIOP-Signature

  1. Analysez le paramĂštre d’en-tĂȘte HTTP FSPIOP-Signature pour obtenir les composants protectedHeader et signature. Dans ce cas, la valeur de protectedHeader est :
eyJhbGciOiJSUzI1NiIsIkZTUElPUC1EZXN0aW5hdGlvbiI6IjU2NzgiLCJGU1BJT1AtVVJJIjo
iL3F1b3RlcyIsIkZTUElPUC1IVFRQLU1ldGhvZCI6IlBPU1QiLCJEYXRlIjoiVHVlLCAyMyBNYX
kgMjAxNyAyMToxMjozMSBHTVQiLCJGU1BJT1AtU291cmNlIjoiMTIzNCJ9
  1. Utilisez BASE64URL pour dĂ©coder la reprĂ©sentation encodĂ©e du JWS Protected Header. VĂ©rifiez que la sĂ©quence d’octets rĂ©sultante est une reprĂ©sentation UTF-8 d’un objet JSON conforme au format RFC7159. Dans ce cas, l'objet JSON dĂ©codĂ© est :
{
    "alg":"RS256",
    "FSPIOP-Destination":"5678",
    "FSPIOP-URI":"/quotes",
    "FSPIOP-HTTP-Method":"POST",
    "Date":"Tue, 23 May 2017 21:12:31 GMT",
    "FSPIOP-Source":"1234"
}
  1. VĂ©rifier que le paramĂštre alg est valide pour l’API. Il doit faire partie de RS256, RS384, RS512. Dans ce cas, la valeur alg est RS256, ce qui est valide.

  2. VĂ©rifier que la valeur du paramĂštre FSPIOP-URI est la mĂȘme que l’URL d’entrĂ©e de ce message API.

  3. VĂ©rifier que la valeur du paramĂštre FSPIOP-HTTP-Method est la mĂȘme que la mĂ©thode HTTP de ce message API.

  4. VĂ©rifier que la valeur de l'en-tĂȘte HTTP FSPIOP-Source est la mĂȘme que celle indiquĂ©e dans ce JWS Protected Header.

  5. VĂ©rifier que la valeur de l’en-tĂȘte HTTP FSPIOP-Destination est la mĂȘme que celle indiquĂ©e dans ce JWS Protected Header.

  6. VĂ©rifier les autres paramĂštres d’en-tĂȘte HTTP protĂ©gĂ©s. Ici, le paramĂštre Date est protĂ©gĂ© par le JWS Protected Header. Si les paramĂštres Date dans l’en-tĂȘte HTTP et le JWS Protected Header sont Ă©gaux, alors la validation est rĂ©ussie. Les deux paramĂštres Date dans l’exemple doivent avoir la valeur :

"Tue, 23 May 2017 21:12:31 GMT"

La validation est réussie.

# Vérification de la signature JWS

  1. Dans ce cas, le JWS Payload est le corps complet du message HTTP de l'API, donc (indentation incluse pour la présentation) :
{
    "amount": { "amount": "150", "currency": "USD" },
    "transactionType": { "scenario": "TRANSFER", "initiator": "PAYER",
    "subScenario": "P2P Transfer across MM systems",
    "initiatorType": "CONSUMER"
    },
    "transactionId": "36629a51-393a-4e3c-b347-c2cb57e1e1fc",
    "quoteId": "59e331fa-345f-4554-aac8-fcd8833f7d50",
    "expiration": "2017-05-24T08:40:00.000-04:00",
    "payer": {
        "personalInfo": { "dateOfBirth": "1986-02-14",
            "complexName": { "middleName": "Ben",
                "LastName": "Lee", "firstName": "Bill" } },
        "name": "Bill Lee",
        "partyIdInfo": { "fspId": "1234",
            "partyIdType": "MSISDN",
            "partySubIdOrType": "RegisteredCustomer",
            "partyIdentifier": "16135551212" } },
    "payee": {
        "partyIdInfo": { "fspId": "5678",
            "partyIdType": "MSISDN",
            "partyIdentifier": "15295558888" } },
    "fees": { "amount": "1.5", "currency": "USD" },
    "extensionList": {
        "extension": [
            { "value": "value1", "key": "key1" },
            { "value": "value2", "key": "key2" },
            { "value": "value3", "key": "key3" }
        ]
    },
    "note": "this is a sample for POST /quotes",
    "geoCode": { "longitude": "125.520001", "latitude": "57.323889" },
    "amountType": "RECEIVE"
}
  1. Calculez la valeur encodée du payload : BASE64URL(JWS Payload). Obtenez la valeur encodée suivante :
eyJwYXllZSI6eyJwYXJ0eUlkSW5mbyI6eyJwYXJ0eUlkVHlwZSI6Ik1TSVNETiIsInBhcnR5SWRlbnRpZmllciI6IjE1Mjk1NTU4ODg4IiwiZnNwSWQiOiI1Njc4In19LCJhbW91bnRUeXBlIjoiUkVDRUlWRSIsInRyYW5zYWN0aW9uVHlwZSI6eyJzY2VuYXJpbyI6IlRSQU5TRkVSIiwiaW5pdGlhdG9yIjoiUEFZRVIiLCJzdWJTY2VuYXJpbyI6IlAyUCBUcmFuc2ZlciBhY3Jvc3MgTU0gc3lzdGVtcyIsImluaXRpYXRvclR5cGUiOiJDT05TVU1FUiJ9LCJub3RlIjoidGhpcyBpcyBhIHNhbXBsZSBmb3IgUE9TVCAvcXVvdGVzIiwiYW1vdW50Ijp7ImFtb3VudCI6IjE1MCIsImN1cnJlbmN5IjoiVVNEIn0sImZlZXMiOnsiYW1vdW50IjoiMS41IiwiY3VycmVuY3kiOiJVU0QifSwiZXh0ZW5zaW9uTGlzdCI6W3sidmFsdWUiOiJ2YWx1ZTEiLCJrZXkiOiJrZXkxIn0seyJ2YWx1ZSI6InZhbHVlMiIsImtleSI6ImtleTIifSx7InZhbHVlIjoidmFsdWUzIiwia2V5Ijoia2V5MyJ9XSwiZ2VvQ29kZSI6eyJsYXRpdHVkZSI6IjU3LjMyMzg4OSIsImxvbmdpdHVkZSI6IjEyNS41MjAwMDEifSwiZXhwaXJhdGlvbiI6IjIwMTctMDUtMjRUMDg6NDA6MDAuMDAwLTA0OjAwIiwicGF5ZXIiOnsicGVyc29uYWxJbmZvIjp7ImNvbXBsZXhOYW1lIjp7ImZpcnN0TmFtZSI6IkJpbGwiLCJtaWRkbGVOYW1lIjoiQmVuIiwiTGFzdE5hbWUiOiJMZWUifSwiZGF0ZU9mQmlydGgiOiIxOTg2LTAyLTE0In0sInBhcnR5SWRJbmZvIjp7InBhcnR5SWRUeXBlIjoiTVNJU0ROIiwicGFydHlTdWJJZE9yVHlwZSI6IlJlZ2lzdGVyZWRDdXN0b21lciIsInBhcnR5SWRlbnRpZmllciI6IjE2MTM1NTUxMjEyIiwiZnNwSWQiOiIxMjM0In0sIm5hbWUiOiJCaWxsIExlZSJ9LCJxdW90ZUlkIjoiNTllMzMxZmEtMzQ1Zi00NTU0LWFhYzgtZmNkODgzM2Y3ZDUwIiwidHJhbnNhY3Rpb25JZCI6IjM2NjI5YTUxLTM5M2EtNGUzYy1iMzQ3LWMyY2I1N2UxZTFmYyJ9
  1. Validez la signature JWS par rapport à JWS Signing Input (le JWS Protected Header, JWS Payload) avec l'algorithme RS256 (spécifié dans le JWS Protected Header), et la clé publique. Notez si la validation a réussi ou non.

# Références

1 https://tools.ietf.org/html/rfc7515#section-1.1 (opens new window) – JSON Web Signature (JWS) - Conventions de notation

2 https://tools.ietf.org/html/rfc7515 (opens new window) – JSON Web Signature (JWS)

3 https://www.iana.org/assignments/jose/jose.xhtml#web-signature-encryption-header-parameters (opens new window) – ParamĂštres d’en-tĂȘte JSON Web Signature et Encryption

4 https://tools.ietf.org/html/rfc7159 (opens new window) – Format d'Ă©change de donnĂ©es JavaScript Object Notation (JSON)

5 https://tools.ietf.org/html/rfc7517 (opens new window) – JSON Web Key (JWK)