Wednesday, July 31, 2013

Introducing EScript - scripting for your IDE

During the last years I was playing around with a scripting engine supporting JavaScript that is directly integrated in Eclipse. This engine is used as a basis for my RCPs to allow users to create their own workflow.

I thought this might come in handy for others too, so I raised bug 365133. In the meantime I was able to extend the framework and added other interpreters as well. Currently Rhino, JRuby and Jython are supported (some better, some worse).

Hoping to get feedback from the community (you!) I release this project into the wild. Check out the project homepage, or dive directly into the source at github.


"What can I do with such an engine?", you may ask.
At my company we use it to automate test equipment, create test patterns and accumulate test results. Therefore we need to commuinicate with lots of lab equipment like oscilloscopes, RFID readers and so on. As our work flows are very dynamic, we provide a script environment along with command sets to easily access these devices. Our users may then create their dedicated tests by implementing their own scripts.

By creating libraries (which are independent of the used interpreter!)  you may extend the script languages with your own functionality. Find an example at the EScript homepage.

You may also access any class available in your IDE and directly call methods on it.


All source is available under EPL terms. Drop me a line if you find it useful or need some support.
Please be aware that despite the Rhino implementation is available for quite some time, other interpreters were added just recently. So be prepared for some surprises :)

Wednesday, July 17, 2013

Tycho 10: Signing plugins and executables

Eclipse supports signed plugins and displays this information in its Installation Details. On Mac and Windows you might further want to sign your executable to get rid of potential warnings when launching your application. All this can be done automatically with tycho. To get a general overview how to build a product with tycho, see my previous tutorials on this topic:

Tycho Tutorials

For a list of all tycho related tutorials see Tycho Tutorials Overview

Source code for this tutorial is available on github as a single zip archive, as a Team Project Set or you can browse the files online.

Before we start signing stuff, we need a certificate. In our example, we will use a self-signed certificate, you will probably want to go for one from a certification authority.

Step 1: Creating a self signed certificate

There exist lots of tutorials out there, how to sign jar files with a self-signed certificate. I suggest you pick one and try to sign a jar file for test purposes. Here are the two commands needed to create the certificate, which can be executed in a shell:
$JAVA_HOME/bin/keytool -genkey -keyalg RSA -sigalg SHA1withRSA -keystore C:\userdata\workspaces\blog\com.codeandme.tycho.releng\sample.keystore -alias eve -dname "CN=Eve, OU=none, O=example, L=somewhere, ST=earth, C=ea, EMAILADDRESS=eve@example.com"

Enter keystore password: verystrong
Re-enter new password: verystrong
Enter key password for <eve>
        (RETURN if same as keystore password): secret
Re-enter new password: secret

$JAVA_HOME/bin/keytool -selfcert -keystore C:\userdata\workspaces\blog\com.codeandme.tycho.releng\sample.keystore -alias eve
(I always preferred Eve over Alice and Bob...)

The email address field seems to be necessary (thanks for the comment), see this message on stackoverflow

Step 2: Signing jar files with tycho

Signing will be done by the maven-jarsigner-plugin. Open the master pom located in com.codeandme.tycho.releng (see previous tutorials) and add following plugin section to it.
   <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jarsigner-plugin</artifactId>
    <version>1.2</version>
    <configuration>
     <keystore>${basedir}/../com.codeandme.tycho.releng/blog.keystore</keystore>
     <storepass>verystrong</storepass>
     <alias>eve</alias>
     <keypass>secret</keypass>
    </configuration>
    <executions>
     <execution>
      <id>sign</id>
      <goals>
       <goal>sign</goal>
      </goals>
     </execution>
    </executions>
   </plugin>
Set your passwords and the path to your keystore and run your maven build. Congratulations, you have signed your jars successfully.

Step 3: Create a code signing certificate for windows

Creating a self-signed certificate for your windows executable is not very useful unless you add your CA (we will create this in a second) to the trusted root certificates on the target machines. So this might be valid for a setup in a closed environment but not when your software is downloaded from the internet. In the latter case you need to buy a certificate from one of the big CAs (see this thread for some cheap ones).

