Zbuduj szyfrowany czat od początku do końca za pomocą Seald i PubNub

PubNub Developer Relations - Mar 18 - - Dev Community

Ten artykuł został napisany przez osobę trzecią, seald, i przedstawia alternatywę dla wbudowanego szyfrowania wiadomości na poziomie PubNub . Został on pierwotnie opublikowany na Hackernoon.


Dziś dowiemy się, jak zbudowaćszyfrowany czat end-to-end za pomocą Pubnub i seald SDK.

W pełni działający przykład użycia PubNub i Seald można znaleźć tutaj: https: //github.com/seald/pubnub-example-project

Czym jest Pubnub?

PubNub to usługa komunikacji w czasie rzeczywistym, którą można zintegrować z większością aplikacji. Niezawodna i skalowalna, może być łatwo zintegrowana z najpopularniejszymi frameworkami.

Co to jest Seald?

Seald.io oferuje SDK, który pozwala na szyfrowanie end-to-end, z zaawansowanymi funkcjami zarządzania, bez wcześniejszej wiedzy kryptograficznej. Ten SDK można zintegrować z aplikacjami internetowymi, backendowymi, mobilnymi lub desktopowymi.

Przegląd zawartości

  • Dlaczego warto korzystać z szyfrowania end-to-end?

  • Dlaczego warto używać Seald.io zamiast haka szyfrującego PubNub?

  • Cele 🏆

  • Wdrożenie 🧠

  • Dodanie szyfrowania end-to-end za pomocą Seald 🔒💬

  • Podsumowanie ✅

Dlaczego warto używać szyfrowania end-to-end? 🔒

Szyfrowanie typu end-to-end oferuje najwyższy poziom prywatności i bezpieczeństwa. Umożliwia szyfrowanie wrażliwych danych natychmiast po ich zebraniu. Wczesne szyfrowanie zmniejsza powierzchnię ataku aplikacji. Kolejną zaletą jest to, że możesz precyzyjnie zarządzać tym, kto może uzyskać dostęp do danych. Będzie to również chronić, gdy nie jest to w twoim zakresie, na przykład usługi innych firm.

Szyfrowanie typu end-to-end pozwala zachować kontrolę przez cały czas, gdy dane są przesyłane, gdy są w spoczynku, a nawet gdy nie są w zasięgu ręki. W ten sposób oferuje znacznie szerszą ochronę niż inne technologie szyfrowania (TLS, szyfrowanie pełnodyskowe, ...).

Za każdym razem, gdy masz do czynienia z przypadkiem, w którym zgodność jest ważna (RODO, HIPAA, SOC-2, ...) lub gdy masz wrażliwe dane (medyczne, obronne, ...), szyfrowanie end-to-end jest koniecznością. Ale nawet w przypadku bardziej powszechnych danych jest to dobra praktyka. Naruszenie bezpieczeństwa danych jest niszczycielskim wydarzeniem, które staje się coraz częstsze.

Dlaczego warto używać Seald.io zamiast haka szyfrującego PubNub? 👀

PubNub SDK oferuje prosty hak szyfrujący, wykorzystujący argument cipherKey podczas tworzenia instancji SDK. Zapewni to, że wszystkie przesłane wiadomości zostaną zaszyfrowane przed wysłaniem. Jednak zarządzanie kluczami należy wykonać samodzielnie.

Luki w zabezpieczeniach rzadko wynikają z samego szyfrowania, ale najczęściej z wycieku kluczy przez luki w modelu bezpieczeństwa.

Seald.io proponuje solidny model bezpieczeństwa, certyfikowany przez ANSSI, z kontrolą zarządzania dostępem w czasie rzeczywistym, odwoływaniem i odzyskiwaniem użytkowników, 2FA i nie tylko .

Cele 🏆

Ten artykuł wyjaśnia, jak krok po kroku zintegrować Seald z PubNub, aby zabezpieczyć czat za pomocą szyfrowania end-to-end. Zbudujemy przykładową aplikację do przesyłania wiadomości z następującymi funkcjami:

  • Czaty indywidualne i grupowe.

  • Każdy użytkownik ma dedykowany pokój czatu z każdym innym użytkownikiem.

  • Każdy może utworzyć czat grupowy z wieloma innymi użytkownikami.

  • Szyfrowanie end-to-end każdej wysyłanej wiadomości i pliku.

  • Zarządzanie dostępem do czatów w czasie rzeczywistym.

