SignalOmemoKeyUtil.java

  1. /**
  2.  *
  3.  * Copyright 2017 Paul Schaub
  4.  *
  5.  * This file is part of smack-omemo-signal.
  6.  *
  7.  * smack-omemo-signal is free software; you can redistribute it and/or modify
  8.  * it under the terms of the GNU General Public License as published by
  9.  * the Free Software Foundation; either version 3 of the License, or
  10.  * (at your option) any later version.
  11.  *
  12.  * This program is distributed in the hope that it will be useful,
  13.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.  * GNU General Public License for more details.
  16.  *
  17.  * You should have received a copy of the GNU General Public License
  18.  * along with this program; if not, write to the Free Software Foundation,
  19.  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
  20.  */
  21. package org.jivesoftware.smackx.omemo.signal;

  22. import java.io.IOException;
  23. import java.util.List;
  24. import java.util.TreeMap;

  25. import org.jivesoftware.smackx.omemo.element.OmemoBundleElement;
  26. import org.jivesoftware.smackx.omemo.exceptions.CorruptedOmemoKeyException;
  27. import org.jivesoftware.smackx.omemo.internal.OmemoDevice;
  28. import org.jivesoftware.smackx.omemo.trust.OmemoFingerprint;
  29. import org.jivesoftware.smackx.omemo.util.OmemoKeyUtil;

  30. import org.whispersystems.libsignal.IdentityKey;
  31. import org.whispersystems.libsignal.IdentityKeyPair;
  32. import org.whispersystems.libsignal.InvalidKeyException;
  33. import org.whispersystems.libsignal.ecc.Curve;
  34. import org.whispersystems.libsignal.ecc.ECPublicKey;
  35. import org.whispersystems.libsignal.state.PreKeyBundle;
  36. import org.whispersystems.libsignal.state.PreKeyRecord;
  37. import org.whispersystems.libsignal.state.SessionRecord;
  38. import org.whispersystems.libsignal.state.SignedPreKeyRecord;
  39. import org.whispersystems.libsignal.util.KeyHelper;

  40. /**
  41.  * Concrete implementation of the KeyUtil for an implementation using the Signal library.
  42.  *
  43.  * @author Paul Schaub
  44.  */
  45. public class SignalOmemoKeyUtil extends OmemoKeyUtil<IdentityKeyPair, IdentityKey, PreKeyRecord, SignedPreKeyRecord,
  46.         SessionRecord, ECPublicKey, PreKeyBundle> {

  47.     @Override
  48.     public IdentityKeyPair generateOmemoIdentityKeyPair() {
  49.         return KeyHelper.generateIdentityKeyPair();
  50.     }

  51.     @Override
  52.     public TreeMap<Integer, PreKeyRecord> generateOmemoPreKeys(int currentPreKeyId, int count) {
  53.         List<PreKeyRecord> preKeyRecords = KeyHelper.generatePreKeys(currentPreKeyId, count);
  54.         TreeMap<Integer, PreKeyRecord> map = new TreeMap<>();
  55.         for (PreKeyRecord p : preKeyRecords) {
  56.             map.put(p.getId(), p);
  57.         }
  58.         return map;
  59.     }

  60.     @Override
  61.     public SignedPreKeyRecord generateOmemoSignedPreKey(IdentityKeyPair identityKeyPair, int currentPreKeyId)
  62.             throws CorruptedOmemoKeyException {
  63.         try {
  64.             return KeyHelper.generateSignedPreKey(identityKeyPair, currentPreKeyId);
  65.         } catch (InvalidKeyException e) {
  66.             throw new CorruptedOmemoKeyException(e);
  67.         }
  68.     }

  69.     @Override
  70.     public SignedPreKeyRecord signedPreKeyFromBytes(byte[] data) throws IOException {
  71.         if (data == null) return null;
  72.         return new SignedPreKeyRecord(data);
  73.     }

  74.     @Override
  75.     public byte[] signedPreKeyToBytes(SignedPreKeyRecord signedPreKeyRecord) {
  76.         return signedPreKeyRecord.serialize();
  77.     }

  78.     @Override
  79.     public SessionRecord rawSessionFromBytes(byte[] data) throws IOException {
  80.         if (data == null) return null;
  81.         return new SessionRecord(data);
  82.     }

  83.     @Override
  84.     public byte[] rawSessionToBytes(SessionRecord session) {
  85.         return session.serialize();
  86.     }

  87.     @Override
  88.     public IdentityKeyPair identityKeyPairFromBytes(byte[] data) throws CorruptedOmemoKeyException {
  89.         if (data == null) return null;
  90.         try {
  91.             return new IdentityKeyPair(data);
  92.         } catch (InvalidKeyException e) {
  93.             throw new CorruptedOmemoKeyException(e);
  94.         }
  95.     }

  96.     @Override
  97.     public IdentityKey identityKeyFromBytes(byte[] data) throws CorruptedOmemoKeyException {
  98.         if (data == null) return null;
  99.         try {
  100.             return new IdentityKey(data, 0);
  101.         } catch (InvalidKeyException e) {
  102.             throw new CorruptedOmemoKeyException(e);
  103.         }
  104.     }

  105.     @Override
  106.     public ECPublicKey ellipticCurvePublicKeyFromBytes(byte[] data) throws CorruptedOmemoKeyException {
  107.         if (data == null) return null;
  108.         try {
  109.             return Curve.decodePoint(data, 0);
  110.         } catch (InvalidKeyException e) {
  111.             throw new CorruptedOmemoKeyException(e);
  112.         }
  113.     }

  114.     @Override
  115.     public byte[] preKeyToBytes(PreKeyRecord preKeyRecord) {
  116.         return preKeyRecord.serialize();
  117.     }

  118.     @Override
  119.     public PreKeyRecord preKeyFromBytes(byte[] bytes) throws IOException {
  120.         if (bytes == null) return null;
  121.         return new PreKeyRecord(bytes);
  122.     }

  123.     @Override
  124.     public PreKeyBundle bundleFromOmemoBundle(OmemoBundleElement bundle, OmemoDevice contact, int preKeyId)
  125.             throws CorruptedOmemoKeyException {
  126.         return new PreKeyBundle(0,
  127.                 contact.getDeviceId(),
  128.                 preKeyId,
  129.                 BUNDLE.preKeyPublic(bundle, preKeyId),
  130.                 BUNDLE.signedPreKeyId(bundle),
  131.                 BUNDLE.signedPreKeyPublic(bundle),
  132.                 BUNDLE.signedPreKeySignature(bundle),
  133.                 BUNDLE.identityKey(bundle));
  134.     }

  135.     @Override
  136.     public byte[] signedPreKeySignatureFromKey(SignedPreKeyRecord signedPreKey) {
  137.         return signedPreKey.getSignature();
  138.     }

  139.     @Override
  140.     public int signedPreKeyIdFromKey(SignedPreKeyRecord signedPreKey) {
  141.         return signedPreKey.getId();
  142.     }

  143.     @Override
  144.     public byte[] identityKeyPairToBytes(IdentityKeyPair identityKeyPair) {
  145.         return identityKeyPair.serialize();
  146.     }

  147.     @Override
  148.     public IdentityKey identityKeyFromPair(IdentityKeyPair identityKeyPair) {
  149.         return identityKeyPair.getPublicKey();
  150.     }

  151.     @Override
  152.     public byte[] identityKeyForBundle(IdentityKey identityKey) {
  153.         return identityKey.getPublicKey().serialize();
  154.     }

  155.     @Override
  156.     public byte[] identityKeyToBytes(IdentityKey identityKey) {
  157.         return identityKey.serialize();
  158.     }

  159.     @Override
  160.     public byte[] preKeyPublicKeyForBundle(ECPublicKey preKey) {
  161.         return preKey.serialize();
  162.     }

  163.     @Override
  164.     public byte[] preKeyForBundle(PreKeyRecord preKeyRecord) {
  165.         return preKeyRecord.getKeyPair().getPublicKey().serialize();
  166.     }

  167.     @Override
  168.     public byte[] signedPreKeyPublicForBundle(SignedPreKeyRecord signedPreKey) {
  169.         return signedPreKey.getKeyPair().getPublicKey().serialize();
  170.     }

  171.     @Override
  172.     public OmemoFingerprint getFingerprintOfIdentityKey(IdentityKey identityKey) {
  173.         if (identityKey == null) {
  174.             return null;
  175.         }

  176.         String fp = identityKey.getFingerprint();
  177.         // Cut "(byte)0x" prefixes, remove spaces and commas, cut first two digits.
  178.         fp = fp.replace("(byte)0x", "").replace(",", "")
  179.                 .replace(" ", "").substring(2);
  180.         return new OmemoFingerprint(fp);
  181.     }

  182.     @Override
  183.     public OmemoFingerprint getFingerprintOfIdentityKeyPair(IdentityKeyPair identityKeyPair) {
  184.         if (identityKeyPair == null) {
  185.             return null;
  186.         }
  187.         return getFingerprintOfIdentityKey(identityKeyPair.getPublicKey());
  188.     }
  189. }