__NUXT_JSONP__("/fr/blog/creer-une-messagerie-chiffree-de-bout-en-bout-avec-stream-et-seald", (function(a,b,c,d,e,f,g,h,i,j,k,l){return {data:[{post:{slug:c,id:d,uuid:"590888a4-8558-4a94-ae96-2450ac44582a",title:"Créer une messagerie chiffrée de bout-en-bout avec Stream et Seald 🔒💬",html:"\u003Cp\u003EL'article original a été écrit par Sander Goossens, développeur chez \u003Ca href=\"https:\u002F\u002Fwww.inthepocket.com\u002F?ref=blog.seald.io\"\u003EIn The Pocket\u003C\u002Fa\u003E, vous pouvez le trouver ici : \u003Ca href=\"https:\u002F\u002Fdev.inthepocket.com\u002Fposts\u002F2022-02-15-creating-an-encrypted-chat-with-getstream-and-seald-io\u002F?ref=blog.seald.io\"\u003Ehttps:\u002F\u002Fdev.inthepocket.com\u002Fposts\u002F2022-02-15-creating-an-encrypted-chat-with-getstream-and-seald-io\u002F\u003C\u002Fa\u003E\u003Cbr\u003E\u003Cbr\u003E\u003Cstrong\u003ESander Goossens\u003C\u002Fstrong\u003E : Récemment, un client est venu nous voir pour nous demander une solution de messagerie avec une confidentialité absolue sur les messages. Après quelques recherches, nous avons rapidement trouvé une solution combinant \u003Ca href=\"https:\u002F\u002Fgetstream.io\u002F?ref=blog.seald.io\"\u003EGetStream.io\u003C\u002Fa\u003E et \u003Ca href=\"https:\u002F\u002Fwww.seald.io\u002F?ref=blog.seald.io\"\u003ESeald.io\u003C\u002Fa\u003E.\u003C\u002Fp\u003E\u003Cfigure class=\"kg-card kg-image-card\"\u003E\u003Cimg src=\"https:\u002F\u002Fblog.seald.io\u002Fcontent\u002Fimages\u002F2023\u002F08\u002Fimage-3.png\" class=\"kg-image\" alt loading=\"lazy\" width=\"1654\" height=\"1239\" srcset=\"https:\u002F\u002Fblog.seald.io\u002Fcontent\u002Fimages\u002Fsize\u002Fw600\u002F2023\u002F08\u002Fimage-3.png 600w, https:\u002F\u002Fblog.seald.io\u002Fcontent\u002Fimages\u002Fsize\u002Fw1000\u002F2023\u002F08\u002Fimage-3.png 1000w, https:\u002F\u002Fblog.seald.io\u002Fcontent\u002Fimages\u002Fsize\u002Fw1600\u002F2023\u002F08\u002Fimage-3.png 1600w, https:\u002F\u002Fblog.seald.io\u002Fcontent\u002Fimages\u002F2023\u002F08\u002Fimage-3.png 1654w\" sizes=\"(min-width: 720px) 720px\"\u003E\u003C\u002Ffigure\u003E\u003Cp\u003E\u003Ca href=\"https:\u002F\u002Fgetstream.io\u002F?ref=blog.seald.io\"\u003EGetStream.io\u003C\u002Fa\u003E offre une messagerie en temps réel avec une infrastructure fiable et des SDK riches en fonctionnalités. L'un des principaux arguments de vente de GetStream.io est la disponibilité de composants d'UI prêts à l'emploi. Avec la prise en charge de React Native, React, Android, Flutter, iOS\u002FSwift,... vous pouvez rapidement créer une application de messagerie sans avoir à créer vous-même chaque composant d'UI.\u003C\u002Fp\u003E\u003Cfigure class=\"kg-card kg-image-card\"\u003E\u003Cimg src=\"https:\u002F\u002Fblog.seald.io\u002Fcontent\u002Fimages\u002F2023\u002F08\u002Fimage-26.png\" class=\"kg-image\" alt loading=\"lazy\" width=\"2000\" height=\"1147\" srcset=\"https:\u002F\u002Fblog.seald.io\u002Fcontent\u002Fimages\u002Fsize\u002Fw600\u002F2023\u002F08\u002Fimage-26.png 600w, https:\u002F\u002Fblog.seald.io\u002Fcontent\u002Fimages\u002Fsize\u002Fw1000\u002F2023\u002F08\u002Fimage-26.png 1000w, https:\u002F\u002Fblog.seald.io\u002Fcontent\u002Fimages\u002Fsize\u002Fw1600\u002F2023\u002F08\u002Fimage-26.png 1600w, https:\u002F\u002Fblog.seald.io\u002Fcontent\u002Fimages\u002F2023\u002F08\u002Fimage-26.png 2379w\" sizes=\"(min-width: 720px) 720px\"\u003E\u003C\u002Ffigure\u003E\u003Cp\u003E\u003Ca href=\"https:\u002F\u002Fwww.seald.io\u002F?ref=blog.seald.io\"\u003ESeald.io\u003C\u002Fa\u003E propose un SDK de chiffrement de bout-en-bout, très simple à utiliser.\u003C\u002Fp\u003E\u003Cp\u003ELe chiffrement de bout-en-bout est la technologie la plus sécurisée qui soit, mais c'est aussi la plus complexe et la plus longue à mettre en œuvre (gestion des clés, récupération des comptes utilisateurs, etc.).\u003Cbr\u003E\u003Cbr\u003EPour simplifier son adoption, Seald a développé un SDK associé à une API, qui vous permet d'ajouter le chiffrement de bout-en-bout dans vos applications en quelques lignes de code, sans aucune connaissance préalable en cryptographie.\u003Cbr\u003E\u003Cbr\u003ELa solution bénéficie d'\u003Ca href=\"https:\u002F\u002Fwww.ssi.gouv.fr\u002Fentreprise\u002Fcertification_cspn\u002Fseald-sdk-goatee-version-2-1\u002F?ref=blog.seald.io\"\u003Eun visa de sécurité (CSPN) délivré par l'ANSSI\u003C\u002Fa\u003E, qui vous assure un modèle de sécurité robuste.\u003Cbr\u003E\u003Cbr\u003EGrâce aux API et aux composants SDK mis à disposition par Stream, nous pouvons y intégrer le chiffrement de bout-en-bout de Seald.\u003Cbr\u003E\u003Cbr\u003EAssez d'introduction, voyons ce que nous allons construire et comment nous l'avons abordé !\u003C\u002Fp\u003E\u003Chr\u003E\u003Ch2 id=\"le-but\"\u003ELe but\u003C\u002Fh2\u003E\u003Chr\u003E\u003Cul\u003E\u003Cli\u003ELes messages ne doivent être lisibles que par les membres d'une conversation.\u003C\u002Fli\u003E\u003Cli\u003ELes messages ne doivent pas être lisibles dans le tableau de bord de l'administrateur du flux.\u003C\u002Fli\u003E\u003C\u002Ful\u003E\u003Chr\u003E\u003Ch2 id=\"services\"\u003EServices\u003C\u002Fh2\u003E\u003Chr\u003E\u003Cul\u003E\u003Cli\u003EAPI de messagerie : backend nodeJS personnalisé pour gérer toutes les fonctionnalités GetStream et Seald côté serveur. Avoir une base de données postgreSQL où nous stockons les utilisateurs de Seald.\u003C\u002Fli\u003E\u003Cli\u003EAPI des utilisateurs : backend nodeJS personnalisé pour gérer tout ce qui concerne les utilisateurs.\u003C\u002Fli\u003E\u003C\u002Ful\u003E\u003Cfigure class=\"kg-card kg-image-card\"\u003E\u003Cimg src=\"https:\u002F\u002Fc.tenor.com\u002F4eF0XKHqDB4AAAAC\u002Fmeeting-bored.gif\" class=\"kg-image\" alt loading=\"lazy\"\u003E\u003C\u002Ffigure\u003E\u003Chr\u003E\u003Ch2 id=\"la-mise-en-%C5%93uvre\"\u003ELa mise en œuvre\u003C\u002Fh2\u003E\u003Chr\u003E\u003Cp\u003ECommençons notre application par un écran d'inscription où l'utilisateur peut saisir ses coordonnées. Lorsqu'un utilisateur s'inscrit avec succès, nous pouvons l'authentifier avec notre fournisseur d'authentification.\u003C\u002Fp\u003E\u003Cfigure class=\"kg-card kg-image-card\"\u003E\u003Cimg src=\"https:\u002F\u002Fblog.seald.io\u002Fcontent\u002Fimages\u002F2023\u002F08\u002Fimage-14.png\" class=\"kg-image\" alt loading=\"lazy\" width=\"450\" height=\"974\"\u003E\u003C\u002Ffigure\u003E\u003Cp\u003ELe fournisseur d'authentification renvoie un code JWT qui peut être utilisé dans l'ensemble de l'application.\u003C\u002Fp\u003E\u003Cpre\u003E\u003Ccode class=\"language-json\"\u003E{  \"accessToken\":  \"eyJ2ZXIiOiIxLjAiLCJraWQiOiIzYWMxMTjYwZi0yMzhm...\"}\n\u003C\u002Fcode\u003E\u003C\u002Fpre\u003E\u003Cp\u003ENous souhaitons connecter l'utilisateur aux serveurs GetStream, et nous devons donc récupérer un jeton JWT auprès de GetStream. Un point de terminaison de notre API de messagerie s'en chargera. Utilisez l'ID utilisateur de votre fournisseur d'authentification pour créer un jeton auprès de GetStream.\u003C\u002Fp\u003E\u003Cpre\u003E\u003Ccode\u003Eimport { StreamChat } from 'stream-chat';\nconst serverClient = StreamChat.getInstance(STREAM_KEY, STREAM_SECRET);\n\nexport async function getMessagingToken(id: string) {\n  return serverClient.createToken(id);\n}\u003C\u002Fcode\u003E\u003C\u002Fpre\u003E\u003Cp\u003ENous allons stocker ce jeton de messagerie dans notre application react-native. Nous utilisons pour cela \u003Ca href=\"https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002Fzustand?ref=blog.seald.io\"\u003EZustand\u003C\u002Fa\u003E ❤️. En utilisant ce jeton, nous sommes maintenant en mesure de connecter un utilisateur à notre client GetStream.\u003C\u002Fp\u003E\u003Cfigure class=\"kg-card kg-code-card\"\u003E\u003Cpre\u003E\u003Ccode class=\"language-typescript\"\u003Econst client = StreamChat.getInstance(config.stream.apiKey);\n\n const init = useCallback(async () =&gt; {\n    try {\n      \u002F\u002F First disconnect any user that was still connected.\n      await client.disconnectUser();\n      await client.connectUser(\n        {\n          id: connectedUserId,\n        },\n        \u002F\u002F Use the JWT token received from our messaging API endpoint.\n        messagingToken.accessToken,\n      );\n\n      logger.verbose('ChatClient initialized');\n    } catch (error) {\n      logException(error);\n    }\n  }, [messagingToken, connectedUserId, client]);\u003C\u002Fcode\u003E\u003C\u002Fpre\u003E\u003Cfigcaption\u003EWe call this init function inside our ChatProvider that's wrapping our screens.\u003C\u002Ffigcaption\u003E\u003C\u002Ffigure\u003E\u003Cp\u003EPassons à l'étape suivante de notre processus d'intégration. Nous devons maintenant initialiser notre 2FA avec Seald. Nous avons créé un écran où l'utilisateur peut entrer son numéro de téléphone.\u003C\u002Fp\u003E\u003Cfigure class=\"kg-card kg-image-card\"\u003E\u003Cimg src=\"https:\u002F\u002Fblog.seald.io\u002Fcontent\u002Fimages\u002F2023\u002F08\u002Fimage-4.png\" class=\"kg-image\" alt loading=\"lazy\" width=\"450\" height=\"974\"\u003E\u003C\u002Ffigure\u003E\u003Cp\u003ELorsqu'un utilisateur saisit son numéro de téléphone, nous devons envoyer un \u003Cem\u003Echallenge\u003C\u002Fem\u003E que l'utilisateur peut saisir sur l'écran suivant. Nous avons créé un hook personnalisé \u003Ccode\u003EuseTwoFactorAuth\u003C\u002Fcode\u003E pour gérer la configuration de 2FA.\u003Cbr\u003E\u003Cbr\u003EPour effectuer les appels à l'API, nous utilisons react-query. Je ne vais pas me plonger dans chaque hook personnalisé, les 3 hooks ci-dessous récupèrent des données avec react-query à partir de nos points d'API.\u003C\u002Fp\u003E\u003Cpre\u003E\u003Ccode class=\"language-typescript\"\u003Econst { signup, isLoading } = useSignupSeald();\nconst { fetchMe, isLoading: isLoadingFetchMe } = useMeSeald();\nconst { sendChallenge, isLoading: isLoadingSendChallenge } = useSendChallenge();\u003C\u002Fcode\u003E\u003C\u002Fpre\u003E\u003Cp\u003ELorsqu'un utilisateur n'existe pas encore, nous appelons le point d'API \u003Ccode\u003Esignup\u003C\u002Fcode\u003E. Ce point d'API s'assurera que l'utilisateur est sauvegardé dans notre base de données postgreSQL et qu'une clé \u003Ccode\u003ETwoManRuleKey\u003C\u002Fcode\u003E est créée et stockée dans notre base de données. Pour en savoir plus sur la protection en \u003Cem\u003E2-man-rule\u003C\u002Fem\u003E, vous pouvez consulter la \u003Ca href=\"https:\u002F\u002Fdocs.seald.io\u002Fen\u002Fsdk\u002Fexample\u002F2-man-rule.html?ref=blog.seald.io#explanation\"\u003Edocumentation\u003C\u002Fa\u003E.\u003C\u002Fp\u003E\u003Cpre\u003E\u003Ccode class=\"language-typescript\"\u003E  const setup2FA = async (phoneNumber: string) =&gt; {\n    let user: OnboardedUser;\n\n    try {\n      \u002F\u002F The messaging API will be called to fetch an existing seald user, this is needed because the login will also execute this setup2FA hook.\n      user = await fetchMe();\n      \u002F\u002F It's possible that the user early killed the application while the signup was still busy. If we were not able to\n      \u002F\u002F store an activation key, we need to signup the user again to receive one needed for the initiation of the identity.\n      if (!user.activationKey) {\n        user = await signup();\n      }\n      \u002F\u002F eslint-disable-next-line @typescript-eslint\u002Fno-explicit-any\n    } catch (error: any) {\n      \u002F\u002F User does not exist\n      if (error?.error?.type === MessagingApiErrorType.USER_NOT_FOUND) {\n        user = await signup();\n      }\n    }\n  };\u003C\u002Fcode\u003E\u003C\u002Fpre\u003E\u003Cp\u003EPour que Seald puisse fonctionner correctement, nous devons générer un jeton de licence utilisateur dans notre backend. Voir la \u003Ca href=\"https:\u002F\u002Fdocs.seald.io\u002Fen\u002Fsdk\u002Fexample\u002Fuser-licence-token.html?ref=blog.seald.io#licence-token-generation-function\"\u003Edocumentation\u003C\u002Fa\u003E pour plus d'informations sur la manière de procéder. Chaque fois que le point d'API permettant de récupérer l'utilisateur ou de l'inscrire est appelé, un jeton de licence est généré et renvoyé par notre API.\u003Cbr\u003E\u003Cbr\u003ELorsqu'un utilisateur existant se reconnecte, le point d'API \u003Ccode\u003EfetchMe\u003C\u002Fcode\u003E renvoie la réponse suivante :\u003C\u002Fp\u003E\u003Cpre\u003E\u003Ccode class=\"language-json\"\u003E{\n   \"id\":\"0015r00000OxGgIAAV\",\n   \"isEnrolled\":true,\n   \"sealdId\":\"TESTING_0015r00000OxGgIAAV\",\n   \"twoManRuleKey\":\"VCl2Z0U+LYZ6Fq2rjm40PFrYWlrLDIsSRgGufKo9wJGlxDAU+5mUwji21g2G86GzN3dLKsrdWmYbPZn0QTGa9g==\"\n}\u003C\u002Fcode\u003E\u003C\u002Fpre\u003E\u003Cp\u003ELorsqu'un nouvel utilisateur est créé lors de l'inscription, la réponse du point d'API \u003Ccode\u003Esignup\u003C\u002Fcode\u003E est la suivante :\u003C\u002Fp\u003E\u003Cpre\u003E\u003Ccode class=\"language-json\"\u003E{\n   \"activationKey\":\"dbbb72c5-b2c5-47db-ad4c-5dfec91918df:5b1f82d5f3cb073c0103a4aa55bdd900777a4b3b4b89b99d906af533f3358a6e:7f24176eff547227984710ac5b2d858b3a78af509225f5b6cdc41197254dd81a02b16d893b176ffd70c952b87c4ba95a1f98b9f0bc3d0926f117e832fa45a9f3\",\n   \"id\":\"0015r00000Q0DQcAAN\",\n   \"isEnrolled\":false,\n   \"sealdId\":\"TESTING_0015r00000Q0DQcAAN\",\n   \"twoManRuleKey\":\"miSTd8ad7FrtvNSMee+uLDLgj+tYCPf9iENm3CzsytILSw5YuMI1TEOtEF7sU46f4qa6KVF+wb3tU1cdbLzTBA==\"\n}\u003C\u002Fcode\u003E\u003C\u002Fpre\u003E\u003Cp\u003EMaintenant que notre utilisateur est créé, nous pouvons envoyer le \u003Cem\u003Echallenge\u003C\u002Fem\u003E à l'utilisateur et initier l'identité Seald avec la clé d'activation.\u003C\u002Fp\u003E\u003Cpre\u003E\u003Ccode class=\"language-typescript\"\u003E if (user) {\n      \u002F\u002F The activation key is the user licence token from seald.\n      const { sealdId, activationKey } = user;\n\n      \u002F\u002F Create session in seald, send challenge to user.\n      await sendChallenge({ phoneNumber });\n\n      if (sealdId &amp;&amp; activationKey) {\n        await seald.initiateIdentity(sealdId, activationKey);\n      }\n    }\u003C\u002Fcode\u003E\u003C\u002Fpre\u003E\u003Cp\u003ELa commande \u003Ccode\u003EsendChallenge\u003C\u002Fcode\u003E appellera le point d'API qui met en œuvre l'envoi d'un \u003Cem\u003Echallenge\u003C\u002Fem\u003E conformément aux \u003Ca href=\"https:\u002F\u002Fdocs.seald.io\u002Fen\u002Fsdk\u002Fapi-ssks\u002F?ref=blog.seald.io#headers-of-the-requests\"\u003Espécifications\u003C\u002Fa\u003E. Seald créera une \"session\" et cette session sera requise lors de la sauvegarde ou de la récupération de notre identité Seald.\u003C\u002Fp\u003E\u003Cpre\u003E\u003Ccode class=\"language-json\"\u003E{\n   \"mustAuthenticate\": true,\n   \"twoManRuleKey\":\"miSTd8ad7FrtvNSMee+uLDLgj+tYCPf9iENm3CzsytILSw5YuMI1TEOtEF7sU46f4qa6KVF+wb3tU1cdbLzTBA==\",\n   \"twoManRuleSessionId\":\"c1c2b55f-f119-4a88-8a0d-e95512e3c667\"\n}\u003C\u002Fcode\u003E\u003C\u002Fpre\u003E\u003Cp\u003ENous pouvons maintenant passer au dernier écran de saisie du \u003Cem\u003Echallenge\u003C\u002Fem\u003E.\u003C\u002Fp\u003E\u003Cfigure class=\"kg-card kg-image-card\"\u003E\u003Cimg src=\"https:\u002F\u002Fblog.seald.io\u002Fcontent\u002Fimages\u002F2023\u002F08\u002Fimage-15.png\" class=\"kg-image\" alt loading=\"lazy\" width=\"450\" height=\"974\"\u003E\u003C\u002Ffigure\u003E\u003Cp\u003EUn \u003Cem\u003Ehook\u003C\u002Fem\u003E personnalisé sera appelé lorsque le \u003Cem\u003Echallenge\u003C\u002Fem\u003E a été saisi :\u003C\u002Fp\u003E\u003Cpre\u003E\u003Ccode class=\"language-typescript\"\u003Eexport const useSaveOrRetrieveSealdIdentity = () =&gt; {\n  const { updateUser } = useUpdateUser();\n  const { enroll } = useEnroll();\n\n  const sealdId = useStore(state =&gt; state.sealdId);\n  const twoManRuleSessionId = useStore(state =&gt; state.twoManRuleSessionId);\n  const twoManRuleKey = useStore(state =&gt; state.twoManRuleKey);\n  const mustAuthenticate = useStore(state =&gt; state.mustAuthenticate);\n  const userEnrolled = useStore(state =&gt; state.isEnrolled);\n\n  return {\n    saveOrRetrieveIdentity: async (phoneNumber: string, challenge: string) =&gt; {\n      \u002F\u002F Store phone number for later login purposes.\n      await updateUser({ c_recoveryPhoneNumber: phoneNumber });\n\n      \u002F\u002F If user was already enrolled, the identity already exists so we need to retrieve it.\n      \u002F\u002F SSKS will be called, and the identity will be retrieved.\n      if (userEnrolled) {\n        await seald.retrieveIdentity(\n          sealdId,\n          twoManRuleSessionId,\n          twoManRuleKey,\n          challenge,\n          phoneNumber,\n        );\n      } else {\n        await seald.saveIdentity(\n          phoneNumber,\n          twoManRuleKey,\n          sealdId,\n          twoManRuleSessionId,\n          mustAuthenticate,\n          challenge,\n        );\n\n        if (!userEnrolled) {\n          enroll();\n        }\n      }\n    },\n  };\n};\u003C\u002Fcode\u003E\u003C\u002Fpre\u003E\u003Cp\u003ENous avons maintenant établi une identité sécurisée et pouvons utiliser cette identité pour créer des sessions sécurisées entre deux utilisateurs 🙌\u003C\u002Fp\u003E\u003Cfigure class=\"kg-card kg-image-card\"\u003E\u003Cimg src=\"https:\u002F\u002Fc.tenor.com\u002FHJ0iSKwIG28AAAAC\u002Fyes-baby.gif\" class=\"kg-image\" alt loading=\"lazy\"\u003E\u003C\u002Ffigure\u003E\u003Chr\u003E\u003Ch2 id=\"cr%C3%A9er-une-messagerie-instantan%C3%A9e-s%C3%A9curis%C3%A9e\"\u003ECréer une messagerie instantanée sécurisée\u003C\u002Fh2\u003E\u003Chr\u003E\u003Cp\u003EGetStream.io nous offre des composants d'UI qui s'intègrent facilement dans notre application react-native. Nous avons modifié certains composants de GetStream, mais dans cet exemple, je ne montrerai que les choses nécessaires.\u003Cbr\u003E\u003Cbr\u003ELorsque vous créez un écran pour le chat, vous pouvez commencer par une implémentation de base comme celle-ci :\u003C\u002Fp\u003E\u003Cpre\u003E\u003Ccode class=\"language-tsx\"\u003E  import { Channel, Chat } from 'stream-chat-react-native';\n\n  const client = StreamChat.getInstance(config.stream.apiKey);\n  const channel = client.channel(\"messaging\", id, [\"member1\", \"member2\"]);\n\n  return (\n    &lt;Chat client={client}&gt;\n        &lt;Channel channel={channel} \u002F&gt; \u002F\u002F Channel you created between two members.\n    &lt;\u002FChat&gt;\n  );\n\u003C\u002Fcode\u003E\u003C\u002Fpre\u003E\u003Cp\u003ESans chiffrer\u002Fdéchiffrer les messages, la messagerie se présente comme suit :\u003C\u002Fp\u003E\u003Cfigure class=\"kg-card kg-image-card\"\u003E\u003Cimg src=\"https:\u002F\u002Fblog.seald.io\u002Fcontent\u002Fimages\u002F2023\u002F08\u002Fimage-16.png\" class=\"kg-image\" alt loading=\"lazy\" width=\"450\" height=\"974\"\u003E\u003C\u002Ffigure\u003E\u003Cp\u003EMais nous voulons pouvoir envoyer des messages chiffrés de bout-en-bout. Nous devons donc changer la méthode \u003Ccode\u003EdoSendMessageRequest\u003C\u002Fcode\u003E. Comme vous pouvez le voir, nous chiffrons notre message à l'aide d'une session de chiffrement. Cette session de chiffrement doit être créée lors de la création de votre conversation.\u003Cbr\u003E\u003Cbr\u003ELorsqu'une session de chiffrement est créée entre deux utilisateurs, nous stockons l'ID de la session dans les métadonnées de la conversation dans GetStream, afin qu'il puisse être réutilisé pour récupérer une session de chiffrement.\u003C\u002Fp\u003E\u003Cpre\u003E\u003Ccode class=\"language-tsx\"\u003Econst channel = client.channel(\"messaging\", id, [\"member1\", \"member2\"]);\n  await channel.watch();\n\n  let session: EncryptionSession;\n\n  if (channel.data?.session_id) {\n    session = await seald.retrieveEncryptionSession(channel.data.session_id);\n  } else {\n    session = await seald.createEncryptionSession(members.map(member =&gt; member.sealdId));\n    await channel.updatePartial({ set: { session_id: session.sessionId } });\n  }\n\n  const sendMessage = async (_channelId: string, message: Message) =&gt; {\n    const encryptedText = await encryptionSession.encryptMessage(message.text || '');\n    return channel.sendMessage({ ...message, text: encryptedText });\n  };\n  \n  return (\n    &lt;Chat\n      client={client}\n    &gt;\n        &lt;Channel\n          channel={channel}\n          doSendMessageRequest={sendMessage}\n        \u002F&gt;\n    &lt;\u002FChat&gt;\n  );\u003C\u002Fcode\u003E\u003C\u002Fpre\u003E\u003Cp\u003ESi nous envoyons maintenant un autre message, vous pouvez voir que le texte du message est maintenant chiffré et illisible.\u003C\u002Fp\u003E\u003Cfigure class=\"kg-card kg-image-card\"\u003E\u003Cimg src=\"https:\u002F\u002Fblog.seald.io\u002Fcontent\u002Fimages\u002F2023\u002F08\u002Fimage-17.png\" class=\"kg-image\" alt loading=\"lazy\" width=\"450\" height=\"974\"\u003E\u003C\u002Ffigure\u003E\u003Cp\u003ENous devons changer le composant \u003Ccode\u003EMessageText\u003C\u002Fcode\u003E pour afficher le message.\u003C\u002Fp\u003E\u003Cpre\u003E\u003Ccode class=\"language-tsx\"\u003Ereturn (\n    &lt;Chat\n      client={client}\n    &gt;\n        &lt;Channel\n          channel={channel}\n          doSendMessageRequest={sendMessage}\n          MessageText={(props: MessageTextProps) =&gt; (\n            &lt;DecryptedMessageText\n              {...props}\n              channel={channel}\n              session={encryptionSession}\n              onError={handleDecryptionError}\n              onFinished={handleDecryptionEnd}\n            \u002F&gt;\n          )}\n        \u002F&gt;\n    &lt;\u002FChat&gt;\n  );\u003C\u002Fcode\u003E\u003C\u002Fpre\u003E\u003Cp\u003ENotre composant \u003Ccode\u003EDecryptedMessageText\u003C\u002Fcode\u003E utilisera notre session de chiffrement pour déchiffrer le message.\u003C\u002Fp\u003E\u003Cpre\u003E\u003Ccode class=\"language-tsx\"\u003Eimport { useEffect, useRef, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport type { EncryptionSession } from '@seald-io\u002Fsdk\u002Flib\u002Fmain';\nimport type { MessageTextProps, MessageType as Message } from 'stream-chat-react-native';\n\nimport type { LocalChannel } from 'core\u002Fchat\u002Ftypes';\n\ninterface Props extends MessageTextProps {\n  channel: LocalChannel;\n  session: EncryptionSession;\n}\n\nconst decryptMessage = async (text: string, session: EncryptionSession) =&gt; {\n  try {\n    \u002F\u002F If we have  JSON, it can be decrypted.\n    JSON.parse(text);\n    try {\n      if (!session) {\n        throw new Error('EncryptionSession is undefined');\n      }\n      return await session.decryptMessage(text);\n    } catch (err) {\n      logException(err);\n      return false;\n    }\n  } catch (err) {\n    \u002F\u002F Otherwise it's just plain text\n    return text;\n  }\n};\n\nconst DecryptedMessageText = ({\n  channel,\n  session,\n  message,\n  renderText,\n  theme,\n  ...rest\n}: Props) =&gt; {\n  const { t } = useTranslation();\n  const decryptedMessage = useRef&lt;Message&gt;(message);\n\n  useEffect(() =&gt; {\n    const decrypt = async () =&gt; {\n      if (message.text) {\n        const text = await decryptMessage(message.text, session);\n        if (text === false) {\n          \u002F\u002F Handle errors\n          return;\n        }\n\n        decryptedMessage.current = {\n          ...message,\n          text,\n        };\n      }\n    };\n\n    decrypt();\n    \u002F\u002F eslint-disable-next-line react-hooks\u002Fexhaustive-deps\n  }, [message, session]);\n\n  return renderText({\n    ...rest,\n    message: decryptedMessage.current,\n  });\n};\n\nexport default DecryptedMessageText;\u003C\u002Fcode\u003E\u003C\u002Fpre\u003E\u003Cp\u003ENotre message est maintenant déchiffré et de nouveau visible pour les membres de la conversation.\u003C\u002Fp\u003E\u003Cfigure class=\"kg-card kg-image-card\"\u003E\u003Cimg src=\"https:\u002F\u002Fblog.seald.io\u002Fcontent\u002Fimages\u002F2023\u002F08\u002Fimage-24.png\" class=\"kg-image\" alt loading=\"lazy\" width=\"450\" height=\"974\"\u003E\u003C\u002Ffigure\u003E\u003Cp\u003ELorsque nous jetons un coup d'œil au tableau de bord de GetStream.io, nous pouvons également voir que nos messages ne sont pas lisibles, et qu'ils sont donc chiffrés de bout-en-bout 💪.\u003Cbr\u003E\u003C\u002Fp\u003E\u003Cfigure class=\"kg-card kg-image-card\"\u003E\u003Cimg src=\"https:\u002F\u002Fblog.seald.io\u002Fcontent\u002Fimages\u002F2023\u002F08\u002Fimage-25.png\" class=\"kg-image\" alt loading=\"lazy\" width=\"1247\" height=\"1101\" srcset=\"https:\u002F\u002Fblog.seald.io\u002Fcontent\u002Fimages\u002Fsize\u002Fw600\u002F2023\u002F08\u002Fimage-25.png 600w, https:\u002F\u002Fblog.seald.io\u002Fcontent\u002Fimages\u002Fsize\u002Fw1000\u002F2023\u002F08\u002Fimage-25.png 1000w, https:\u002F\u002Fblog.seald.io\u002Fcontent\u002Fimages\u002F2023\u002F08\u002Fimage-25.png 1247w\" sizes=\"(min-width: 720px) 720px\"\u003E\u003C\u002Ffigure\u003E\u003Chr\u003E\u003Ch2 id=\"conclusion\"\u003EConclusion\u003C\u002Fh2\u003E\u003Chr\u003E\u003Cfigure class=\"kg-card kg-image-card\"\u003E\u003Cimg src=\"https:\u002F\u002Fc.tenor.com\u002FmYI35XJyfloAAAAC\u002Fmicdrop-jonstewart.gif\" class=\"kg-image\" alt loading=\"lazy\"\u003E\u003C\u002Ffigure\u003E\u003Cp\u003EPs : vous utilisez PubNub plutôt que Stream ? \u003Ca href=\"https:\u002F\u002Fwww.seald.io\u002Ffr\u002Fblog\u002Fcomment-creer-un-chat-chiffre-de-bout-en-bout-avec-pubnub-et-seald?ref=blog.seald.io\"\u003EVoici un article qui explique commente intégrer Seald dans PubNub.\u003C\u002Fa\u003E\u003C\u002Fp\u003E",comment_id:d,feature_image:e,featured:f,visibility:"public",created_at:"2023-08-29T15:26:54.000+02:00",updated_at:"2023-10-25T00:47:43.000+02:00",published_at:"2023-08-29T17:23:23.000+02:00",custom_excerpt:a,codeinjection_head:"{\n  \"fr\": \"creer-une-messagerie-chiffree-de-bout-en-bout-avec-stream-et-seald\",\n  \"en\": \"creating-an-end-to-end-encrypted-chat-with-stream-and-seald\"\n}",codeinjection_foot:a,custom_template:a,canonical_url:"https:\u002F\u002Fdev.inthepocket.com\u002Fposts\u002F2022-02-15-creating-an-encrypted-chat-with-getstream-and-seald-io\u002F",authors:[{id:g,name:h,slug:i,profile_image:j,cover_image:a,bio:a,website:a,location:a,facebook:a,twitter:a,meta_title:a,meta_description:a,url:k}],tags:[{id:"63344e447f645d00017cb6ea",name:"#fr",slug:"hash-fr",description:a,feature_image:a,visibility:"internal",og_image:a,og_title:a,og_description:a,twitter_image:a,twitter_title:a,twitter_description:a,meta_title:a,meta_description:a,codeinjection_head:a,codeinjection_foot:a,canonical_url:a,accent_color:a,url:"https:\u002F\u002Fblog.seald.io\u002F404\u002F"}],primary_author:{id:g,name:h,slug:i,profile_image:j,cover_image:a,bio:a,website:a,location:a,facebook:a,twitter:a,meta_title:a,meta_description:a,url:k},primary_tag:a,url:"https:\u002F\u002Fblog.seald.io\u002Fcreer-une-messagerie-chiffree-de-bout-en-bout-avec-stream-et-seald\u002F",excerpt:"L'article original a été écrit par Sander Goossens, développeur chez In The Pocket, vous pouvez le trouver ici : https:\u002F\u002Fdev.inthepocket.com\u002Fposts\u002F2022-02-15-creating-an-encrypted-chat-with-getstream-and-seald-io\u002F\n\nSander Goossens : Récemment, un client est venu nous voir pour nous demander une solution de messagerie avec une confidentialité absolue sur les messages. Après quelques recherches, nous avons rapidement trouvé une solution combinant GetStream.io et Seald.io.\n\nGetStream.io offre une m",reading_time:8,access:true,comments:f,og_image:a,og_title:a,og_description:a,twitter_image:a,twitter_title:a,twitter_description:a,meta_title:a,meta_description:"Après quelques recherches, nous avons trouvé la combinaison de Stream et de Seald pour créer une solution de messagerie chiffrée de bout-en-bout.",email_subject:a,frontmatter:a,feature_image_alt:a,feature_image_caption:a,responsiveImages:[{srcset:"https:\u002F\u002Fblog.seald.io\u002Fcontent\u002Fimages\u002Fsize\u002Fw2000\u002F2023\u002F08\u002FStreamfrxSeald.png",media:"(min-width: 1000px)"},{srcset:"https:\u002F\u002Fblog.seald.io\u002Fcontent\u002Fimages\u002Fsize\u002Fw1000\u002F2023\u002F08\u002FStreamfrxSeald.png",media:"(min-width: 600px)"},{srcset:e,media:"(min-width: 300px)"}]},langs:[{lang:"fr",slug:c,href:b,url:b},{lang:"en",slug:"creating-an-end-to-end-encrypted-chat-with-stream-and-seald",href:l,url:l}],url:b,origin:"https:\u002F\u002Fwww.seald.io",_img:{}}],fetch:{},mutations:[]}}(null,"https:\u002F\u002Fwww.seald.io\u002Ffr\u002Fblog\u002Fcreer-une-messagerie-chiffree-de-bout-en-bout-avec-stream-et-seald","creer-une-messagerie-chiffree-de-bout-en-bout-avec-stream-et-seald","64edf21eb9df6d00010a1a23","https:\u002F\u002Fblog.seald.io\u002Fcontent\u002Fimages\u002Fsize\u002Fw600\u002F2023\u002F08\u002FStreamfrxSeald.png",false,"63344e437f645d00017cb6cd","Maxime Huber","maxime","https:\u002F\u002Fblog.seald.io\u002Fcontent\u002Fimages\u002F2019\u002F03\u002Fmaxime-huber.jpg","https:\u002F\u002Fblog.seald.io\u002Fauthor\u002Fmaxime\u002F","https:\u002F\u002Fwww.seald.io\u002Fblog\u002Fcreating-an-end-to-end-encrypted-chat-with-stream-and-seald")));