12 December 2008

VirtualBox host interface networking on Ubuntu

For 99% of my work I can use Ubuntu. But for some bad software I need Windows because that software is even not running in Wine. For that purpose I have set up a Windows virtual machine using VirtualBox.

Installing VirtualBox on Ubuntu is very easy:
sudo apt-get install virtualbox-ose virtualbox-ose-modules-`uname -r`
You can now create virtual machines in GUI mode with VirtualBox. Your virtual machine uses NAT networking by default. Most internet and networking applications can work well with that. But some Windows applications still use NetBIOS functionality instead of TCP/IP and that is not routable. To get NetBIOS work, you need to configure your virtual machine to use host interface networking.

For host interface networking you need to configure a network bridge. Because I am not a network specialist, I have googled around, tried many options and ended in the setup I am describing now. Maybe it is not really the best way to do this, however it is working well.
  • edit /etc/network/interfaces:
    sudo vi /etc/network/interfaces
    • remove all lines referring to eth0 (assuming this is the active NIC) and insert the lines below:
      auto br0
      iface br0 inet dhcp
      bridge_ports eth0
      bridge_fd 9
      bridge_hello 2
      bridge_maxage 12
      bridge_stp off

      auto eth0
      iface eth0 inet manual
  • restart networking:
    sudo /etc/init.d/networking restart

  • create virtual NIC:
    sudo VBoxAddIF vbox1 $USER br0
  • edit VirtualBox interfaces config:
    sudo bash -c "echo \"vbox1 $USER br0\" > /etc/vbox/interfaces"
  • setup your (Windows) guest to use host interface networking with device vbox1 now

29 November 2008

Flash 10 player problems in Ubuntu 8.10 Intrepid

I last upgraded my Ubuntu (Linux) 8.04 laptop to Ubuntu 8.10 Intrepid. As usual it was a problemless upgrade; I only had to setup my VPN connection again because it was all integrated now in NetworkManager. But within a day I saw my browser (Firefox 3.0) did not play Flash anymore.

Firefox served the "plugin install" dialog. I installed the Adobe Flash player, but I was not able to get the Adobe Flash player running. The GNash player was I nightmare; very slow and much content not playing at all. Even a manual download from the Adobe site did not help.

After some googling I seemed to be the only one with this problem. But found a hint: look at ldd output.
Finally I downloaded and installed the deb-package from Adobe again:
    wget -c http://fpdownload.macromedia.com/get/flashplayer/current/install_flash_player_10_linux.deb
sudo dpkg -i install_flash_player_10_linux.deb

I ran the ldd command:
    ldd /usr/lib/adobe-flashplugin/libflashplayer.so

The output showed that some libraries were missing. I could fix that by installing a needed package:
    sudo apt-get install libnss3-1d

And creating some symbolic links after that:
    cd /usr/lib
sudo ln -s libnss3.so.1d libnss3.so
sudo ln -s libsmime3.so.1d libsmime3.so
sudo ln -s libssl3.so.1d libssl3.so

And I could again view Flash 10 movies as before!

01 October 2008

PHP encrypt and Java decrypt

For a project I needed to transfer data from a PHP server to a Java server. The data was a PHP array and it must be serialized in a portable way. Because it must be transferred safely, I needed encryption. And because encrypted data is binary data and has to be transferred in the query part of the URL, I needed encoding.

At the sender side I had to do this steps:
  • Serialization: For transferring data structures between different programming languages I like JSON. JSON encoding is small and easy to implement; you can find libraries for almost each language.
  • Encryption: I tried to decrypt a PHP Crypt_RSA encrypted string with Java, but PHP and Java were behaving slightly different. I could not manage to get it working. After a failed attempt with Crypt_Blowfish I searched the internet again. And I found a file-based solution, so I decided to use AES encryption.
  • Encoding: The most common string encoding to use for binary data is Base64 encoding. However Java does not have native support for it, there are enough libraries. You still have to urlencode the resulting string.
At the receiver side I did the opposite steps:
  • Decoding: Urldecoding depending of your servlet engine. Base64 decoding with an Apache library.
  • Decryption: AES decryption.
  • Deserialization: Converting the JSON string to a native Java object using a JSON library.

The code

For testing I used this PHP code to encrypt on the command-line:
<?php
if ($_SERVER['argc'] != 2) {

file_put_contents('php://stderr',
"ERROR: specify one string to be encrypted\n\n");
exit(
1);
}
// set keys
$secret_key = "1234567890123456";
$iv = "abcdefghijklmnop";
$plaintext = $_SERVER['argv'][1];
// encryption
$enc = mcrypt_encrypt(MCRYPT_RIJNDAEL_128,
$secret_key, $plaintext, MCRYPT_MODE_CBC, $iv);
// base64 encoding
$enc64 = base64_encode($enc);
echo
$enc64 . "\n";
?>

And this Java code to decrypt on the command-line:
import java.io.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import org.apache.commons.codec.binary.Base64;

public class decrypt {

public static void main(String args[]) throws Exception {
if (args.length != 1) {
System.err.println("ERROR: specify a base64 encoded encrypted string as parameter\n");
System.exit(1);
}
// define keys
String secret = new String("HQ5s-YmCzwwhjIcH");
String iv = new String("mZsewcXovdHVMRsE");
// base64 decoding
int i = 0;
String enc64 = args[0];
byte[] enc64bytes = enc64.getBytes();
byte[] dec64bytes = Base64.decodeBase64(enc64bytes);
// because the toString method does not work you have to cast each array element separately
String dec64 = new String();
for (i = 0; i < dec64bytes.length; i++) {
dec64 += (char)dec64bytes[i];
}
// set decrypt params
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
SecretKeySpec keySpec = new SecretKeySpec(secret.getBytes(), "AES");
IvParameterSpec ivSpec = new IvParameterSpec(iv.getBytes());
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
ByteArrayInputStream fis = new ByteArrayInputStream(dec64bytes);
CipherInputStream cis = new CipherInputStream(fis, cipher);
ByteArrayOutputStream fos = new ByteArrayOutputStream();
// decrypting
byte[] b = new byte[8];
while ((i = cis.read(b)) != -1) {
fos.write(b, 0, i);
}
fos.flush();
fos.close();
cis.close();
fis.close();
System.out.println(fos.toString());
}

}

I have studied long on why the base64 decoded byte array could not be converted to a string with the toString method. I think Java supposes it is a Unicode string because it is binary and then I get too few character. Use the loop it is ok, because that handles each character separately. If your source is binary, you should consider to use a loop instead of the fos.toString() call.