Wdrożenie 🧠

Założenie konta PubNub 👤

Aby rozpocząć, będziesz potrzebować konta PubNub. Możesz zarejestrować się tutaj. Po zalogowaniu się na pulpicie nawigacyjnym powinieneś zobaczyć, że została utworzona aplikacja demonstracyjna z demonstracyjnym zestawem kluczy:

Wybierz*demonstracyjny* zestaw kluczy i przewiń do zakładki konfiguracji. Dla naszego demo musimy aktywować uprawnienia Files i Objects. W przypadku uprawnienia Object użyjemy następujących zdarzeń: User Metadata Events, Channel Metadata Events iMembershipEvents.

Po utworzeniu i skonfigurowaniu zestawu kluczy musimy skopiować go do naszego frontendu.

Utwórzmy plik JSON w folderze src/ o nazwie settings.json. Będziemy używać tego pliku dla wszystkich kluczy API, których będziemy potrzebować. Zaczynamy od zestawu kluczy PubNub:

{
  "PUBNUB_PUB_KEY": "pub-c-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
  "PUBNUB_SUB_KEY": "sub-c-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
}
Enter fullscreen mode Exit fullscreen mode

Tworzenie podstawowego czatu przy użyciu PubNub 💬

Będziemy używać PubNub do prawie każdego zadania backendu. Nasz backend będzie obsługiwał tylko rejestrację / logowanie użytkowników i używał minimalistycznego modelu użytkownika z tylko identyfikatorem, nazwą i adresem e-mail.

Z przodu potrzebujemy małego interfejsu uwierzytelniania:

Gdy użytkownik ma już konto, pierwszą rzeczą, której potrzebuje, jest instancja PubNub SDK.

Aby zidentyfikować użytkownika w Pub nub, musimy podać identyfikator UUID.

Aby zachować prostotę, użyjemy tego samego identyfikatora, co w naszym backendzie:

/* frontend/src/App.js */
import settings from './settings.json' // our settings file for API keys
/*
...
*/
const pubnub = new PubNub({
    publishKey: settings.PUBNUB_PUB_KEY,
    subscribeKey: settings.PUBNUB_SUB_KEY,
    uuid: currentUser.id
})
Enter fullscreen mode Exit fullscreen mode

Aby nasz backend był tak prosty, jak to tylko możliwe, użyjemy metadanych użytkownika PubNub do wymiany informacji o użytkownikach.

Tuż po instancji SDK, po prostu wywołujemy funkcję PubNub setUUIDMetadata:

/* frontend/src/App.js */
await pubnub.objects.setUUIDMetadata({
  uuid: currentUser.id,
  data: {
    email: currentUser.emailAddress,
    name: currentUser.name
  }
})
Enter fullscreen mode Exit fullscreen mode

Pobieranie początkowego stanu aplikacji 🌱

Pierwszą rzeczą do zrobienia z PubNub jest pobranie wszystkich istniejących członków i przechowywanie ich w naszym lokalnym magazynie danych:

/* frontend/src/App.js */
const existingMembers = await pubnub.objects.getAllUUIDMetadata()
dispatch({
  type: SET_USERS,
  payload: {
    users: existingMembers.data.map(u => new User({ id: u.id, name: u.name, emailAddress: u.email }))
  }
})
Enter fullscreen mode Exit fullscreen mode

Każdy pokój rozmów będzie odpowiadał kanałowi PubNub. Dodamy również pewne metadane do każdego kanału:

  • ownerId: Identyfikator użytkownika, który utworzył pokój.

  • one2one: Wartość logiczna rozróżniająca pokoje do bezpośredniej komunikacji i pokoje grupowe.

  • archived: Wartość logiczna, aby ukryć usunięty pokój grupowy.

Metadane ownerId zostaną użyte później podczas dodawania Seald SDK. PubNub nie ma koncepcji własności, ale Seald tak. Zdefiniuje on, kto może dodawać lub usuwać użytkowników z kanału. Zasadniczo definiuje administratora grupy.

Zaczniemy od pobrania istniejących pokojów rozmów. Będziemy również potrzebować metadanych pokoju, więc musimy dołączyć niestandardowe pola. Następnie musimy odfiltrować zarchiwizowane pokoje i wysłać wszystko do naszego magazynu danych.

Na koniec subskrybujemy kanał PubNub powiązany z pokojem, dzięki czemu będziemy otrzymywać nowe wiadomości:

/* frontend/src/App.js */
// Retrieve rooms of which we are members
const memberships = await pubnub.objects.getMemberships({
  include: {
    customChannelFields: true
  }
})
const knownRooms = []
// For each room, retrieve room members
for (const room of memberships.data.filter(r => !r.channel.custom.archived)) {
  const roomMembers = await pubnub.objects.getChannelMembers({ channel: room.channel.id })
  knownRooms.push(new Room({
    id: room.channel.id,
    name: room.channel.name,
    users: roomMembers.data.map(u => u.uuid.id),
    ownerId: room.channel.custom.ownerId,
    one2one: room.channel.custom.one2one
  }))
}
// Store rooms in our data store
dispatch({
  type: SET_ROOMS,
  payload: {
    rooms: knownRooms
  }
})
// Subscribe to channels to get new messages
pubnub.subscribe({ channels: knownRooms.map(r => r.id) })
Enter fullscreen mode Exit fullscreen mode

Teraz pobraliśmy wszystkie pokoje, w których się znajdujemy. Potrzebujemy jeszcze jednej rzeczy, aby zakończyć inicjalizację aplikacji: upewnić się, że mamy pokój one2one z każdym innym członkiem, w tym z nowo zarejestrowanymi.

Dla każdego nowo znalezionego użytkownika utworzymy nowy pokój i wyślemy wiadomość powitalną.

Następnie ustawimy metadane pokoju i zasubskrybujemy go:

/* frontend/src/App.js */
// Ensure that we have a one2one room with everyone
const one2oneRooms = knownRooms.filter(r => r.one2one)
for (const m of existingMembers.data.filter(u => u.id!== currentUser.id)) {
    if (!one2oneRooms.find(r => r.users.includes(m.id))) {
      // New user found: generating a new one2one room
      const newRoomId = PubNub.generateUUID()
      const newRoom = new Room({
            id: newRoomId,
            users: [currentUser.id, m.id],
            one2one: true,
            name: m.name,
            ownerId: currentUser.id
          })
      // Add the new room to our local list
      dispatch({
        type: EDIT_OR_ADD_ROOM,
        payload: {
          room: new Room({
            id: newRoomId,
            users: [currentUser.id, m.id],
            one2one: true,
            name: m.name, ownerId: currentUser.id
          })
        }
      })
      // Publish a "Hello" message in the room
      await pubnub.publish({
        channel: newRoomId,
        message: {
          type: 'message',
          data: (await sealdSession.encryptMessage('Hello 👋'))
        }
      })
      // Subscribe to the new room
      pubnub.subscribe({ channels: [newRoomId] })
      await pubnub.objects.setChannelMetadata({
        channel: newRoomId,
        data: {
          name: 'one2one',
          custom: {
            one2one: true,
            ownerId: currentUser.id,
          },
        }
      })
      await pubnub.objects.setChannelMembers({
        channel: newRoomId,
        uuids: [currentUser.id, m.id]
      })
    }
}
Enter fullscreen mode Exit fullscreen mode

Gdy to wszystko zostanie zrobione, nasz początkowy stan aplikacji jest w pełni zdefiniowany. Musimy go jednak aktualizować.

Można to zrobić po prostu dodając detektor zdarzeń dla zdarzeń członkostwa:

/* frontend/src/App.js */
pubnub.addListener({
  objects: async function(objectEvent) {
    if (objectEvent.message.type === 'membership') {
      if (objectEvent.message.event === 'delete') { // User is removed from a room
        /*
        Removing the room from store...
        */
      }
      if (objectEvent.message.event === 'set') { // User is added to a room
        const metadata = await pubnub.objects.getChannelMetadata({ channel: objectEvent.message.data.channel.id })
        const roomMembers = (await pubnub.objects.getChannelMembers({ channel: objectEvent.message.data.channel.id })).data.map(u => u.uuid.id)
        /*
        Adding new room to store + subscribing to new room channel...
        */
      }
    }
  }
})
pubnub.subscribe({ channels: [currentUser.id] }) // channel on which events concerning the current user are published
Enter fullscreen mode Exit fullscreen mode

