org.whispersystems.libsignal.state.IdentityKeyStore Java Examples

The following examples show how to use org.whispersystems.libsignal.state.IdentityKeyStore. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: IdentityUtil.java    From mollyim-android with GNU General Public License v3.0 6 votes vote down vote up
public static void saveIdentity(Context context, String user, IdentityKey identityKey) {
  synchronized (SESSION_LOCK) {
    IdentityKeyStore      identityKeyStore = new TextSecureIdentityKeyStore(context);
    SessionStore          sessionStore     = new TextSecureSessionStore(context);
    SignalProtocolAddress address          = new SignalProtocolAddress(user, 1);

    if (identityKeyStore.saveIdentity(address, identityKey)) {
      if (sessionStore.containsSession(address)) {
        SessionRecord sessionRecord = sessionStore.loadSession(address);
        sessionRecord.archiveCurrentState();

        sessionStore.storeSession(address, sessionRecord);
      }
    }
  }
}
 
Example #2
Source File: IdentityUtil.java    From bcm-android with GNU General Public License v3.0 6 votes vote down vote up
public static void saveIdentity(Context context, AccountContext accountContext, String number, IdentityKey identityKey) {
    synchronized (SESSION_LOCK) {
        IdentityKeyStore identityKeyStore = new TextSecureIdentityKeyStore(context, accountContext);
        SessionStore sessionStore = new TextSecureSessionStore(context, accountContext);
        SignalProtocolAddress address = new SignalProtocolAddress(number, 1);

        if (identityKeyStore.saveIdentity(address, identityKey)) {
            if (sessionStore.containsSession(address)) {
                SessionRecord sessionRecord = sessionStore.loadSession(address);
                sessionRecord.archiveCurrentState();

                sessionStore.storeSession(address, sessionRecord);
            }
        }
    }
}
 
Example #3
Source File: SessionBuilder.java    From Silence with GNU General Public License v3.0 6 votes vote down vote up
/**
 * Build a new session from a {@link org.whispersystems.libsignal.protocol.KeyExchangeMessage}
 * received from a remote client.
 *
 * @param message The received KeyExchangeMessage.
 * @return The KeyExchangeMessage to respond with, or null if no response is necessary.
 * @throws InvalidKeyException if the received KeyExchangeMessage is badly formatted.
 */
public KeyExchangeMessage process(KeyExchangeMessage message)
    throws InvalidKeyException, UntrustedIdentityException, StaleKeyExchangeException
{
  synchronized (SessionCipher.SESSION_LOCK) {
    if (!identityKeyStore.isTrustedIdentity(remoteAddress, message.getIdentityKey(), IdentityKeyStore.Direction.SENDING)) {
      throw new UntrustedIdentityException(remoteAddress.getName(), message.getIdentityKey());
    }

    KeyExchangeMessage responseMessage = null;

    if (message.isInitiate()) responseMessage = processInitiate(message);
    else                      processResponse(message);

    return responseMessage;
  }
}
 
Example #4
Source File: KeyExchangeInitiator.java    From Silence with GNU General Public License v3.0 6 votes vote down vote up
public static void initiateKeyExchange(Context context, MasterSecret masterSecret, Recipients recipients, int subscriptionId) {
  Recipient         recipient         = recipients.getPrimaryRecipient();
  SessionStore      sessionStore      = new SilenceSessionStore(context, masterSecret, subscriptionId);
  PreKeyStore       preKeyStore       = new SilencePreKeyStore(context, masterSecret, subscriptionId);
  SignedPreKeyStore signedPreKeyStore = new SilencePreKeyStore(context, masterSecret, subscriptionId);
  IdentityKeyStore  identityKeyStore  = new SilenceIdentityKeyStore(context, masterSecret, subscriptionId);

  SessionBuilder    sessionBuilder    = new SessionBuilder(sessionStore, preKeyStore, signedPreKeyStore,
                                                           identityKeyStore, new SignalProtocolAddress(recipient.getNumber(), 1));

  if (identityKeyStore.getIdentityKeyPair() != null) {
    KeyExchangeMessage         keyExchangeMessage = sessionBuilder.process();
    String                     serializedMessage  = Base64.encodeBytesWithoutPadding(keyExchangeMessage.serialize());
    OutgoingKeyExchangeMessage textMessage        = new OutgoingKeyExchangeMessage(recipients, serializedMessage, subscriptionId);

    MessageSender.send(context, masterSecret, textMessage, -1, false);
  } else {
    Toast.makeText(context, R.string.VerifyIdentityActivity_you_do_not_have_an_identity_key,
            Toast.LENGTH_LONG).show();
  }
}
 