Nevertheless for our test purposes such a certificate will do, so lets create one following this description on stackoverflow. We need to install Windows SDK, so download and run the installer. On the Install Options page select Windows Native Code Development/Tools, we do not need anything else for signing. After the installer is done you should find signtool.exe in C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin.

To create a code signing certificate, startup a command shell:
"C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\makecert.exe" -r -pe -n "CN=Eve" -ss CA -sr CurrentUser -a sha256 -cy authority -sky signature -sv SampleCA.pvk SampleCA.cer
"C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\makecert.exe" -pe -n "CN=Eve" -a sha256 -cy end -sky signature -ic SampleCA.cer -iv SampleCA.pvk -sv SampleSPC.pvk SampleSPC.cer
"C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\pvk2pfx.exe" -pvk SampleCA.pvk -spc SampleCA.cer -pfx SampleCA.pfx
"C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\signtool.exe" sign /v /f SampleCA.pfx /t http://timestamp.verisign.com/scripts/timstamp.dll Application.exe
  • Line 1 creates a root CA. You will be asked for a Subject Key twice. This is the key for your CA. Lets use "verystrong".
  • Line 2 creates a signing certificate using the root CA. The Subject Key is now the key for our signing certificate. So use a different one to that before (eg. "secret"). You will also be asked for an Issuer Signature, which refers to the Subject Key of step 1 ("verystrong").
  • Line 3 converts our certificate into pfx format. Again you need the Subject Key of step 1 ("verystrong").
  • Line 4 signs a fictional file Application.exe with our key.