Możemy teraz przyjrzeć się samemu czatowi one2one. Następnie zajmiemy się pokojami grupowymi.

Odbieranie i wysyłanie wiadomości w pokoju czatu 📩

W pliku chat.js będziemy mieli całą logikę do wyświetlania wiadomości z pokoju czatu.

Aby zainicjować ten pokój, jedyną rzeczą, którą musimy zrobić, jest pobranie wszystkich wcześniej istniejących wiadomości.

Można to zrobić po prostu znając identyfikator pokoju:

/* frontend/src/components/Chat.jsx */
const fetchedMessages = (await pubnub.fetchMessages({ channels: [currentRoomId] })).channels[currentRoomId]
Enter fullscreen mode Exit fullscreen mode

Możemy zasubskrybować kanał, aby otrzymywać nowe wiadomości i dodać słuchacza, aby wyświetlać je w czasie rzeczywistym:

/* frontend/src/components/Chat.jsx */
pubnub.addListener({ message: handleReceiveMessage })
pubnub.subscribe({ channels: [currentRoomId] })
Enter fullscreen mode Exit fullscreen mode

Aby wysłać wiadomość, musimy po prostu opublikować ją na kanale:

/* frontend/src/components/Chat.jsx */
const handleSubmitMessage = async e => {
  /* Some checks that the room is in a correct state... */
  await pubnub.publish({
    channel: state.room.id,
    message: {
      type: 'message',
      data: state.message
    }
  })
}
Enter fullscreen mode Exit fullscreen mode

Aby wysłać plik, najpierw prześlemy go do PubNub. Następnie pobierzemy URI przesłanego pliku i opublikujemy go jako wiadomość na czacie:

/* frontend/src/components/UploadButton.jsx */
// Upload Encrypted file
const uploadData = await pubnub.sendFile({
  channel: room.id,
  file: myFile,
  storeInHistory: false
})
const fileURL = await pubnub.getFileUrl({ id: uploadData.id, name: uploadData.name, channel: room.id })
await pubnub.publish({
  channel: state.room.id,
  message: {
    type: 'file',
    url: fileURL,
    fileName: await sealdSession.encryptMessage(selectedFiles[0].name)
  }
})
Enter fullscreen mode Exit fullscreen mode

Zarządzanie czatem grupowym 👨‍👩‍👦‍👦

Aby tworzyć grupy i zarządzać nimi, będziemy potrzebować interfejsu do wybierania użytkowników:

Po wybraniu*członków grupy* możemy utworzyć kanał PubNub dla naszego pokoju, a następnie ustawić metadane i członkostwo dla kanału. Kod jest bardzo podobny do tego, co robi się dla pokoi one2one, więc nie będziemy go tutaj powtarzać.

Mamy teraz pełną aplikację czatu. Dodajmy szyfrowanie end-to-end dla każdej wiadomości!

Dodawanie szyfrowania end-to-end z Seald 🔒💬

Skonfiguruj konto Seald 👤

Aby rozpocząć korzystanie z Seald, utwórz bezpłatne konto próbne tutaj

Po wylądowaniu na pulpicie nawigacyjnym Seald wyświetlanych jest kilka adresów URL i tokenów API.

Pobierz następujące elementy:

  • appId

  • apiURL

  • keyStorageURL

Dodamy te klucze do naszego pliku settings.json:

{
  "PUBNUB_PUB_KEY": "pub-c-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
  "PUBNUB_SUB_KEY": "sub-c-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
  "SEALD_APP_ID": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
  "SEALD_API_URL": "https://api.staging-0.seald.io",
  "SEALD_KEYSTORAGE_URL": "https://ssks.staging-0.seald.io"
}
Enter fullscreen mode Exit fullscreen mode

Aby móc korzystać z Seald SDK, każdy użytkownik potrzebuje licencji JWT podczas rejestracji.

Te JWT muszą zostać wygenerowane na zapleczu przy użyciu tajnego i tajnego identyfikatora.

Ze strony docelowej pulpitu nawigacyjnego skopiuj sekret JWT i powiązany z nim identyfikator w backend/settings.json:

{
  "SEALD_JWT_SECRET_ID": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
  "SEALD_JWT_SECRET": "XXXXXXXXXXXXXXXXXXXXXXXX"
}
Enter fullscreen mode Exit fullscreen mode

Podczas wywołania API rejestracji wygenerujemy JWT licencji Seald i zwrócimy go z powrotem:

