All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.whispersystems.libsignal.state.SessionState Maven / Gradle / Ivy

/**
 * Copyright (C) 2014-2016 Open Whisper Systems
 *
 * Licensed according to the LICENSE file in this repository.
 */

package org.whispersystems.libsignal.state;

import org.signal.client.internal.Native;

import org.whispersystems.libsignal.IdentityKey;
import org.whispersystems.libsignal.IdentityKeyPair;
import org.whispersystems.libsignal.InvalidKeyException;
import org.whispersystems.libsignal.ecc.Curve;
import org.whispersystems.libsignal.ecc.ECKeyPair;
import org.whispersystems.libsignal.ecc.ECPrivateKey;
import org.whispersystems.libsignal.ecc.ECPublicKey;
import org.whispersystems.libsignal.logging.Log;
import org.whispersystems.libsignal.state.StorageProtos.SessionStructure.Chain;
import org.whispersystems.libsignal.state.StorageProtos.SessionStructure.PendingKeyExchange;
import org.whispersystems.libsignal.state.StorageProtos.SessionStructure.PendingPreKey;
import org.whispersystems.libsignal.util.Pair;
import org.whispersystems.libsignal.util.guava.Optional;

import java.io.IOException;

import java.util.Iterator;
import java.util.List;

import static org.whispersystems.libsignal.state.StorageProtos.SessionStructure;

public class SessionState {
  private SessionStructure sessionStructure;

  static public SessionState initializeAliceSession(IdentityKeyPair identityKey,
                                                    ECKeyPair baseKey,
                                                    IdentityKey theirIdentityKey,
                                                    ECPublicKey theirSignedPreKey,
                                                    ECPublicKey theirRatchetKey) {
  try {
      return new SessionState(Native.SessionState_InitializeAliceSession(identityKey.getPrivateKey().nativeHandle(),
                                                     identityKey.getPublicKey().getPublicKey().nativeHandle(),
                                                     baseKey.getPrivateKey().nativeHandle(),
                                                     baseKey.getPublicKey().nativeHandle(),
                                                     theirIdentityKey.getPublicKey().nativeHandle(),
                                                     theirSignedPreKey.nativeHandle(),
                                                     theirRatchetKey.nativeHandle()));
    } catch (IOException e) {
      throw new AssertionError(e);
    }
  }

  static public SessionState initializeBobSession(IdentityKeyPair identityKey,
                                                  ECKeyPair signedPreKey,
                                                  ECKeyPair ephemeralKey,
                                                  IdentityKey theirIdentityKey,
                                                  ECPublicKey theirBaseKey) {
    try {
      return new SessionState(Native.SessionState_InitializeBobSession(identityKey.getPrivateKey().nativeHandle(),
                                                   identityKey.getPublicKey().getPublicKey().nativeHandle(),
                                                   signedPreKey.getPrivateKey().nativeHandle(),
                                                   signedPreKey.getPublicKey().nativeHandle(),
                                                   ephemeralKey.getPrivateKey().nativeHandle(),
                                                   ephemeralKey.getPublicKey().nativeHandle(),
                                                   theirIdentityKey.getPublicKey().nativeHandle(),
                                                   theirBaseKey.nativeHandle()));
    } catch (IOException e) {
      throw new AssertionError(e);
    }
  }

  public SessionState(byte[] serialized) throws IOException {
    this.sessionStructure = SessionStructure.parseFrom(serialized);
  }

  private static final int MAX_MESSAGE_KEYS = 2000;

  public SessionState() {
    this.sessionStructure = SessionStructure.newBuilder().build();
  }

  public SessionState(SessionStructure sessionStructure) {
    this.sessionStructure = sessionStructure;
  }

  public SessionState(SessionState copy) {
    this.sessionStructure = copy.sessionStructure.toBuilder().build();
  }

  public SessionStructure getStructure() {
    return sessionStructure;
  }

  public byte[] getAliceBaseKey() {
    return this.sessionStructure.getAliceBaseKey().toByteArray();
  }

  public int getSessionVersion() {
    int sessionVersion = this.sessionStructure.getSessionVersion();

    if (sessionVersion == 0) return 2;
    else                     return sessionVersion;
  }

  public IdentityKey getRemoteIdentityKey() {
    try {
      if (!this.sessionStructure.hasRemoteIdentityPublic()) {
        return null;
      }

      return new IdentityKey(this.sessionStructure.getRemoteIdentityPublic().toByteArray(), 0);
    } catch (InvalidKeyException e) {
      Log.w("SessionRecordV2", e);
      return null;
    }
  }

  public IdentityKey getLocalIdentityKey() {
    try {
      return new IdentityKey(this.sessionStructure.getLocalIdentityPublic().toByteArray(), 0);
    } catch (InvalidKeyException e) {
      throw new AssertionError(e);
    }
  }

  public int getPreviousCounter() {
    return sessionStructure.getPreviousCounter();
  }

  public ECPublicKey getSenderRatchetKey() {
    try {
      return Curve.decodePoint(sessionStructure.getSenderChain().getSenderRatchetKey().toByteArray(), 0);
    } catch (InvalidKeyException e) {
      throw new AssertionError(e);
    }
  }

  public ECKeyPair getSenderRatchetKeyPair() {
    ECPublicKey  publicKey  = getSenderRatchetKey();
    ECPrivateKey privateKey = Curve.decodePrivatePoint(sessionStructure.getSenderChain()
                                                                       .getSenderRatchetKeyPrivate()
                                                                       .toByteArray());

    return new ECKeyPair(publicKey, privateKey);
  }

  public boolean hasSenderChain() {
    return sessionStructure.hasSenderChain();
  }

  private Pair getReceiverChain(ECPublicKey senderEphemeral) {
    List receiverChains = sessionStructure.getReceiverChainsList();
    int         index          = 0;

    for (Chain receiverChain : receiverChains) {
      try {
        ECPublicKey chainSenderRatchetKey = Curve.decodePoint(receiverChain.getSenderRatchetKey().toByteArray(), 0);

        if (chainSenderRatchetKey.equals(senderEphemeral)) {
          return new Pair<>(receiverChain,index);
        }
      } catch (InvalidKeyException e) {
        Log.w("SessionRecordV2", e);
     }

     index++;
    }

   return null;
   }

   public byte[] getReceiverChainKeyValue(ECPublicKey senderEphemeral) {
     Pair receiverChainAndIndex = getReceiverChain(senderEphemeral);
     Chain               receiverChain         = receiverChainAndIndex.first();

     if (receiverChain == null) {
       return null;
     } else {
       return receiverChain.getChainKey().getKey().toByteArray();
     }
  }

  public byte[] getSenderChainKeyValue() {
    Chain.ChainKey chainKeyStructure = sessionStructure.getSenderChain().getChainKey();
    return chainKeyStructure.getKey().toByteArray();
  }

  public int getRemoteRegistrationId() {
    return this.sessionStructure.getRemoteRegistrationId();
  }

  public int getLocalRegistrationId() {
    return this.sessionStructure.getLocalRegistrationId();
  }

  public byte[] serialize() {
    return sessionStructure.toByteArray();
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy