diff options
Diffstat (limited to 'src/main/java/de/pixart/messenger/crypto/axolotl/XmppAxolotlMessage.java')
-rw-r--r-- | src/main/java/de/pixart/messenger/crypto/axolotl/XmppAxolotlMessage.java | 209 |
1 files changed, 94 insertions, 115 deletions
diff --git a/src/main/java/de/pixart/messenger/crypto/axolotl/XmppAxolotlMessage.java b/src/main/java/de/pixart/messenger/crypto/axolotl/XmppAxolotlMessage.java index cfa6a275e..6fbf8c3dc 100644 --- a/src/main/java/de/pixart/messenger/crypto/axolotl/XmppAxolotlMessage.java +++ b/src/main/java/de/pixart/messenger/crypto/axolotl/XmppAxolotlMessage.java @@ -37,69 +37,13 @@ public class XmppAxolotlMessage { private static final String KEYTYPE = "AES"; private static final String CIPHERMODE = "AES/GCM/NoPadding"; private static final String PROVIDER = "BC"; - + private final List<XmppAxolotlSession.AxolotlKey> keys; + private final Jid from; + private final int sourceDeviceId; private byte[] innerKey; private byte[] ciphertext = null; private byte[] authtagPlusInnerKey = null; private byte[] iv = null; - private final List<XmppAxolotlSession.AxolotlKey> keys; - private final Jid from; - private final int sourceDeviceId; - - public static class XmppAxolotlPlaintextMessage { - private final String plaintext; - private final String fingerprint; - - XmppAxolotlPlaintextMessage(String plaintext, String fingerprint) { - this.plaintext = plaintext; - this.fingerprint = fingerprint; - } - - public String getPlaintext() { - return plaintext; - } - - - public String getFingerprint() { - return fingerprint; - } - } - - public static class XmppAxolotlKeyTransportMessage { - private final String fingerprint; - private final byte[] key; - private final byte[] iv; - - XmppAxolotlKeyTransportMessage(String fingerprint, byte[] key, byte[] iv) { - this.fingerprint = fingerprint; - this.key = key; - this.iv = iv; - } - - public String getFingerprint() { - return fingerprint; - } - - public byte[] getKey() { - return key; - } - - public byte[] getIv() { - return iv; - } - } - - public static int parseSourceId(final Element axolotlMessage) throws IllegalArgumentException { - final Element header = axolotlMessage.findChild(HEADER); - if (header == null) { - throw new IllegalArgumentException("No header found"); - } - try { - return Integer.parseInt(header.getAttribute(SOURCEID)); - } catch (NumberFormatException e) { - throw new IllegalArgumentException("invalid source id"); - } - } private XmppAxolotlMessage(final Element axolotlMessage, final Jid from) throws IllegalArgumentException { this.from = from; @@ -148,6 +92,18 @@ public class XmppAxolotlMessage { this.innerKey = generateKey(); } + public static int parseSourceId(final Element axolotlMessage) throws IllegalArgumentException { + final Element header = axolotlMessage.findChild(HEADER); + if (header == null) { + throw new IllegalArgumentException("No header found"); + } + try { + return Integer.parseInt(header.getAttribute(SOURCEID)); + } catch (NumberFormatException e) { + throw new IllegalArgumentException("invalid source id"); + } + } + public static XmppAxolotlMessage fromElement(Element element, Jid from) { return new XmppAxolotlMessage(element, from); } @@ -164,12 +120,28 @@ public class XmppAxolotlMessage { } private static byte[] generateIv() { - SecureRandom random = new SecureRandom(); - byte[] iv = new byte[16]; + final SecureRandom random = new SecureRandom(); + byte[] iv = new byte[Config.TWELVE_BYTE_IV ? 12 : 16]; random.nextBytes(iv); return iv; } + private static byte[] getPaddedBytes(String plaintext) { + int plainLength = plaintext.getBytes().length; + int pad = Math.max(64, (plainLength / 32 + 1) * 32) - plainLength; + SecureRandom random = new SecureRandom(); + int left = random.nextInt(pad); + int right = pad - left; + StringBuilder builder = new StringBuilder(plaintext); + for (int i = 0; i < left; ++i) { + builder.insert(0, random.nextBoolean() ? "\t" : " "); + } + for (int i = 0; i < right; ++i) { + builder.append(random.nextBoolean() ? "\t" : " "); + } + return builder.toString().getBytes(); + } + public boolean hasPayload() { return ciphertext != null; } @@ -189,39 +161,13 @@ public class XmppAxolotlMessage { System.arraycopy(this.innerKey, 0, authtagPlusInnerKey, 0, this.innerKey.length); this.ciphertext = ciphertext; } - } catch (NoSuchAlgorithmException e) { - throw new CryptoFailedException(e); - } catch (NoSuchPaddingException e) { - throw new CryptoFailedException(e); - } catch (InvalidKeyException e) { - throw new CryptoFailedException(e); - } catch (IllegalBlockSizeException e) { - throw new CryptoFailedException(e); - } catch (BadPaddingException e) { - throw new CryptoFailedException(e); - } catch (NoSuchProviderException e) { - throw new CryptoFailedException(e); - } catch (InvalidAlgorithmParameterException e) { + } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException + | IllegalBlockSizeException | BadPaddingException | NoSuchProviderException + | InvalidAlgorithmParameterException e) { throw new CryptoFailedException(e); } } - private static byte[] getPaddedBytes(String plaintext) { - int plainLength = plaintext.getBytes().length; - int pad = Math.max(64, (plainLength / 32 + 1) * 32) - plainLength; - SecureRandom random = new SecureRandom(); - int left = random.nextInt(pad); - int right = pad - left; - StringBuilder builder = new StringBuilder(plaintext); - for (int i = 0; i < left; ++i) { - builder.insert(0, random.nextBoolean() ? "\t" : " "); - } - for (int i = 0; i < right; ++i) { - builder.append(random.nextBoolean() ? "\t" : " "); - } - return builder.toString().getBytes(); - } - public Jid getFrom() { return this.from; } @@ -297,19 +243,19 @@ public class XmppAxolotlMessage { byte[] key = unpackKey(session, sourceDeviceId); if (key != null) { try { - if (key.length >= 32) { - int authtaglength = key.length - 16; - Log.d(Config.LOGTAG, "found auth tag as part of omemo key"); - byte[] newCipherText = new byte[key.length - 16 + ciphertext.length]; - byte[] newKey = new byte[16]; - System.arraycopy(ciphertext, 0, newCipherText, 0, ciphertext.length); - System.arraycopy(key, 16, newCipherText, ciphertext.length, authtaglength); - System.arraycopy(key, 0, newKey, 0, newKey.length); - ciphertext = newCipherText; - key = newKey; + if (key.length < 32) { + throw new OutdatedSenderException("Key did not contain auth tag. Sender needs to update their OMEMO client"); } - - Cipher cipher = Compatibility.twentyEight() ? Cipher.getInstance(CIPHERMODE) : Cipher.getInstance(CIPHERMODE, PROVIDER); + final int authTagLength = key.length - 16; + byte[] newCipherText = new byte[key.length - 16 + ciphertext.length]; + byte[] newKey = new byte[16]; + System.arraycopy(ciphertext, 0, newCipherText, 0, ciphertext.length); + System.arraycopy(key, 16, newCipherText, ciphertext.length, authTagLength); + System.arraycopy(key, 0, newKey, 0, newKey.length); + ciphertext = newCipherText; + key = newKey; + + final Cipher cipher = Compatibility.twentyEight() ? Cipher.getInstance(CIPHERMODE) : Cipher.getInstance(CIPHERMODE, PROVIDER); SecretKeySpec keySpec = new SecretKeySpec(key, KEYTYPE); IvParameterSpec ivSpec = new IvParameterSpec(iv); @@ -318,22 +264,55 @@ public class XmppAxolotlMessage { String plaintext = new String(cipher.doFinal(ciphertext)); plaintextMessage = new XmppAxolotlPlaintextMessage(Config.OMEMO_PADDING ? plaintext.trim() : plaintext, session.getFingerprint()); - } catch (NoSuchAlgorithmException e) { - throw new CryptoFailedException(e); - } catch (NoSuchPaddingException e) { - throw new CryptoFailedException(e); - } catch (InvalidKeyException e) { - throw new CryptoFailedException(e); - } catch (InvalidAlgorithmParameterException e) { - throw new CryptoFailedException(e); - } catch (IllegalBlockSizeException e) { - throw new CryptoFailedException(e); - } catch (BadPaddingException e) { - throw new CryptoFailedException(e); - } catch (NoSuchProviderException e) { + } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException + | InvalidAlgorithmParameterException | IllegalBlockSizeException + | BadPaddingException | NoSuchProviderException e) { throw new CryptoFailedException(e); } } return plaintextMessage; } + + public static class XmppAxolotlPlaintextMessage { + private final String plaintext; + private final String fingerprint; + + XmppAxolotlPlaintextMessage(String plaintext, String fingerprint) { + this.plaintext = plaintext; + this.fingerprint = fingerprint; + } + + public String getPlaintext() { + return plaintext; + } + + + public String getFingerprint() { + return fingerprint; + } + } + + public static class XmppAxolotlKeyTransportMessage { + private final String fingerprint; + private final byte[] key; + private final byte[] iv; + + XmppAxolotlKeyTransportMessage(String fingerprint, byte[] key, byte[] iv) { + this.fingerprint = fingerprint; + this.key = key; + this.iv = iv; + } + + public String getFingerprint() { + return fingerprint; + } + + public byte[] getKey() { + return key; + } + + public byte[] getIv() { + return iv; + } + } }
\ No newline at end of file |