# 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.
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.
Calculer la valeur encodée du payload : BASE64URL(JWS Payload).
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.
Calculer la valeur encodĂ©e de l'en-tĂȘte : BASE64URL(UTF8(JWS Protected Header)).
Calculer la signature JWS selon la spécification JWS en utilisant la sortie des étapes 2 et 4.
Calculer la valeur encodée de la signature : BASE64URL(JWS Signature).
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.
Analyser le paramĂštre dâen-tĂȘte HTTP FSPIOP-Signature pour obtenir les composants protectedHeader et signature.
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).
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.
Calculer la valeur encodée du payload : BASE64URL(JWS Payload). Actuellement, il s'agit du corps HTTP complet du message API.
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.
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
- 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
- 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"
}
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.
VĂ©rifier que la valeur du paramĂštre FSPIOP-URI est la mĂȘme que lâURL dâentrĂ©e de ce message API.
VĂ©rifier que la valeur du paramĂštre FSPIOP-HTTP-Method est la mĂȘme que la mĂ©thode HTTP de ce message API.
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.
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.
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
- 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"
}
- Calculez la valeur encodée du payload : BASE64URL(JWS Payload). Obtenez la valeur encodée suivante :
eyJwYXllZSI6eyJwYXJ0eUlkSW5mbyI6eyJwYXJ0eUlkVHlwZSI6Ik1TSVNETiIsInBhcnR5SWRlbnRpZmllciI6IjE1Mjk1NTU4ODg4IiwiZnNwSWQiOiI1Njc4In19LCJhbW91bnRUeXBlIjoiUkVDRUlWRSIsInRyYW5zYWN0aW9uVHlwZSI6eyJzY2VuYXJpbyI6IlRSQU5TRkVSIiwiaW5pdGlhdG9yIjoiUEFZRVIiLCJzdWJTY2VuYXJpbyI6IlAyUCBUcmFuc2ZlciBhY3Jvc3MgTU0gc3lzdGVtcyIsImluaXRpYXRvclR5cGUiOiJDT05TVU1FUiJ9LCJub3RlIjoidGhpcyBpcyBhIHNhbXBsZSBmb3IgUE9TVCAvcXVvdGVzIiwiYW1vdW50Ijp7ImFtb3VudCI6IjE1MCIsImN1cnJlbmN5IjoiVVNEIn0sImZlZXMiOnsiYW1vdW50IjoiMS41IiwiY3VycmVuY3kiOiJVU0QifSwiZXh0ZW5zaW9uTGlzdCI6W3sidmFsdWUiOiJ2YWx1ZTEiLCJrZXkiOiJrZXkxIn0seyJ2YWx1ZSI6InZhbHVlMiIsImtleSI6ImtleTIifSx7InZhbHVlIjoidmFsdWUzIiwia2V5Ijoia2V5MyJ9XSwiZ2VvQ29kZSI6eyJsYXRpdHVkZSI6IjU3LjMyMzg4OSIsImxvbmdpdHVkZSI6IjEyNS41MjAwMDEifSwiZXhwaXJhdGlvbiI6IjIwMTctMDUtMjRUMDg6NDA6MDAuMDAwLTA0OjAwIiwicGF5ZXIiOnsicGVyc29uYWxJbmZvIjp7ImNvbXBsZXhOYW1lIjp7ImZpcnN0TmFtZSI6IkJpbGwiLCJtaWRkbGVOYW1lIjoiQmVuIiwiTGFzdE5hbWUiOiJMZWUifSwiZGF0ZU9mQmlydGgiOiIxOTg2LTAyLTE0In0sInBhcnR5SWRJbmZvIjp7InBhcnR5SWRUeXBlIjoiTVNJU0ROIiwicGFydHlTdWJJZE9yVHlwZSI6IlJlZ2lzdGVyZWRDdXN0b21lciIsInBhcnR5SWRlbnRpZmllciI6IjE2MTM1NTUxMjEyIiwiZnNwSWQiOiIxMjM0In0sIm5hbWUiOiJCaWxsIExlZSJ9LCJxdW90ZUlkIjoiNTllMzMxZmEtMzQ1Zi00NTU0LWFhYzgtZmNkODgzM2Y3ZDUwIiwidHJhbnNhY3Rpb25JZCI6IjM2NjI5YTUxLTM5M2EtNGUzYy1iMzQ3LWMyY2I1N2UxZTFmYyJ9
- 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)
