fixes for otr file transfer

iNPUTmice created

Change summary

src/eu/siacs/conversations/utils/CryptoHelper.java                |  8 
src/eu/siacs/conversations/xmpp/jingle/JingleFile.java            | 14 
src/eu/siacs/conversations/xmpp/jingle/JingleSocks5Transport.java | 35 
src/eu/siacs/conversations/xmpp/jingle/JingleTransport.java       | 15 
4 files changed, 49 insertions(+), 23 deletions(-)

Detailed changes

src/eu/siacs/conversations/utils/CryptoHelper.java 🔗

@@ -5,9 +5,9 @@ import java.nio.charset.Charset;
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 import java.security.SecureRandom;
+import java.util.Arrays;
 
 import eu.siacs.conversations.entities.Account;
-
 import android.util.Base64;
 
 public class CryptoHelper {
@@ -28,7 +28,11 @@ public class CryptoHelper {
 	}
 	
 	public static byte[] hexToBytes(String hexString) {
-		return new BigInteger(hexString, 16).toByteArray();
+		byte[] array = new BigInteger(hexString, 16).toByteArray();
+		if (array[0] == 0) {
+			array = Arrays.copyOfRange(array, 1, array.length);
+		}
+		return array;
 	}
 
 	public static String saslPlain(String username, String password) {

src/eu/siacs/conversations/xmpp/jingle/JingleFile.java 🔗

@@ -25,7 +25,11 @@ public class JingleFile extends File {
 	}
 	
 	public long getExpectedSize() {
-		return this.expectedSize;
+		if (this.aeskey!=null) {
+			return (this.expectedSize/16 + 1) * 16;
+		} else {
+			return this.expectedSize;
+		}
 	}
 	
 	public void setExpectedSize(long size) {
@@ -41,18 +45,18 @@ public class JingleFile extends File {
 	}
 	
 	public void setKey(byte[] key) {
-		Log.d("xmppService","using aes key "+CryptoHelper.bytesToHex(key));
 		if (key.length>=32) {
 			byte[] secretKey = new byte[32];
 			System.arraycopy(key, 0, secretKey, 0, 32);
-			this.aeskey = new SecretKeySpec(key, "AES");
+			this.aeskey = new SecretKeySpec(secretKey, "AES");
 		} else if (key.length>=16) {
-			byte[] secretKey = new byte[15];
+			byte[] secretKey = new byte[16];
 			System.arraycopy(key, 0, secretKey, 0, 16);
-			this.aeskey = new SecretKeySpec(key, "AES");
+			this.aeskey = new SecretKeySpec(secretKey, "AES");
 		} else {
 			Log.d("xmppService","weird key");
 		}
+		Log.d("xmppService","using aes key "+CryptoHelper.bytesToHex(this.aeskey.getEncoded()));
 	}
 	
 	public Key getKey() {

src/eu/siacs/conversations/xmpp/jingle/JingleSocks5Transport.java 🔗

@@ -6,6 +6,7 @@ import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.io.ObjectInputStream.GetField;
 import java.net.Socket;
 import java.net.UnknownHostException;
 import java.security.MessageDigest;
@@ -97,17 +98,16 @@ public class JingleSocks5Transport extends JingleTransport {
 					digest.reset();
 					fileInputStream = getInputStream(file);
 					int count;
-					long txbytes = 0;
+					long txBytes = 0;
 					byte[] buffer = new byte[8192];
-					while ((count = fileInputStream.read(buffer)) != -1) {
-						txbytes += count;
+					while ((count = fileInputStream.read(buffer)) > 0) {
+						txBytes += count;
 						outputStream.write(buffer, 0, count);
 						digest.update(buffer, 0, count);
-						Log.d("xmppService","tx bytes: "+txbytes);
 					}
+					Log.d("xmppService","txBytes="+txBytes);
 					outputStream.flush();
 					file.setSha1Sum(CryptoHelper.bytesToHex(digest.digest()));
-					//outputStream.close();
 					if (callback!=null) {
 						callback.onFileTransmitted(file);
 					}
@@ -115,7 +115,8 @@ public class JingleSocks5Transport extends JingleTransport {
 					// TODO Auto-generated catch block
 					e.printStackTrace();
 				} catch (IOException e) {
-					Log.d("xmppService","io exception: "+e.getMessage());
+					// TODO Auto-generated catch block
+					e.printStackTrace();
 				} catch (NoSuchAlgorithmException e) {
 					// TODO Auto-generated catch block
 					e.printStackTrace();
@@ -149,26 +150,32 @@ public class JingleSocks5Transport extends JingleTransport {
 					long remainingSize = file.getExpectedSize();
 					byte[] buffer = new byte[8192];
 					int count = buffer.length;
-					//while(remainingSize > 0) {
-					while((count = inputStream.read(buffer)) > 0) {
-						Log.d("xmppService","remaining size: "+remainingSize+" reading "+count+" bytes");
+					long rxBytes = 0;
+					while(remainingSize > 0) {
 						count = inputStream.read(buffer);
-						if (count!=-1) {
+						if (count==-1) {
+							Log.d("xmppService","read end");
+						} else {
+							rxBytes += count;
 							fileOutputStream.write(buffer, 0, count);
 							digest.update(buffer, 0, count);
+							remainingSize-=count;
 						}
-						remainingSize-=count;
 					}
+					Log.d("xmppService","rx bytes="+rxBytes);
 					fileOutputStream.flush();
 					fileOutputStream.close();
 					file.setSha1Sum(CryptoHelper.bytesToHex(digest.digest()));
 					callback.onFileTransmitted(file);
 				} catch (FileNotFoundException e) {
-					Log.d("xmppService","file not found exception");
+					// TODO Auto-generated catch block
+					e.printStackTrace();
 				} catch (IOException e) {
-					Log.d("xmppService","io exception: "+e.getMessage());
+					// TODO Auto-generated catch block
+					e.printStackTrace();
 				} catch (NoSuchAlgorithmException e) {
-					Log.d("xmppService","no such algo"+e.getMessage());
+					// TODO Auto-generated catch block
+					e.printStackTrace();
 				}
 			}
 		}).start();

src/eu/siacs/conversations/xmpp/jingle/JingleTransport.java 🔗

@@ -5,6 +5,7 @@ import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.security.InvalidAlgorithmParameterException;
 import java.security.InvalidKeyException;
 import java.security.NoSuchAlgorithmException;
 
@@ -12,6 +13,7 @@ import javax.crypto.Cipher;
 import javax.crypto.CipherOutputStream;
 import javax.crypto.CipherInputStream;
 import javax.crypto.NoSuchPaddingException;
+import javax.crypto.spec.IvParameterSpec;
 
 import android.util.Log;
 
@@ -19,14 +21,16 @@ public abstract class JingleTransport {
 	public abstract void connect(final OnTransportConnected callback);
 	public abstract void receive(final JingleFile file, final OnFileTransmitted callback);
 	public abstract void send(final JingleFile file, final OnFileTransmitted callback);
+	private byte[] iv = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0xf};
 	
 	protected InputStream getInputStream(JingleFile file) throws FileNotFoundException {
 		if (file.getKey() == null) {
 			return new FileInputStream(file);
 		} else {
 			try {
+				IvParameterSpec ips = new IvParameterSpec(iv);
 				Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
-				cipher.init(Cipher.ENCRYPT_MODE, file.getKey());
+				cipher.init(Cipher.ENCRYPT_MODE, file.getKey(),ips);
 				Log.d("xmppService","opening encrypted input stream");
 				return new CipherInputStream(new FileInputStream(file), cipher);
 			} catch (NoSuchAlgorithmException e) {
@@ -38,6 +42,9 @@ public abstract class JingleTransport {
 			} catch (InvalidKeyException e) {
 				Log.d("xmppService","invalid key: "+e.getMessage());
 				return null;
+			} catch (InvalidAlgorithmParameterException e) {
+				Log.d("xmppService","invavid iv:"+e.getMessage());
+				return null;
 			}
 		}
 	}
@@ -47,8 +54,9 @@ public abstract class JingleTransport {
 			return new FileOutputStream(file);
 		} else {
 			try {
+				IvParameterSpec ips = new IvParameterSpec(iv);
 				Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
-				cipher.init(Cipher.DECRYPT_MODE, file.getKey());
+				cipher.init(Cipher.DECRYPT_MODE, file.getKey(),ips);
 				Log.d("xmppService","opening encrypted output stream");
 				return new CipherOutputStream(new FileOutputStream(file), cipher);
 			} catch (NoSuchAlgorithmException e) {
@@ -60,6 +68,9 @@ public abstract class JingleTransport {
 			} catch (InvalidKeyException e) {
 				Log.d("xmppService","invalid key: "+e.getMessage());
 				return null;
+			} catch (InvalidAlgorithmParameterException e) {
+				Log.d("xmppService","invavid iv:"+e.getMessage());
+				return null;
 			}
 		}
 	}