SSHTools Knowledgebase
Information and FAQs about SSHTools products
  
Search  
   
Browse by Category
SSHTools Knowledgebase .: SSHD Maverick .: Configuring Maverick SSHD to use JCE

Configuring Maverick SSHD to use JCE

Pre-Requisite
Maverick SSH Daemon API
SSH Client

Resources
Sun JCE - JCE framework and provider http://java.sun.com/products/jce/index.jsp
Bouncy Caslte JCE Third party cryptographic service provider http://www.bouncycastle.org

What It Does
The Maverick SSHD API enables the development of robust, high performance SSH-enabled server applications. This feature-rich API can be used to custom-build a server to suit each user or organisations specific security-related needs. In this series of articles we show the reader step-by-step how to introduce increasingly more advanced functionality into their Maverick SSH Server; by the end of which the user should have a fully working and functionality-rich SSH server application.

This second tutorial covers the encryption algorithms employed by the Maverick SSH server and introduces the reader to the JCE framework. By the end of this tutorial the reader should be able to install third party JCE cryptographic service.

How It Works
Maverick Crypto
In the previous article we created a secure SFTP compatible SSH server, no direct code was ever written to handle protection of data simply because we chose to rely on the default functionality employed by the SSHDaemon base class. As was previously mentioned this base class performs all the complex processing required for a SSH server to operate successfully, one of these many tasks is encrypting and decrypting data transmissions, ciphering.

The default implementation utilises the cipher algorithms implemented by the com.maverick.ssh2 package and cover the following algorithms:

BlowfishCbc (cipher)
TripleDesCbc (cipher)
MD5 (message authentication)
SHA1 (message authentication)
Diffie-Hellman SHA1 (key exchange)

The code snippet below can be added to the configuration method to specifiy a particular cipher,

    context.setPreferredCipherCS(context.CIPHER_TRIPLEDES_CBC);
    context.setPreferredCipherSC(context.CIPHER_BLOWFISH_CBC);
    System.out.println(context.getPreferredCipherCS());
    System.out.println(context.getPreferredCipherSC());

The standard default ciphers installed are 3DES and Blowfish block ciphers however the API also supports a number of optional ciphers:

aes128-cbc
aes192-cbc
aes256-cbc
twofish128-cbc
twofish192-cbc
twofish256-cbc
cast128-cbc

If no JCE is enabled then these are dynamically loaded at runtime and can be used by using the ConfigurationContxt::setPreferredSC(String) and ConfigurationContxt::setPreferredCS(String) as above using the names listed above.

    context.setPreferredCipherSC("cast128-cbc");

The AbstractComponentFactory::list(String preferred) method returns a list of supported ciphers,

    System.out.println("Supported ciphers: "+context.supportedCiphers().list(""));

Fig1. Maverick supported ciphers

As can be seen, all com.sshtools.cipher algorithms are already available.

Optionally these can be installed by adding the sshtools-cipher.jar to your class path and using the following code within the configure method.

 // import the cipher package
import com.sshtools.cipher.*;

 // Add AES
 context.supportedCiphers().add(AES128Cbc.AES128_CBC, AES128Cbc.class);
 context.supportedCiphers().add(AES192Cbc.AES192_CBC, AES192Cbc.class);
 context.supportedCiphers().add(AES256Cbc.AES256_CBC, AES256Cbc.class);

 // Add Twofish - note the 256 bit cipher has two different entries to maintain backwards compatibility
 context.supportedCiphers().add(Twofish128Cbc.TWOFISH128_CBC, Twofish128Cbc.class);
 context.supportedCiphers().add(Twofish192Cbc.TWOFISH192_CBC, Twofish192Cbc.class);
 context.supportedCiphers().add(Twofish256Cbc.TWOFISH256_CBC, Twofish256Cbc.class);
 context.supportedCiphers().add(Twofish256Cbc.TWOFISH_CBC, Twofish256Cbc.class);

 // Add CAST
  context.supportedCiphers().add(CAST128Cbc.CAST128_CBC, CAST128Cbc.class);

Ciphers
In cryptography encryption is the process of obscuring information to make it unreadable without special knowledge, this unreadable cipher string is created using various mathematical algorithms known as a cipher. If no cipher is specified within the configuration method then the server uses the default AES128-cbc block cipher.