To verify that signing worked you can open the Properties dialog of your executable and examine Digital Signatures.
    Step 4: Integrate signing in maven build

    For signing our executable we need to run the external signtool.exe by using the exec-maven-plugin. Open com.example.tycho.releng.product/pom.xml and add a new plugin section with following content:
       <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>exec-maven-plugin</artifactId>
        <version>1.2.1</version>
        <executions>
         <execution>
          <id>exec</id>
          <phase>package</phase>
          <goals>
           <goal>exec</goal>
          </goals>
         </execution>
        </executions>
        <configuration>
         <executable>C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\signtool.exe</executable>
         <arguments>
          <argument>sign</argument>
          <argument>/v</argument>
          <argument>/f</argument>
          <argument>C:\UserData\Workspaces\Blog\om.codeandme.tycho.releng\SampleCA.pfx</argument>
          <argument>/t</argument>
          <argument>http://timestamp.verisign.com/scripts/timstamp.dll</argument>
          <argument>${project.build.directory}\products\tycho.product\win32\win32\x86\eclipse.exe</argument>
         </arguments>
        </configuration>
       </plugin>
    
    Make sure you have no line breaks in your xml nodes!

    For MacOS this should work similar. To my knowledge you would just have to use another signing application.

    Tuesday, July 2, 2013

    Writing your own JCA extensions - a full cipher

    So you have managed to create your own cipher. Great! Now lets go for the real thing and implement a cipher.

    Basically ciphers are implemented similar to digests. But while digests can be used without any security restrictions, ciphers need to be signed when used with JCA. In more detail your cipher implementation must reside in a signed jar file. To sign you need a code signing certificate from Oracle. Application for such a certificate is free of charge, but will take approximately 2 weeks to be processed. You will not get it for fun either as you have to provide your use case.

    For the exact procedure follow Oracles step by step guide. To follow the tutorial below I expect you to have your certificate ready. Otherwise you might do the coding but will not be able to use your provider afterwards.

    Source code for this tutorial is available on googlecode as a single zip archive, as a Team Project Set or you can checkout the SVN projects directly.

    Step 1: Create key classes

    We wil create a Caesar cipher implementation. You could also do ROT13 with it. As ciphers are about encryption/decryption we need some keys. Our key class will be very simple as we just need to store an offset for shifting our letters later on.

    Start by creating a new Java Project named com.example.jce.cipher. Then implement the key class com.example.jce.provider.CaesarKey:
    package com.example.jce.cipher;
    
    import javax.crypto.SecretKey;
    
    public class CaesarKey implements SecretKey {
     private static final long serialVersionUID = -542084808194990775L;
    
     private byte mValue;
    
     public CaesarKey(byte value) {
      // converts any value to [0, 26), even negative ones
      mValue = (byte) (((value % 26) + 26) % 26);
     }
    
     @Override
     public String getAlgorithm() {
      return "Caesar";
     }
    
     @Override
     public String getFormat() {
      return getAlgorithm() + " format";
     }
    
     @Override
     public byte[] getEncoded() {
      return new byte[] { mValue };
     }
    }
    
    You may also implement a key generator that creates random keys on demand. This is not mandatory for our example but may be useful sometimes. The generator is implemented in com.example.jce.cipher.CaesarkeyGenerator:
    package com.example.jce.cipher;
    
    import java.security.InvalidAlgorithmParameterException;
    import java.security.SecureRandom;
    import java.security.spec.AlgorithmParameterSpec;
    
    import javax.crypto.KeyGeneratorSpi;
    import javax.crypto.SecretKey;
    
    public class CaesarKeyGenerator extends KeyGeneratorSpi {
    
     SecureRandom mRandomSource;
    
     public void engineInit(SecureRandom sr) {
      mRandomSource = sr;
     }
    
     public void engineInit(AlgorithmParameterSpec ap, SecureRandom sr) throws InvalidAlgorithmParameterException {
      throw new InvalidAlgorithmParameterException("No parameters supported in this class");
     }
    
     public SecretKey engineGenerateKey() {
      if (mRandomSource == null)
       mRandomSource = new SecureRandom();
    
      return new CaesarKey((byte) Math.abs(mRandomSource.nextInt()));
     }
    
     @Override
     protected void engineInit(int arg0, SecureRandom sr) {
      engineInit(sr);
     }
    }
    
    Step 2: Implement the cipher

    Ciphers are implemented extending CipherSpi (as all JCA extensions extend a WhateverSpi class). Implement com.example.jce.cipher.CaesarCipher as follows:
    package com.example.jce.cipher;
    
    import java.security.AlgorithmParameters;
    import java.security.InvalidAlgorithmParameterException;
    import java.security.InvalidKeyException;
    import java.security.Key;
    import java.security.NoSuchAlgorithmException;
    import java.security.SecureRandom;
    import java.security.spec.AlgorithmParameterSpec;
    
    import javax.crypto.BadPaddingException;
    import javax.crypto.Cipher;
    import javax.crypto.CipherSpi;
    import javax.crypto.IllegalBlockSizeException;
    import javax.crypto.NoSuchPaddingException;
    import javax.crypto.ShortBufferException;
    
    public class CaesarCipher extends CipherSpi {
    
     private Key mKey;
     private int mOPMode;
    
     @Override
     protected byte[] engineDoFinal(byte[] input, int inputOffset, int inputLen) throws IllegalBlockSizeException, BadPaddingException {
      return engineUpdate(input, inputOffset, inputLen);
     }
    
     @Override
     protected int engineDoFinal(byte[] input, int inputOffset, int inputLen, byte[] output, int outputOffset) throws ShortBufferException,
       IllegalBlockSizeException, BadPaddingException {
      return engineUpdate(input, inputOffset, inputLen, output, outputOffset);
     }
    
     @Override
     protected int engineGetBlockSize() {
      return 1;
     }
    
     @Override
     protected byte[] engineGetIV() {
      return null;
     }
    
     @Override
     protected int engineGetOutputSize(int inputLen) {
      return 0;
     }
    
     @Override
     protected AlgorithmParameters engineGetParameters() {
      return null;
     }
    
     @Override
     protected void engineInit(int opmode, Key key, SecureRandom random) throws InvalidKeyException {
      mOPMode = opmode;
    
      if (key instanceof CaesarKey)
       mKey = key;
    
      else
       throw new InvalidKeyException("Caesar cipher needs a Caesar key");
     }
    
     @Override
     protected void engineInit(int opmode, Key key, AlgorithmParameterSpec params, SecureRandom random) throws InvalidKeyException,
       InvalidAlgorithmParameterException {
      engineInit(opmode, key, random);
     }
    
     @Override
     protected void engineInit(int opmode, Key key, AlgorithmParameters params, SecureRandom random) throws InvalidKeyException,
       InvalidAlgorithmParameterException {
      engineInit(opmode, key, random);
     }
    
     @Override
     protected void engineSetMode(String mode) throws NoSuchAlgorithmException {
      throw new NoSuchAlgorithmException();
     }
    
     @Override
     protected void engineSetPadding(String pading) throws NoSuchPaddingException {
      throw new NoSuchPaddingException();
     }
    
     @Override
     protected byte[] engineUpdate(byte[] input, int inputOffset, int inputLen) {
      byte[] output = new byte[inputLen];
      try {
       engineUpdate(input, inputOffset, inputLen, output, 0);
      } catch (ShortBufferException e) {
       // output buffer is always big enough
      }
    
      return output;
     }
    
     @Override
     protected int engineUpdate(byte[] input, int inputOffset, int inputLen, byte[] output, int outputOffset) throws ShortBufferException {
      if (output.length - outputOffset < inputLen)
       throw new ShortBufferException("Buffer too short to hold encrypted data");
    
      for (int index = inputOffset; index < inputOffset + inputLen; index++)
       output[outputOffset + index - inputOffset] = twistCharacter(input[index], getKey());
    
      return inputLen;
     }
    
     private byte getKey() {
      // calculate key depending on encryption/decryption
      if (mOPMode == Cipher.ENCRYPT_MODE)
       return mKey.getEncoded()[0];
    
      // decode using inverse key
      return (byte) (26 - mKey.getEncoded()[0]);
     }
    
     private byte twistCharacter(byte data, byte key) {
    
      if (Character.isLetter(data)) {
       // only operate on characters, leave everything else as-is
       if (Character.isLowerCase(data))
        return (byte) (((data - 'a' + key) % 26) + 'a');
       else
        return (byte) (((data - 'A' + key) % 26) + 'A');
      }
    
      return data;
     }
    
     @Override
     protected int engineGetKeySize(Key key) throws InvalidKeyException {
      if (key instanceof CaesarKey)
       return 1;
    
      throw new InvalidKeyException("Caesar cipher needs a Caesar key");
     }
    }
    
    This is a straight forward implementation that will encode characters only. Everything else like digits or punctuation will remain unchanged.

    Step 3: Create a JCE provider

    As for the digest, we need to usa a provider to register our digest in the JRE. Create a new class com.example.jce.cipher.CaesarProvider:
    package com.example.jce.cipher;
    
    import java.security.Provider;
    
    public class CaesarProvider extends Provider {
    
     private static final long serialVersionUID = -67123468605911408L;
    
     public CaesarProvider() {
      super("Caesar Cipher", 1.0, "Caesar cipher v1.0");
    
      put("KeyGenerator.Caesar", CaesarKeyGenerator.class.getName());
      put("Cipher.Caesar", CaesarCipher.class.getName());
     }
    }
    At this point we need the certificate requested from Oracle, because a cipher class needs to be nested in a signed jar file. If you do not have such a certificate your quest ends here...

    For all the others: export the project as a JAR file and sign it using jarsigner along with your certificate. The commandline looks something like this:
    jarsigner -keystore <store location> -storepass <store master password> <JAR file> <keystore alias>

    Step 4: Using our provider

    Create a new Java project com.example.jce.cipher.consumer. Create a subfolder libs and store your signed JAR file there. Then add this JAR to the Java Build Path.

    Now everything is in place to use our cipher:
     public static void main(String[] args) {
      // adding provider dynamically
      Security.addProvider(new CaesarProvider());
    
      try {
       String message = "Hello World";
       Cipher c = Cipher.getInstance("Caesar");
       SecretKey key = new CaesarKey((byte) 2);
       System.out.println("Message:   " + message);
    
       c.init(Cipher.ENCRYPT_MODE, key);
       byte[] encrypted = c.doFinal(message.getBytes());
       System.out.println("Encrypted: " + new String(encrypted));
    
       c.init(Cipher.DECRYPT_MODE, key);
       byte[] decrypted = c.doFinal(encrypted);
       System.out.println("Decrypted: " + new String(decrypted));
    
      } catch (Exception e) {
       e.printStackTrace();
      }
     }

    Further reading

    If you intend to implement your own stuff you should have a look at these links: