docs: OmemoMessage.Received decryptMessage(OmemoManager.LoggedInOmemoManager managerGuard,
                                           BareJid senderJid,
                                           OmemoElement omemoElement)
              throws CorruptedOmemoKeyException, CryptoFailedException, NoRawSessionException {
  
          OmemoManager manager = managerGuard.get();
          int senderId = omemoElement.getHeader().getSid();
          OmemoDevice senderDevice = new OmemoDevice(senderJid, senderId);
  
          CipherAndAuthTag cipherAndAuthTag = getOmemoRatchet(manager)
                  .retrieveMessageKeyAndAuthTag(senderDevice, omemoElement);
  
          // Retrieve senders fingerprint. TODO: Find a way to do this without the store.
          OmemoFingerprint senderFingerprint;
          try {
              senderFingerprint = getOmemoStoreBackend().getFingerprint(manager.getOwnDevice(), senderDevice);
          } catch (NoIdentityKeyException e) {
              throw new AssertionError("Cannot retrieve OmemoFingerprint of sender although decryption was successful: " + e);
          }
  
          // Reset the message counter.
          omemoStore.storeOmemoMessageCounter(manager.getOwnDevice(), senderDevice, 0);
  
          if (omemoElement.isMessageElement()) {
              // Use symmetric message key to decrypt message payload.
              String plaintext = OmemoRatchet.decryptMessageElement(omemoElement, cipherAndAuthTag);
  
              return new OmemoMessage.Received(omemoElement, cipherAndAuthTag.getKey(), cipherAndAuthTag.getIv(),
                      plaintext, senderFingerprint, senderDevice, cipherAndAuthTag.wasPreKeyEncrypted());
  
          } else {
              // KeyTransportMessages don't require decryption of the payload.
              return new OmemoMessage.Received(omemoElement, cipherAndAuthTag.getKey(), cipherAndAuthTag.getIv(),
                      null, senderFingerprint, senderDevice, cipherAndAuthTag.wasPreKeyEncrypted());
          }
      }