AES128-cbc, known also as Rijndael (pronounced Rhine-Dahl) is a symmetric block cipher widely recognised and used in commercial and government organisations. A block cipher works on a fixed length block of data; in this instance 128-bit blocks. The cipher takes 128-bit plaintext and equates an equivalent 128-bit block of encrypted text, cipher text. To decrypt the message the cipher takes a 128-bit blocks of cipher text and reproduces the original 128-bit plaintext; with the entire transformation being controlled by a secret key.

Fig2. Block cipher uses secret key to control transformation

JCE
So far we have seen how to utilise the ciphers available as part of the com.maverick.ssh2 and com.sshtools.cipher packages, there are a good number available but our server is still somewhat limited to using only those maintained within the API itself.

However, the latest releases of the API saw the introduction of the com.sshtools.jce package which aims to overcome this obstacle. The com.sshtools.jce package and in particular its JCEProviderMapping class enables the server to install and use any external cryptographic implementation available that follows the open JCE standard, from implementations offered by opensource vendors to commercially available ones and even JCE providers written by oneself increasing the flexibility of the API considerably.

JCE (Java Cryptography Extension) was developed at Sun Microsystems as a lightweight encryption framework; essentially it is a set of packages and implementations for performing cryptographic tasks as data encryption, key generation and agreement, and message authentication.

fig.3 JDK ext directory listing

As the above directory listing shows, the JCE framework sunjce_provider.jar comes bundled as part of JDK1.4 and above, for earlier versions of the JDK the JCE can be downloaded as an additional package, refer to the sun website for further installation instructions.

Getting the server to start using the JCE framework is very simply, the changes necessary are all done before we even instantiate our server.

  public static void main(String[] args) throws Exception {
      org.apache.log4j.BasicConfigurator.configure();
  
      LicenseManager.addLicense("----BEGIN SSHTools LICENSE----...");
      
      JCEProviderMapping.enableJCEProvider(true);

      ExampleSSHD sshd = new ExampleSSHD();      
      sshd.startup();      
   }

The JCEProviderMapping::enableJCEProvider(boolean) method takes a boolean which simply denotes whether the JCE framework should be turned on or off and inversely override the J2SSH API cryptographic libraries.

The JCE API consists of numerous classes and interfaces for working with many kinds of algorithms and security features. Now that we have installed it we can either rely on the default algorithms or request a particular algorithm through ConfigurationContext::setPreferredCipherCS(String name) and ConfigurationContext::setPreferredCipherSC(String name). In both cases the Maverick API ciphers will be bypassed and the new default SunJCE implementations will be used.

Bouncy Castle
The default behaviour when a JCE is in use is to request all algorithm implementations without specifying a provider, this enables the JCE to work with the Sun reference and SunJCE providers, we are not limited to using the SunJCE provider other third party providers can be installed and used in the same manner though any provider used in this default state must implement a minimum set of algorithms:

DESede/CBC/NoPadding (Cipher)Blowfish/CBC/NoPadding (Cipher)
MD5 (Digest)SHA-1 (Digest)
HmacSha1 (HMAC)HmacMD5 (HMAC)
RSA (Public key)DSA (Public key)
SHA1withRSA (Signature)SHA1withDSA (Signature)

Note: The names of these algorithms follow the JCE transformation naming convention, algorithm/mode/padding and algorithm which simply refers to default mode and padding.

For this article the Bouncy Castle JCE, a free and widely recognised provider, will be used. Using the Bouncy Castle provider is a very simple process, firstly the Bouncy Castle jar file needs to be included into the project libraries, this can be found at the Bouncy Castle homepage, please refer to the Pre-requisite section for a link.

Once installed all we need to do is instantiate the provider and set it as the default provider.