Example #5
Source File: SessionBuilder.java    From libsignal-protocol-java with GNU General Public License v3.0 6 votes vote down vote up
/**
 * Build a new session from a received {@link PreKeySignalMessage}.
 *
 * After a session is constructed in this way, the embedded {@link SignalMessage}
 * can be decrypted.
 *
 * @param message The received {@link PreKeySignalMessage}.
 * @throws org.whispersystems.libsignal.InvalidKeyIdException when there is no local
 *                                                             {@link org.whispersystems.libsignal.state.PreKeyRecord}
 *                                                             that corresponds to the PreKey ID in
 *                                                             the message.
 * @throws org.whispersystems.libsignal.InvalidKeyException when the message is formatted incorrectly.
 * @throws org.whispersystems.libsignal.UntrustedIdentityException when the {@link IdentityKey} of the sender is untrusted.
 */
/*package*/ Optional<Integer> process(SessionRecord sessionRecord, PreKeySignalMessage message)
    throws InvalidKeyIdException, InvalidKeyException, UntrustedIdentityException
{
  IdentityKey theirIdentityKey = message.getIdentityKey();

  if (!identityKeyStore.isTrustedIdentity(remoteAddress, theirIdentityKey, IdentityKeyStore.Direction.RECEIVING)) {
    throw new UntrustedIdentityException(remoteAddress.getName(), theirIdentityKey);
  }

  Optional<Integer> unsignedPreKeyId = processV3(sessionRecord, message);

  identityKeyStore.saveIdentity(remoteAddress, theirIdentityKey);

  return unsignedPreKeyId;
}
 
Example #6
Source File: SessionBuilder.java    From Silence with GNU General Public License v3.0 5 votes vote down vote up
/**
 * Constructs a SessionBuilder.
 *
 * @param sessionStore The {@link org.whispersystems.libsignal.state.SessionStore} to store the constructed session in.
 * @param preKeyStore The {@link  org.whispersystems.libsignal.state.PreKeyStore} where the client's local {@link org.whispersystems.libsignal.state.PreKeyRecord}s are stored.
 * @param identityKeyStore The {@link org.whispersystems.libsignal.state.IdentityKeyStore} containing the client's identity key information.
 * @param remoteAddress The address of the remote user to build a session with.
 */
public SessionBuilder(SessionStore sessionStore,
                      PreKeyStore preKeyStore,
                      SignedPreKeyStore signedPreKeyStore,
                      IdentityKeyStore identityKeyStore,
                      SignalProtocolAddress remoteAddress)
{
  this.sessionStore      = sessionStore;
  this.preKeyStore       = preKeyStore;
  this.signedPreKeyStore = signedPreKeyStore;
  this.identityKeyStore  = identityKeyStore;
  this.remoteAddress     = remoteAddress;
}
 
Example #7
Source File: SessionBuilder.java    From Silence with GNU General Public License v3.0 5 votes vote down vote up
/**
 * Build a new session from a received {@link PreKeySignalMessage}.
 *
 * After a session is constructed in this way, the embedded {@link SignalMessage}
 * can be decrypted.
 *
 * @param message The received {@link PreKeySignalMessage}.
 * @throws org.whispersystems.libsignal.InvalidKeyIdException when there is no local
 *                                                             {@link org.whispersystems.libsignal.state.PreKeyRecord}
 *                                                             that corresponds to the PreKey ID in
 *                                                             the message.
 * @throws org.whispersystems.libsignal.InvalidKeyException when the message is formatted incorrectly.
 * @throws org.whispersystems.libsignal.UntrustedIdentityException when the {@link IdentityKey} of the sender is untrusted.
 */
/*package*/ Optional<Integer> process(SessionRecord sessionRecord, PreKeySignalMessage message)
    throws InvalidKeyIdException, InvalidKeyException, UntrustedIdentityException
{
  IdentityKey theirIdentityKey = message.getIdentityKey();

  if (!identityKeyStore.isTrustedIdentity(remoteAddress, theirIdentityKey, IdentityKeyStore.Direction.RECEIVING)) {
    throw new UntrustedIdentityException(remoteAddress.getName(), theirIdentityKey);
  }

  Optional<Integer> unsignedPreKeyId = processV3(sessionRecord, message);

  identityKeyStore.saveIdentity(remoteAddress, theirIdentityKey);
  return unsignedPreKeyId;
}
 
Example #8
Source File: SessionBuilder.java    From libsignal-protocol-java with GNU General Public License v3.0 5 votes vote down vote up
/**
 * Constructs a SessionBuilder.
 *
 * @param sessionStore The {@link org.whispersystems.libsignal.state.SessionStore} to store the constructed session in.
 * @param preKeyStore The {@link  org.whispersystems.libsignal.state.PreKeyStore} where the client's local {@link org.whispersystems.libsignal.state.PreKeyRecord}s are stored.
 * @param identityKeyStore The {@link org.whispersystems.libsignal.state.IdentityKeyStore} containing the client's identity key information.
 * @param remoteAddress The address of the remote user to build a session with.
 */
public SessionBuilder(SessionStore sessionStore,
                      PreKeyStore preKeyStore,
                      SignedPreKeyStore signedPreKeyStore,
                      IdentityKeyStore identityKeyStore,
                      SignalProtocolAddress remoteAddress)
{
  this.sessionStore      = sessionStore;
  this.preKeyStore       = preKeyStore;
  this.signedPreKeyStore = signedPreKeyStore;
  this.identityKeyStore  = identityKeyStore;
  this.remoteAddress     = remoteAddress;
}
 
Example #9
Source File: SessionCipher.java    From libsignal-protocol-java with GNU General Public License v3.0 5 votes vote down vote up
/**
 * Construct a SessionCipher for encrypt/decrypt operations on a session.
 * In order to use SessionCipher, a session must have already been created
 * and stored using {@link SessionBuilder}.
 *
 * @param  sessionStore The {@link SessionStore} that contains a session for this recipient.
 * @param  remoteAddress  The remote address that messages will be encrypted to or decrypted from.
 */
public SessionCipher(SessionStore sessionStore, PreKeyStore preKeyStore,
                     SignedPreKeyStore signedPreKeyStore, IdentityKeyStore identityKeyStore,
                     SignalProtocolAddress remoteAddress)
{
  this.sessionStore     = sessionStore;
  this.preKeyStore      = preKeyStore;
  this.identityKeyStore = identityKeyStore;
  this.remoteAddress    = remoteAddress;
  this.sessionBuilder   = new SessionBuilder(sessionStore, preKeyStore, signedPreKeyStore,
                                             identityKeyStore, remoteAddress);
}
 
Example #10
Source File: SessionCipher.java    From libsignal-protocol-java with GNU General Public License v3.0 5 votes vote down vote up
/**
 * Decrypt a message.
 *
 * @param  ciphertext The {@link SignalMessage} to decrypt.
 * @param  callback   A callback that is triggered after decryption is complete,
 *                    but before the updated session state has been committed to the session
 *                    DB.  This allows some implementations to store the committed plaintext
 *                    to a DB first, in case they are concerned with a crash happening between
 *                    the time the session state is updated but before they're able to store
 *                    the plaintext to disk.
 *
 * @return The plaintext.
 * @throws InvalidMessageException if the input is not valid ciphertext.
 * @throws DuplicateMessageException if the input is a message that has already been received.
 * @throws LegacyMessageException if the input is a message formatted by a protocol version that
 *                                is no longer supported.
 * @throws NoSessionException if there is no established session for this contact.
 */
public byte[] decrypt(SignalMessage ciphertext, DecryptionCallback callback)
    throws InvalidMessageException, DuplicateMessageException, LegacyMessageException,
           NoSessionException, UntrustedIdentityException
{
  synchronized (SESSION_LOCK) {

    if (!sessionStore.containsSession(remoteAddress)) {
      throw new NoSessionException("No session for: " + remoteAddress);
    }

    SessionRecord sessionRecord = sessionStore.loadSession(remoteAddress);
    byte[]        plaintext     = decrypt(sessionRecord, ciphertext);

    if (!identityKeyStore.isTrustedIdentity(remoteAddress, sessionRecord.getSessionState().getRemoteIdentityKey(), IdentityKeyStore.Direction.RECEIVING)) {
      throw new UntrustedIdentityException(remoteAddress.getName(), sessionRecord.getSessionState().getRemoteIdentityKey());
    }

    identityKeyStore.saveIdentity(remoteAddress, sessionRecord.getSessionState().getRemoteIdentityKey());

    callback.handlePlaintext(plaintext);

    sessionStore.storeSession(remoteAddress, sessionRecord);

    return plaintext;
  }
}
 
Example #11
Source File: SessionBuilder.java    From Silence with GNU General Public License v3.0 4 votes vote down vote up
/**
 * Build a new session from a {@link org.whispersystems.libsignal.state.PreKeyBundle} retrieved from
 * a server.
 *
 * @param preKey A PreKey for the destination recipient, retrieved from a server.
 * @throws InvalidKeyException when the {@link org.whispersystems.libsignal.state.PreKeyBundle} is
 *                             badly formatted.
 * @throws org.whispersystems.libsignal.UntrustedIdentityException when the sender's
 *                                                                  {@link IdentityKey} is not
 *                                                                  trusted.
 */
public void process(PreKeyBundle preKey) throws InvalidKeyException, UntrustedIdentityException {
  synchronized (SessionCipher.SESSION_LOCK) {
    if (!identityKeyStore.isTrustedIdentity(remoteAddress, preKey.getIdentityKey(), IdentityKeyStore.Direction.SENDING)) {
      throw new UntrustedIdentityException(remoteAddress.getName(), preKey.getIdentityKey());
    }

    if (preKey.getSignedPreKey() != null &&
        !Curve.verifySignature(preKey.getIdentityKey().getPublicKey(),
                               preKey.getSignedPreKey().serialize(),
                               preKey.getSignedPreKeySignature()))
    {
      throw new InvalidKeyException("Invalid signature on device key!");
    }

    if (preKey.getSignedPreKey() == null) {
      throw new InvalidKeyException("No signed prekey!");
    }

    SessionRecord         sessionRecord        = sessionStore.loadSession(remoteAddress);
    ECKeyPair             ourBaseKey           = Curve.generateKeyPair();
    ECPublicKey           theirSignedPreKey    = preKey.getSignedPreKey();
    Optional<ECPublicKey> theirOneTimePreKey   = Optional.fromNullable(preKey.getPreKey());
    Optional<Integer>     theirOneTimePreKeyId = theirOneTimePreKey.isPresent() ? Optional.of(preKey.getPreKeyId()) :
                                                                                  Optional.<Integer>absent();

    AliceSignalProtocolParameters.Builder parameters = AliceSignalProtocolParameters.newBuilder();

    parameters.setOurBaseKey(ourBaseKey)
              .setOurIdentityKey(identityKeyStore.getIdentityKeyPair())
              .setTheirIdentityKey(preKey.getIdentityKey())
              .setTheirSignedPreKey(theirSignedPreKey)
              .setTheirRatchetKey(theirSignedPreKey)
              .setTheirOneTimePreKey(theirOneTimePreKey);

    if (!sessionRecord.isFresh()) sessionRecord.archiveCurrentState();

    RatchetingSession.initializeSession(sessionRecord.getSessionState(), parameters.create());

    sessionRecord.getSessionState().setUnacknowledgedPreKeyMessage(theirOneTimePreKeyId, preKey.getSignedPreKeyId(), ourBaseKey.getPublicKey());
    sessionRecord.getSessionState().setLocalRegistrationId(identityKeyStore.getLocalRegistrationId());
    sessionRecord.getSessionState().setRemoteRegistrationId(preKey.getRegistrationId());
    sessionRecord.getSessionState().setAliceBaseKey(ourBaseKey.getPublicKey().serialize());

    identityKeyStore.saveIdentity(remoteAddress, preKey.getIdentityKey());
    sessionStore.storeSession(remoteAddress, sessionRecord);
  }
}
 
Example #12
Source File: SessionBuilder.java    From libsignal-protocol-java with GNU General Public License v3.0 4 votes vote down vote up
/**
 * Build a new session from a {@link org.whispersystems.libsignal.state.PreKeyBundle} retrieved from
 * a server.
 *
 * @param preKey A PreKey for the destination recipient, retrieved from a server.
 * @throws InvalidKeyException when the {@link org.whispersystems.libsignal.state.PreKeyBundle} is
 *                             badly formatted.
 * @throws org.whispersystems.libsignal.UntrustedIdentityException when the sender's
 *                                                                  {@link IdentityKey} is not
 *                                                                  trusted.
 */
public void process(PreKeyBundle preKey) throws InvalidKeyException, UntrustedIdentityException {
  synchronized (SessionCipher.SESSION_LOCK) {
    if (!identityKeyStore.isTrustedIdentity(remoteAddress, preKey.getIdentityKey(), IdentityKeyStore.Direction.SENDING)) {
      throw new UntrustedIdentityException(remoteAddress.getName(), preKey.getIdentityKey());
    }

    if (preKey.getSignedPreKey() != null &&
        !Curve.verifySignature(preKey.getIdentityKey().getPublicKey(),
                               preKey.getSignedPreKey().serialize(),
                               preKey.getSignedPreKeySignature()))
    {
      throw new InvalidKeyException("Invalid signature on device key!");
    }

    if (preKey.getSignedPreKey() == null) {
      throw new InvalidKeyException("No signed prekey!");
    }

    SessionRecord         sessionRecord        = sessionStore.loadSession(remoteAddress);
    ECKeyPair             ourBaseKey           = Curve.generateKeyPair();
    ECPublicKey           theirSignedPreKey    = preKey.getSignedPreKey();
    Optional<ECPublicKey> theirOneTimePreKey   = Optional.fromNullable(preKey.getPreKey());
    Optional<Integer>     theirOneTimePreKeyId = theirOneTimePreKey.isPresent() ? Optional.of(preKey.getPreKeyId()) :
                                                                                  Optional.<Integer>absent();

    AliceSignalProtocolParameters.Builder parameters = AliceSignalProtocolParameters.newBuilder();

    parameters.setOurBaseKey(ourBaseKey)
              .setOurIdentityKey(identityKeyStore.getIdentityKeyPair())
              .setTheirIdentityKey(preKey.getIdentityKey())
              .setTheirSignedPreKey(theirSignedPreKey)
              .setTheirRatchetKey(theirSignedPreKey)
              .setTheirOneTimePreKey(theirOneTimePreKey);

    if (!sessionRecord.isFresh()) sessionRecord.archiveCurrentState();

    RatchetingSession.initializeSession(sessionRecord.getSessionState(), parameters.create());

    sessionRecord.getSessionState().setUnacknowledgedPreKeyMessage(theirOneTimePreKeyId, preKey.getSignedPreKeyId(), ourBaseKey.getPublicKey());
    sessionRecord.getSessionState().setLocalRegistrationId(identityKeyStore.getLocalRegistrationId());
    sessionRecord.getSessionState().setRemoteRegistrationId(preKey.getRegistrationId());
    sessionRecord.getSessionState().setAliceBaseKey(ourBaseKey.getPublicKey().serialize());

    identityKeyStore.saveIdentity(remoteAddress, preKey.getIdentityKey());
    sessionStore.storeSession(remoteAddress, sessionRecord);
  }
}