/* backend/routes/account.js */
const token = new SignJWT({
  iss: settings.SEALD_JWT_SECRET_ID,
  jti: uuidv4(), /// Random string with enough entropy to never repeat.
  iat: Math.floor(Date.now() / 1000), // JWT valid only for 10 minutes. `Date.now()` returns the  in milliseconds, this needs it in seconds.
  scopes: [3], // PERMISSION_JOIN_TEAM
  join_team: true
})
  .setProtectedHeader({ alg: 'HS256' })
const signupJWT = await token.sign(Buffer.from(settings.SEALD_JWT_SECRET, 'ascii'))
Enter fullscreen mode Exit fullscreen mode

Więcej informacji na ten temat można znaleźć w naszym artykule na temat JWT.

Następnie musimy zainstalować Seald SDK.

Musimy również zainstalować wtyczkę do identyfikacji użytkowników na serwerze Seald. W tym celu użyjemy pakietu sdk-plugin-ssks-password.

Wtyczka ta pozwala na proste uwierzytelnianie hasłem naszych użytkowników:

npm i -S @seald-io/sdk @seald-io/sdk-plugin-ssks-password
Enter fullscreen mode Exit fullscreen mode

Instantiating the Seald SDK 💡

Następnie utworzymy plik seald.js. W tym pliku zaczniemy od utworzenia funkcji do instancjonowania Seald SDK:

/* frontend/src/services/seald.js */
import SealdSDK from '@seald-io/sdk-web'
import SealdSDKPluginSSKSPassword from '@seald-io/sdk-plugin-ssks-password'
import settings from './settings.json'
let sealdSDKInstance = null
const instantiateSealdSDK = async () => {
  sealdSDKInstance = SealdSDK({
    appId: settings.SEALD_APP_ID,
    apiURL: settings.SEALD_API_URL,
    plugins: [SealdSDKPluginSSKSPassword(settings.SEALD_KEYSTORAGE_URL)]
  })
}
Enter fullscreen mode Exit fullscreen mode

Tworzenie i pobieranie tożsamości Seald 🔑

W seald .js dodamy również dwie funkcje: jedną do tworzenia tożsamości i jedną do jej pobierania. Aby utworzyć tożsamość, potrzebujemy również licencji JWT zwróconej podczas tworzenia konta:

/* frontend/src/services/seald.js */
export const createIdentity = async ({ userId, password, signupJWT }) => {
  await instantiateSealdSDK()
  await sealdSDKInstance.initiateIdentity({ signupJWT })
  await sealdSDKInstance.ssksPassword.saveIdentity({ userId, password })
}
export const retrieveIdentity = async ({ userId, password }) => {
  await instantiateSealdSDK()
  await sealdSDKInstance.ssksPassword.retrieveIdentity({ userId, password })
}
Enter fullscreen mode Exit fullscreen mode

Podczas naszych przepływów rejestracji i logowania wystarczy wywołać te funkcje po zalogowaniu się użytkownika.

W tym momencie, za każdym razem, gdy nasz użytkownik jest połączony, ma działający Seald SDK, gotowy do szyfrowania i deszyfrowania!

Ostrzeżenie: Aby zapewnić odpowiednie bezpieczeństwo, hasło powinno zostać wstępnie zaszyfrowane przed wysłaniem do serwera uwierzytelniającego. Więcej szczegółów na ten temat można znaleźć w akapicie dotyczącym uwierzytelniania haseł w naszej dokumentacji.

Rozpocznij szyfrowanie i odszyfrowywanie wiadomości 🔒🔓

Każdy pokój rozmów będzie powiązany z encryptionSession w Seald SDK.

Za każdym razem, gdy tworzymy pokój rozmów, musimy po prostu dodać jedną linię, aby utworzyć sesję szyfrowania, a następnie jej użyć:

/* frontend/src/App.js */
// Create a Seald session
const sealdSession = await getSealdSDKInstance().createEncryptionSession(
  { userIds: [currentUser.id, m.id] },
  { metadata: newRoomId }
)
// Publish a "Hello" message in the room
await pubnub.publish({
  channel: newRoomId,
  message: {
    type: 'message',
    data: (await sealdSession.encryptMessage('Hello 👋'))
  }
})
Enter fullscreen mode Exit fullscreen mode

