001/** 002 * 003 * Copyright 2017 Paul Schaub 004 * 005 * This file is part of smack-omemo-signal. 006 * 007 * smack-omemo-signal is free software; you can redistribute it and/or modify 008 * it under the terms of the GNU General Public License as published by 009 * the Free Software Foundation; either version 3 of the License, or 010 * (at your option) any later version. 011 * 012 * This program is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 015 * GNU General Public License for more details. 016 * 017 * You should have received a copy of the GNU General Public License 018 * along with this program; if not, write to the Free Software Foundation, 019 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 020 */ 021package org.jivesoftware.smackx.omemo.signal; 022 023import java.util.logging.Level; 024 025import org.jivesoftware.smackx.omemo.OmemoManager; 026import org.jivesoftware.smackx.omemo.OmemoService; 027import org.jivesoftware.smackx.omemo.OmemoStore; 028import org.jivesoftware.smackx.omemo.exceptions.CorruptedOmemoKeyException; 029import org.jivesoftware.smackx.omemo.internal.OmemoDevice; 030 031import org.whispersystems.libsignal.IdentityKey; 032import org.whispersystems.libsignal.IdentityKeyPair; 033import org.whispersystems.libsignal.SessionBuilder; 034import org.whispersystems.libsignal.SessionCipher; 035import org.whispersystems.libsignal.SignalProtocolAddress; 036import org.whispersystems.libsignal.UntrustedIdentityException; 037import org.whispersystems.libsignal.ecc.ECPublicKey; 038import org.whispersystems.libsignal.state.PreKeyBundle; 039import org.whispersystems.libsignal.state.PreKeyRecord; 040import org.whispersystems.libsignal.state.SessionRecord; 041import org.whispersystems.libsignal.state.SignedPreKeyRecord; 042 043/** 044 * Concrete implementation of the OmemoService using the Signal library. 045 * 046 * @author Paul Schaub 047 */ 048@SuppressWarnings("unused") 049public final class SignalOmemoService 050 extends OmemoService<IdentityKeyPair, IdentityKey, PreKeyRecord, SignedPreKeyRecord, SessionRecord, 051 SignalProtocolAddress, ECPublicKey, PreKeyBundle, SessionCipher> { 052 053 private static SignalOmemoService INSTANCE; 054 private static boolean LICENSE_ACKNOWLEDGED = false; 055 056 @Override 057 protected SignalOmemoRatchet instantiateOmemoRatchet( 058 OmemoManager manager, 059 OmemoStore<IdentityKeyPair, IdentityKey, PreKeyRecord, SignedPreKeyRecord, SessionRecord, 060 SignalProtocolAddress, ECPublicKey, PreKeyBundle, SessionCipher> store) { 061 062 return new SignalOmemoRatchet(manager, getOmemoStoreBackend()); 063 } 064 065 public static void setup() { 066 if (!LICENSE_ACKNOWLEDGED) { 067 throw new IllegalStateException("smack-omemo-signal is licensed under the terms of the GPLv3. " + 068 "Please be aware that you can only use this library within the terms of the GPLv3. " + 069 "See for example https://www.gnu.org/licenses/quick-guide-gplv3 for more details. Please call " + 070 "SignalOmemoService.acknowledgeLicense() prior to the setup() method in order to prevent " + 071 "this exception."); 072 } 073 if (INSTANCE == null) { 074 INSTANCE = new SignalOmemoService(); 075 } 076 setInstance(INSTANCE); 077 } 078 079 @Override 080 public OmemoStore<IdentityKeyPair, IdentityKey, PreKeyRecord, SignedPreKeyRecord, SessionRecord, 081 SignalProtocolAddress, ECPublicKey, PreKeyBundle, SessionCipher> 082 createDefaultOmemoStoreBackend() { 083 return new SignalCachingOmemoStore(); 084 } 085 086 private SignalOmemoService() { 087 super(); 088 } 089 090 public static void acknowledgeLicense() { 091 LICENSE_ACKNOWLEDGED = true; 092 } 093 094 @Override 095 protected void processBundle(OmemoManager omemoManager, 096 PreKeyBundle contactsBundle, 097 OmemoDevice contactsDevice) 098 throws CorruptedOmemoKeyException { 099 100 SignalOmemoStoreConnector connector = new SignalOmemoStoreConnector(omemoManager, getOmemoStoreBackend()); 101 SessionBuilder builder = new SessionBuilder(connector, connector, connector, connector, 102 SignalOmemoStoreConnector.asAddress(contactsDevice)); 103 try { 104 builder.process(contactsBundle); 105 LOGGER.log(Level.FINE, "Session built with " + contactsDevice); 106 } catch (org.whispersystems.libsignal.InvalidKeyException e) { 107 throw new CorruptedOmemoKeyException(e); 108 } catch (UntrustedIdentityException e) { 109 // This should never happen. 110 throw new AssertionError(e); 111 } 112 } 113}