org.whispersystems.libsignal.SessionCipher Java Examples

The following examples show how to use org.whispersystems.libsignal.SessionCipher. 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: SignalServiceCipher.java    From bcm-android with GNU General Public License v3.0 6 votes vote down vote up
public OutgoingPushMessage encrypt(SignalProtocolAddress destination, byte[] unpaddedMessage, PushPurpose pushPurpose)
    throws UntrustedIdentityException
{
  SessionCipher        sessionCipher        = new SessionCipher(signalProtocolStore, destination);
  PushTransportDetails transportDetails     = new PushTransportDetails(sessionCipher.getSessionVersion());
  CiphertextMessage    message              = sessionCipher.encrypt(transportDetails.getPaddedMessageBody(unpaddedMessage));
  int                  remoteRegistrationId = sessionCipher.getRemoteRegistrationId();
  String               body                 = Base64.encodeBytes(message.serialize());

  int type;

  switch (message.getType()) {
    case CiphertextMessage.PREKEY_TYPE:  type = Type.PREKEY_BUNDLE_VALUE; break;
    case CiphertextMessage.WHISPER_TYPE: type = Type.CIPHERTEXT_VALUE;    break;
    default: throw new AssertionError("Bad type: " + message.getType());
  }

  return new OutgoingPushMessage(type, destination.getDeviceId(), remoteRegistrationId, body, pushPurpose);
}
 
Example #2
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 #3
Source File: SessionBuilder.java    From Silence with GNU General Public License v3.0 6 votes vote down vote up
/**
 * Initiate a new session by sending an initial KeyExchangeMessage to the recipient.
 *
 * @return the KeyExchangeMessage to deliver.
 */
public KeyExchangeMessage process() {
  synchronized (SessionCipher.SESSION_LOCK) {
    try {
      int             sequence         = KeyHelper.getRandomSequence(65534) + 1;
      int             flags            = KeyExchangeMessage.INITIATE_FLAG;
      ECKeyPair       baseKey          = Curve.generateKeyPair();
      ECKeyPair       ratchetKey       = Curve.generateKeyPair();
      IdentityKeyPair identityKey      = identityKeyStore.getIdentityKeyPair();
      byte[]          baseKeySignature = Curve.calculateSignature(identityKey.getPrivateKey(), baseKey.getPublicKey().serialize());
      SessionRecord   sessionRecord    = sessionStore.loadSession(remoteAddress);

      sessionRecord.getSessionState().setPendingKeyExchange(sequence, baseKey, ratchetKey, identityKey);
      sessionStore.storeSession(remoteAddress, sessionRecord);

      return new KeyExchangeMessage(CiphertextMessage.CURRENT_VERSION,
                                    sequence, flags, baseKey.getPublicKey(), baseKeySignature,
                                    ratchetKey.getPublicKey(), identityKey.getPublicKey());
    } catch (InvalidKeyException e) {
      throw new AssertionError(e);
    }
  }
}
 
Example #4
Source File: SmsCipher.java    From Silence with GNU General Public License v3.0 6 votes vote down vote up
public IncomingTextMessage decrypt(Context context, IncomingTextMessage message)
    throws LegacyMessageException, InvalidMessageException, DuplicateMessageException,
           NoSessionException, UntrustedIdentityException
{
  try {
    byte[]        decoded       = transportDetails.getDecodedMessage(message.getMessageBody().getBytes());
    SignalMessage signalMessage = new SignalMessage(decoded);
    SessionCipher sessionCipher = new SessionCipher(signalProtocolStore, new SignalProtocolAddress(message.getSender(), 1));
    byte[]        padded        = sessionCipher.decrypt(signalMessage);
    byte[]        plaintext     = transportDetails.getStrippedPaddingMessageBody(padded);

    if (message.isEndSession() && "TERMINATE".equals(new String(plaintext))) {
      signalProtocolStore.deleteSession(new SignalProtocolAddress(message.getSender(), 1));
    }

    return message.withMessageBody(new String(plaintext));
  } catch (IOException | IllegalArgumentException | NullPointerException e) {
    throw new InvalidMessageException(e);
  }
}
 
Example #5
Source File: SmsCipher.java    From Silence with GNU General Public License v3.0 6 votes vote down vote up
public IncomingEncryptedMessage decrypt(Context context, IncomingPreKeyBundleMessage message)
    throws InvalidVersionException, InvalidMessageException, DuplicateMessageException,
           UntrustedIdentityException, LegacyMessageException
{
  try {
    byte[]              decoded       = transportDetails.getDecodedMessage(message.getMessageBody().getBytes());
    PreKeySignalMessage preKeyMessage = new PreKeySignalMessage(decoded);
    SessionCipher       sessionCipher = new SessionCipher(signalProtocolStore, new SignalProtocolAddress(message.getSender(), 1));
    byte[]              padded        = sessionCipher.decrypt(preKeyMessage);
    byte[]              plaintext     = transportDetails.getStrippedPaddingMessageBody(padded);

    return new IncomingEncryptedMessage(message, new String(plaintext));
  } catch (IOException | InvalidKeyException | InvalidKeyIdException e) {
    throw new InvalidMessageException(e);
  }
}
 
Example #6
Source File: SmsCipher.java    From Silence with GNU General Public License v3.0 6 votes vote down vote up
public OutgoingTextMessage encrypt(OutgoingTextMessage message)
  throws NoSessionException, UntrustedIdentityException
{
  byte[] paddedBody      = transportDetails.getPaddedMessageBody(message.getMessageBody().getBytes());
  String recipientNumber = message.getRecipients().getPrimaryRecipient().getNumber();

  if (!signalProtocolStore.containsSession(new SignalProtocolAddress(recipientNumber, 1))) {
    throw new NoSessionException("No session for: " + recipientNumber);
  }

  SessionCipher     cipher            = new SessionCipher(signalProtocolStore, new SignalProtocolAddress(recipientNumber, 1));
  CiphertextMessage ciphertextMessage = cipher.encrypt(paddedBody);
  String            encodedCiphertext = new String(transportDetails.getEncodedMessage(ciphertextMessage.serialize()));

  if (ciphertextMessage.getType() == CiphertextMessage.PREKEY_TYPE) {
    return new OutgoingPrekeyBundleMessage(message, encodedCiphertext);
  } else {
    return message.withBody(encodedCiphertext);
  }
}
 
Example #7
Source File: SignalServiceCipher.java    From bcm-android with GNU General Public License v3.0 5 votes vote down vote up
private byte[] decrypt(SignalServiceProtos.Envelope envelope, byte[] ciphertext)
    throws InvalidVersionException, InvalidMessageException, InvalidKeyException,
           DuplicateMessageException, InvalidKeyIdException, UntrustedIdentityException,
           LegacyMessageException, NoSessionException
{
  SignalProtocolAddress sourceAddress = new SignalProtocolAddress(envelope.getSource(), envelope.getSourceDevice());
  SessionCipher         sessionCipher = new SessionCipher(signalProtocolStore, sourceAddress);

  byte[] paddedMessage;

  if (envelope.getType() == Type.PREKEY_BUNDLE) {
    paddedMessage = sessionCipher.decrypt(new PreKeySignalMessage(ciphertext));
      //纠正remote register id
      SessionRecord sessionRecord = signalProtocolStore.loadSession(sourceAddress);
      if (sessionRecord.getSessionState().getRemoteRegistrationId() == 0) {
          sessionRecord.getSessionState().setRemoteRegistrationId(envelope.getSourceRegistration());
          signalProtocolStore.storeSession(sourceAddress, sessionRecord);
      }

  } else if (envelope.getType() == Type.CIPHERTEXT) {
    paddedMessage = sessionCipher.decrypt(new SignalMessage(ciphertext));
  } else {
    throw new InvalidMessageException("Unknown type: " + envelope.getType());
  }

  PushTransportDetails transportDetails = new PushTransportDetails(sessionCipher.getSessionVersion());
  return transportDetails.getStrippedPaddingMessageBody(paddedMessage);
}
 
Example #8
Source File: SignalOmemoService.java    From Smack with Apache License 2.0 5 votes vote down vote up
@Override
protected SignalOmemoRatchet instantiateOmemoRatchet(
        OmemoManager manager,
        OmemoStore<IdentityKeyPair, IdentityKey, PreKeyRecord, SignedPreKeyRecord, SessionRecord,
                SignalProtocolAddress, ECPublicKey, PreKeyBundle, SessionCipher> store) {

    return new SignalOmemoRatchet(manager, getOmemoStoreBackend());
}
 
Example #9
Source File: SignalOmemoRatchet.java    From Smack with Apache License 2.0 5 votes vote down vote up
SignalOmemoRatchet(OmemoManager omemoManager,
                          OmemoStore<IdentityKeyPair, IdentityKey, PreKeyRecord, SignedPreKeyRecord,
                                         SessionRecord, SignalProtocolAddress, ECPublicKey, PreKeyBundle,
                                         SessionCipher> store) {
    super(omemoManager, store);
    this.storeConnector = new SignalOmemoStoreConnector(omemoManager, store);
}
 
Example #10
Source File: MmsCipher.java    From Silence with GNU General Public License v3.0 5 votes vote down vote up
public SendReq encrypt(Context context, SendReq message)
    throws NoSessionException, RecipientFormattingException, UndeliverableMessageException,
           UntrustedIdentityException
{
  EncodedStringValue[] encodedRecipient = message.getTo();
  String               recipientString  = encodedRecipient[0].getString();
  byte[]               pduBytes         = new PduComposer(context, message).make();

  if (pduBytes == null) {
    throw new UndeliverableMessageException("PDU composition failed, null payload");
  }

  if (!axolotlStore.containsSession(new SignalProtocolAddress(recipientString, 1))) {
    throw new NoSessionException("No session for: " + recipientString);
  }

  SessionCipher     cipher            = new SessionCipher(axolotlStore, new SignalProtocolAddress(recipientString, 1));
  CiphertextMessage ciphertextMessage = cipher.encrypt(pduBytes);
  byte[]            encryptedPduBytes = textTransport.getEncodedMessage(ciphertextMessage.serialize());

  PduBody body         = new PduBody();
  PduPart part         = new PduPart();

  part.setContentId((System.currentTimeMillis()+"").getBytes());
  part.setContentType(ContentType.TEXT_PLAIN.getBytes());
  part.setName((System.currentTimeMillis()+"").getBytes());
  part.setData(encryptedPduBytes);
  body.addPart(part);
  message.setSubject(new EncodedStringValue(WirePrefix.calculateEncryptedMmsSubject()));
  message.setBody(body);

  return message;
}
 
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: SignalOmemoStoreConnector.java    From Smack with Apache License 2.0 4 votes vote down vote up
public SignalOmemoStoreConnector(OmemoManager omemoManager, OmemoStore<IdentityKeyPair,
        IdentityKey, PreKeyRecord, SignedPreKeyRecord, SessionRecord, SignalProtocolAddress, ECPublicKey,
        PreKeyBundle, SessionCipher> store) {
    this.omemoManager = omemoManager;
    this.omemoStore = store;
}
 
Example #13
Source File: XmppAxolotlSession.java    From Pix-Art-Messenger with GNU General Public License v3.0 4 votes vote down vote up
public XmppAxolotlSession(Account account, SQLiteAxolotlStore store, SignalProtocolAddress remoteAddress) {
    this.cipher = new SessionCipher(store, remoteAddress);
    this.remoteAddress = remoteAddress;
    this.sqLiteAxolotlStore = store;
    this.account = account;
}
 
Example #14
Source File: SignalOmemoRatchet.java    From Smack with Apache License 2.0 4 votes vote down vote up
private SessionCipher getCipher(OmemoDevice device) {
    return new SessionCipher(storeConnector, storeConnector, storeConnector, storeConnector,
            SignalOmemoStoreConnector.asAddress(device));
}
 
Example #15
Source File: SignalIOCipherOmemoStore.java    From Zom-Android-XMPP with GNU General Public License v3.0 4 votes vote down vote up
@Override
public OmemoKeyUtil<IdentityKeyPair, IdentityKey, PreKeyRecord, SignedPreKeyRecord, SessionRecord, SignalProtocolAddress, ECPublicKey, PreKeyBundle, SessionCipher> keyUtil() {
    return new SignalOmemoKeyUtil();
}
 
Example #16
Source File: SignalOmemoService.java    From Smack with Apache License 2.0 4 votes vote down vote up
@Override
public OmemoStore<IdentityKeyPair, IdentityKey, PreKeyRecord, SignedPreKeyRecord, SessionRecord,
        SignalProtocolAddress, ECPublicKey, PreKeyBundle, SessionCipher>
createDefaultOmemoStoreBackend() {
    return new SignalCachingOmemoStore();
}
 
Example #17
Source File: SignalOmemoStoreTest.java    From Smack with Apache License 2.0 4 votes vote down vote up
public SignalOmemoStoreTest(OmemoStore<IdentityKeyPair, IdentityKey, PreKeyRecord, SignedPreKeyRecord, SessionRecord, SignalProtocolAddress, ECPublicKey, PreKeyBundle, SessionCipher> store)
        throws XmppStringprepException {
    super(store);
}
 
Example #18
Source File: XmppAxolotlSession.java    From Conversations with GNU General Public License v3.0 4 votes vote down vote up
public XmppAxolotlSession(Account account, SQLiteAxolotlStore store, SignalProtocolAddress remoteAddress) {
	this.cipher = new SessionCipher(store, remoteAddress);
	this.remoteAddress = remoteAddress;
	this.sqLiteAxolotlStore = store;
	this.account = account;
}
 
Example #19
Source File: SignalCachingOmemoStore.java    From Smack with Apache License 2.0 2 votes vote down vote up
/**
 * Create a new SignalCachingOmemoStore as a caching layer around a persisting OmemoStore
 * (eg. a SignalFileBasedOmemoStore).
 *
 * @param wrappedStore other store implementation that gets wrapped
 */
public SignalCachingOmemoStore(OmemoStore<IdentityKeyPair, IdentityKey, PreKeyRecord, SignedPreKeyRecord,
        SessionRecord, SignalProtocolAddress, ECPublicKey, PreKeyBundle, SessionCipher> wrappedStore) {
    super(wrappedStore);
}