Zauważ, że nasz użytkownik jest domyślnie uwzględniony jako odbiorca encryptionSession .

Uzyskując dostęp do pokoju, musimy uzyskać odpowiednią encryptionSession. Można ją pobrać z dowolnej zaszyfrowanej wiadomości lub pliku. Gdy już ją uzyskamy, zachowamy ją w referencji do komponentu.

Następnie możemy po prostu użyć funkcji session.encryptMessage, session.encryptFile, session.decryptMessage i session.decryptFile.

Zacznijmy od wiadomości. Aby wysłać wiadomość:

/* frontend/src/components/Chat.js */
const handleSubmitMessage = async m => {
  /* Some validation that we are in a valid room... */
  // if there is no encryption session set in cache yet, create one
  // (should never happen, as a "Hello" is sent on room creation)
  if (!sealdSessionRef.current) {
    sealdSessionRef.current = await getSealdSDKInstance().createEncryptionSession(
      { userIds: state.room.users },
      { metadata: state.room.id }
    )
  }
  // use the session to encrypt the message we are trying to send
  const encryptedMessage = await sealdSessionRef.current.encryptMessage(state.message)
  // publish the encrypted message to pubnub
  await pubnub.publish({
    channel: state.room.id,
    message: {
      type: 'message',
      data: encryptedMessage
    }
  })
  /* Some cleanup... */
}
Enter fullscreen mode Exit fullscreen mode

I kiedy otrzymujemy wiadomość:

/* frontend/src/components/Chat.js */
const decryptMessage = async m => {
  /* Filter out files... */
  let encryptedData = m.message.data
  if (!sealdSessionRef.current) { // no encryption session set in cache yet
    // we try to get it by parsing the current message
    sealdSessionRef.current = await getSealdSDKInstance().retrieveEncryptionSession({ encryptedMessage: encryptedData })
    // now that we have a session loaded, let's decrypt
  }
  const decryptedData = await sealdSessionRef.current.decryptMessage(encryptedData)
  // we have successfully decrypted the message
  return {
    ...m,
    uuid: m.uuid || m.publisher,
    value: decryptedData
  }
  /* Some error handling... */
}
/* Other stuff... */
const handleReceiveMessage = async m => {
  const decryptedMessage = await decryptMessage(m)
  setState(draft => {
    draft.messages = [...draft.messages, decryptedMessage]
  })
}
Enter fullscreen mode Exit fullscreen mode

Używamy również funkcji decryptMessage, aby odszyfrować wszystkie wiadomości już znajdujące się w sesji podczas otwierania pokoju:

/* frontend/src/components/Chat.js */
const fetchedMessages = (await pubnub.fetchMessages({ channels: [currentRoomId] })).channels[currentRoomId]
const clearMessages = fetchedMessages ? await Promise.all(fetchedMessages.map(decryptMessage)) : []
Enter fullscreen mode Exit fullscreen mode

A teraz pliki. Aby przesłać plik:

/* frontend/src/components/UploadButton.js */
// Encrypt file
const encryptedBlob = await sealdSession.encryptFile(
  selectedFiles[0],
  selectedFiles[0].name,
  { fileSize: selectedFiles[0].size }
)
const encryptedFile = new File([encryptedBlob], selectedFiles[0].name)
// Upload Encrypted file
const uploadData = await pubnub.sendFile({
  channel: room.id,
  file: encryptedFile,
  storeInHistory: false
})
Enter fullscreen mode Exit fullscreen mode

I aby odszyfrować plik:

/* frontend/src/components/Message.js */
const onClick = async () => {
  if (state.data.type === 'file') {
    const response = await fetch(state.data.url)
    const encryptedBlob = await response.blob()
    const { data: clearBlob, filename } = await sealdSession.decryptFile(encryptedBlob)
    const href = window.URL.createObjectURL(clearBlob)
    /* Create an <a> element and simulate a click on it to download the created objectURL */
  }
}
Enter fullscreen mode Exit fullscreen mode

Zarządzanie członkami grupy 👨‍👩‍👦

Czaty grupowe również będą miały swoją encryptionSession. Za każdym razem, gdy tworzona jest grupa, musimy ją utworzyć:

/* frontend/src/components/ManageDialogRoom.js.js */
// To create the encryptionSession
const sealdSession = await getSealdSDKInstance().createEncryptionSession(
  { userIds: dialogRoom.selectedUsersId },
  { metadata: newRoomId }
)
Enter fullscreen mode Exit fullscreen mode

Następnie za każdym razem, gdy modyfikujemy członków grupy, będziemy musieli ich dodać lub usunąć:

/* frontend/src/components/ManageDialogRoom.js.js */
// we compare old and new members to figure out which ones were just added or removed
const usersToRemove = dialogRoom.room.users.filter(id => !dialogRoom.selectedUsersId.includes(id))
const usersToAdd = dialogRoom.selectedUsersId.filter(id => !dialogRoom.room.users.includes(id))
if (usersToAdd.length > 0) {
  // for every added user, add them to the Seald session
  await dialogRoom.sealdSession.addRecipients({ userIds: usersToAdd })
  // then add them to the pubnub channel
  await pubnub.objects.setChannelMembers({
    channel: dialogRoom.room.id,
    uuids: usersToAdd
  })
}
if (usersToRemove.length > 0) {
  // for every removed user, revoke them from the Seald session
  await dialogRoom.sealdSession.revokeRecipients({ userIds: usersToRemove })
  // then remove them from the pubnub channel
  for (const u of usersToRemove) {
    await pubnub.objects.removeMemberships({
      channels: [dialogRoom.room.id],
      uuid: u
    })
  }
}
Enter fullscreen mode Exit fullscreen mode

Wniosek ✅

Gdy to zrobimy, jesteśmy skończeni!

Udało nam się zintegrować Seald z PubNub za pomocą zaledwie kilku linijek kodu.

Teraz, gdy czat jest szyfrowany od końca do końca, możesz zapewnić swoich użytkowników, że ich dane pozostaną poufne, nawet w przypadku naruszenia danych.

Jak zawsze, nie wahaj się skontaktować z Seald lub skontaktuj się z PubNub , jeśli potrzebujesz dodatkowych wskazówek.

Nie możemy się doczekać, aby zobaczyć, co zbudowałeś 🥳.

Spis treści

Przegląd treściDlaczego warto stosowaćszyfrowanie typu end-to-end? Dlaczego wartoużywać Seald.io zamiast haka szyfrującego PubNub? Cele🏆 Wdrożenie🧠 Konfiguracjakonta PubNub 👤 Tworzeniepodstawowego czatu przy użyciu PubNub 💬 Uzyskiwaniepoczątkowego stanu aplikacji 🌱 Odbieraniei wysyłanie wiadomości w pokoju czatu 📩 Zarządzanieczatem grupowym👨‍👩‍👦‍👦Adding szyfrowanieend-to-end za pomocą Seald 🔒 Dlaczego warto używać Seald do szyfrowania end-to-end?szyfrowanie end-to-end z Seald 🔒💬Założeniekonta Seald 👤InstytucjonalizacjaSeald SDK 💡Tworzeniei pobieranie tożsamości Seald 🔑Rozpoczęcieszyfrowania i deszyfrowania wiadomości 🔒🔓Zarządzanieczłonkami grupy👨‍👩‍👦Conclusion ✅

Jak PubNub może ci pomóc?

Ten artykuł został pierwotnie opublikowany na PubNub.com

Nasza platforma pomaga programistom tworzyć, dostarczać i zarządzać interaktywnością w czasie rzeczywistym dla aplikacji internetowych, aplikacji mobilnych i urządzeń IoT.

Fundamentem naszej platformy jest największa w branży i najbardziej skalowalna sieć przesyłania wiadomości w czasie rzeczywistym. Dzięki ponad 15 punktom obecności na całym świecie obsługującym 800 milionów aktywnych użytkowników miesięcznie i niezawodności na poziomie 99,999%, nigdy nie będziesz musiał martwić się o przestoje, limity współbieżności lub jakiekolwiek opóźnienia spowodowane skokami ruchu.

Poznaj PubNub

Sprawdź Live Tour, aby zrozumieć podstawowe koncepcje każdej aplikacji opartej na PubNub w mniej niż 5 minut.

Rozpocznij konfigurację

Załóż konto PubNub, aby uzyskać natychmiastowy i bezpłatny dostęp do kluczy PubNub.

Rozpocznij

Dokumenty PubNub pozwolą Ci rozpocząć pracę, niezależnie od przypadku użycia lub zestawu SDK.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .