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.io.UnsupportedEncodingException; 024import java.security.InvalidAlgorithmParameterException; 025import java.security.InvalidKeyException; 026import java.security.NoSuchAlgorithmException; 027import java.security.NoSuchProviderException; 028import java.util.logging.Level; 029 030import javax.crypto.BadPaddingException; 031import javax.crypto.IllegalBlockSizeException; 032import javax.crypto.NoSuchPaddingException; 033 034import org.jivesoftware.smack.SmackException; 035import org.jivesoftware.smack.XMPPException; 036import org.jivesoftware.smack.XMPPException.XMPPErrorException; 037 038import org.jivesoftware.smackx.omemo.OmemoManager; 039import org.jivesoftware.smackx.omemo.OmemoService; 040import org.jivesoftware.smackx.omemo.OmemoStore; 041import org.jivesoftware.smackx.omemo.exceptions.CorruptedOmemoKeyException; 042import org.jivesoftware.smackx.omemo.internal.OmemoDevice; 043 044import org.whispersystems.libsignal.IdentityKey; 045import org.whispersystems.libsignal.IdentityKeyPair; 046import org.whispersystems.libsignal.SessionBuilder; 047import org.whispersystems.libsignal.SessionCipher; 048import org.whispersystems.libsignal.SignalProtocolAddress; 049import org.whispersystems.libsignal.UntrustedIdentityException; 050import org.whispersystems.libsignal.ecc.ECPublicKey; 051import org.whispersystems.libsignal.state.PreKeyBundle; 052import org.whispersystems.libsignal.state.PreKeyRecord; 053import org.whispersystems.libsignal.state.SessionRecord; 054import org.whispersystems.libsignal.state.SignedPreKeyRecord; 055 056/** 057 * Concrete implementation of the OmemoService using the Signal library. 058 * 059 * @author Paul Schaub 060 */ 061@SuppressWarnings("unused") 062public final class SignalOmemoService extends OmemoService<IdentityKeyPair, IdentityKey, PreKeyRecord, SignedPreKeyRecord, SessionRecord, SignalProtocolAddress, ECPublicKey, PreKeyBundle, SessionCipher> { 063 064 private static SignalOmemoService INSTANCE; 065 private static boolean LICENSE_ACKNOWLEDGED = false; 066 067 public static void setup() throws InvalidKeyException, XMPPErrorException, NoSuchPaddingException, InvalidAlgorithmParameterException, UnsupportedEncodingException, IllegalBlockSizeException, BadPaddingException, NoSuchAlgorithmException, NoSuchProviderException, SmackException, InterruptedException, CorruptedOmemoKeyException { 068 if (!LICENSE_ACKNOWLEDGED) { 069 throw new IllegalStateException("smack-omemo-signal is licensed under the terms of the GPLv3. Please be aware that you " + 070 "can only use this library within the terms of the GPLv3. See for example " + 071 "https://www.gnu.org/licenses/quick-guide-gplv3 for more details. Please call " + 072 "SignalOmemoService.acknowledgeLicense() prior to the setup() method in order to prevent " + 073 "this exception."); 074 } 075 if (INSTANCE == null) { 076 INSTANCE = new SignalOmemoService(); 077 } 078 setInstance(INSTANCE); 079 } 080 081 @Override 082 public OmemoStore<IdentityKeyPair, IdentityKey, PreKeyRecord, SignedPreKeyRecord, SessionRecord, SignalProtocolAddress, ECPublicKey, PreKeyBundle, SessionCipher> createDefaultOmemoStoreBackend() { 083 return new SignalFileBasedOmemoStore(); 084 } 085 086 private SignalOmemoService() 087 throws SmackException, InterruptedException, XMPPException.XMPPErrorException, CorruptedOmemoKeyException, 088 NoSuchPaddingException, InvalidAlgorithmParameterException, UnsupportedEncodingException, 089 IllegalBlockSizeException, BadPaddingException, NoSuchAlgorithmException, NoSuchProviderException, 090 java.security.InvalidKeyException { 091 super(); 092 } 093 094 public static void acknowledgeLicense() { 095 LICENSE_ACKNOWLEDGED = true; 096 } 097 098 @Override 099 protected void processBundle(OmemoManager omemoManager, PreKeyBundle preKeyBundle, OmemoDevice contact) throws CorruptedOmemoKeyException { 100 SignalOmemoStoreConnector connector = new SignalOmemoStoreConnector(omemoManager, getOmemoStoreBackend()); 101 SessionBuilder builder = new SessionBuilder(connector, connector, connector, connector, 102 getOmemoStoreBackend().keyUtil().omemoDeviceAsAddress(contact)); 103 try { 104 builder.process(preKeyBundle); 105 LOGGER.log(Level.INFO, "Session built with " + contact); 106 getOmemoStoreBackend().getOmemoSessionOf(omemoManager, contact); //method puts session in session map. 107 } catch (org.whispersystems.libsignal.InvalidKeyException e) { 108 throw new CorruptedOmemoKeyException(e.getMessage()); 109 } catch (UntrustedIdentityException e) { 110 // This should never happen. 111 throw new AssertionError(e); 112 } 113 } 114}