try { Class cls = Class.forName("org.bouncycastle.jce.provider.BouncyCastleProvider"); Security.addProvider((java.security.Provider) cls.newInstance()); JCEProviderMapping.enableJCEProvider("BC"); log.info("Using JCE BC Provider"); p = Security.getProvider("BC"); System.out.println(p.getInfo());

By using JCEProviderMapping.enableJCEProvider("BC") we instantly inform the server that the Bouncy Castle JCE will be used for all algorithms.

Note: The SSH protocol only supports the default ciphers and key exchange algorithms that were listed earlier in this section, if one looks at the Bouncy Castle provider it contains many more cryptographic algorithms, unfortunately these are not supported.

Maverick Crypto Support
As of SunJCE 1.5 AES has been included as a standard cipher, to use the Bouncy Castle equivelant is simply a matter of using the AbstractJCECipher class. The abstract class is used to define SSH2 ciphers which use a JCE provider instead of the internal Maverick Crypto provider.

As the example below shows, all we need to do is create a new class that implements the AbstractJCECipher class.

import com.sshtools.jce.AbstractJCECipher;

public class AES256Cbc extends AbstractJCECipher {
public AES256Cbc() {

    super("AES/CBC/NoPadding", "AES", 32, "aes256-cbc");

  }
}

We can apply this to any cipher available through the com.maverick.ssh2 and com.sshtools.cipher packages as long as these are supported in the JCE version.

import com.sshtools.jce.AbstractJCECipher;

public class Twofish128Cbc extends AbstractJCECipher {
public Twofish128Cbc() {

    super("Twofish/CBC/NoPadding", "Twofish", 32, "Twofish128Cbc");

  }
}

Once these classes have been created they can be included in our SSH server implementation,

    context.supportedCiphers().add("aes128-cbc", AES128Cbc.class);
    context.supportedCiphers().add("aes192-cbc", AES192Cbc.class);
    context.supportedCiphers().add("Twofish128-cbc", Twofish128Cbc.class);
    
    context.setPreferredCipherSC("aes128-cbc");
    context.setPreferredCipherCS("Twofish128-cbc");
    
    System.out.println("Client->Server cipher "+context.getPreferredCipherCS());
    System.out.println(("Servier->Client cipher "+context.getPreferredCipherSC());
    
    System.out.println("Supported ciphers: "+context.supportedCiphers().list(""));
    log.info("Configuration complete.");

As the above snippet from the configuration method shows, we call the context.supportedCiphers().add("Twofish128-cbc", Twofish128Cbc.class); method to load the cipher and then use the context.setPreferredCipherCS("Twofish128-cbc"); to set this as our preferred cipher. Once running the context will load the equivalent JCE provider implementation.

The AES128-cbc cipher has already been implemented in version 1.2.8 of the J2SSH API so there is no need to create an additional class as we done above, we simply add the AES128Cbc as a supported cipher.

Import com.sshtools.jce.AES128Cbc;
...
context.supportedCiphers().add("aes128-cbc", AES128Cbc.class);

As the above snippet points out, the class must be imported before we can use it.

Future releases of the API should see the remaining AES ciphers become standard implementations.

Multiple Providers
We dont have to use Bouncy Castle as our sole provider, in fact we can combine both the sun provider and Bouncy Castle.

try {
        Class cls = Class.forName("org.bouncycastle.jce.provider.BouncyCastleProvider");
        Security.addProvider((java.security.Provider) cls.newInstance());
        
        for (int i = 0; i < Security.getProviders().length; i++) {
            log.info(Security.getProviders()[i].getName() + " security provider found");

       JCEProviderMapping.enableJCEProvider(true);
       JCEProviderMapping.setProviderForAlgorithm("JCEProviderMapping.Blowfish/CBC/NoPadding", "BC");       

       log.info("Using JCE BC Provider");

Above we inform the server through the method JCEProviderMapping::setProviderForAlgorithm that the Bouncy Castle implementation of the block cipher blowfish should be used over the Sun version.

The JCE orders the providers in the order they have been loaded which means that the provider loaded first will take precedents when finding an implementation over all the others. The Security class can be used to determine which cryptographic provider is used as the main provider,

   System.out.println(Security.getProperty("security.provider.1"));

The secuirty.provider property is suffixed with a number detailing the order of the provider, in this example 1 is used to denote the first provider in the list.

To change the main provider we can use the Security::setProperty(String, String) method,

       Security.setProperty("security.provider.1", "org.bouncycastle.jce.provider.BouncyCastleProvider");
       System.out.println(Security.getProperty("security.provider.1"));

That's all there is to it!

Communication
Now that we have enabled our SSH server to use the JCE framework we can use any external cryptographic algorithm implementations from other providers as Bouncy Castle not just for ciphers as seen in this article but also for key exchange, ConfigurationContext::setPreferredPublicKey(String name), and message authentication, ConfigurationContext::setPreferredMacSC(String), Configuration::setPreferredMacCS(String).

How To Run This Code
This attached zip file contains several source files. Unzip these into a new Java project and build.

2005 SSHTools Ltd, All Rights Reserved


How helpful was this article to you?

User Comments

Add Comment
No comments have been posted.


powered by Lore
© 2008 SSHTools Ltd. All Rights Reserved