# Behaviour of Cipher class in JCE

Ian Clysdale (iclysdal@calum.csclub.uwaterloo.ca)
Thu, 18 Sep 1997 10:54:53 -0400 (EDT)

- Messages sorted by: [ date ][ thread ][ subject ][ author ]
- Next message: George Chung: "RE: Certificate chaining w/javakey generated DSA certificates"
- Previous message: George Chung: "RE: Certificate chaining w/javakey generated DSA certificates"

    From: Ian Clysdale <iclysdal@calum.csclub.uwaterloo.ca>

    Message-Id: <199709181454.KAA28256@calum.csclub.uwaterloo.ca>

    Subject: Behaviour of Cipher class in JCE

    To: java-security@web2.javasoft.com

    Date: Thu, 18 Sep 1997 10:54:53 -0400 (EDT)

Dear Sir/Madam:
I've been working at implementing a simple cipher algorithm following
the CAST-128 protocol (RFC 2144). My algorithm implements (or perhaps I
should say attempts to implement) its own buffering and padding. However,
although I pass up messages to the Cipher super-class during construction of
my Cipher, the Cipher class does not seem to receive them. When I pass in
block-aligned data, the engineCrypt() method is not called at all. When I pass
in non-block-aligned data, outBufferSize() raises an exception since the
data is not block-aligned.
Is it actually possible to implement buffering and padding in the current
version of the JCE (May 1, 1997 release)? If so, what am I doing wrong? I have
included sample code for a very simple minimalist cipher which attempts to
perform its own padding and buffering:

Thanks a lot,
ian
-------------------------
/* Cipher Code : Conforms to JCE. */

package provider.test;

import java.security.*;

public class CipherTest
extends Cipher
implements SymmetricCipher
{
final int BLOCK_SIZE=8;

/* Constructor: */

public CipherTest() {
// Implement padding and buffering. Security provider is Provider.
super(true,true,"ProviderTest");
}

/* SPI Requirements: */
protected int engineBlockSize() {
return BLOCK_SIZE;
}

protected int engineOutBufferSize(int inLen, boolean isFinal) {
// In a theoretical world, return the size of the buffer based
// on the length of the input, and whether or not it is the final
// data.

// Return something just for the sake of it.
return BLOCK_SIZE;
}
protected void engineInitEncrypt(Key key) throws InvalidKeyException {
System.out.println("Performing key scheduling, setting state value to ENCRYPT.");
}

protected void engineInitDecrypt(Key key) throws InvalidKeyException {
System.out.println("Performing key scheduling, setting state value to DECRYPT.");
}

protected int engineUpdate(byte in[],int inOff,int inLen,byte out[],int outOff) {
System.out.println("Performing actual encryption/decryption.");
// Since we didn't actually do anything, say so.
return 0;
}

protected int engineCrypt(byte out[], int offset) {
// Since we are over-riding the buffering, as we told the super-class
// at time of construction, this should always be run.

System.out.println("Cleaning up, flushing the buffer.");

// Since we didn't actually do anything...
return 0;
}
}

-------------------------

/* Provider Code. Conforms to JCE 1.1. */

package provider.test;

public final class ProviderTest extends java.security.Provider {
public ProviderTest() {
super("ProviderTest",0.1,"Ian's Test of JCE Cipher behaviour.");

put("Cipher.CipherTest","provider.test.CipherTest");
}
}

-------------------------

package provider.test;

import java.security.Cipher;
import sun.security.provider.SecretKey;

class Driver {

Driver() {
byte[] FortyBitKey = new byte[] { 1, 2, 3, 4, 5 };
byte[] BlockAligned = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
byte[] NotAligned = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
byte[] Storage;
try {
// Get the cipher.
Cipher c=Cipher.getInstance("CipherTest","ProviderTest");

// Create the Key
SecretKey testKey=new SecretKey(FortyBitKey, "TestCipher");

// Perform a test encryption on both the block-aligned and the
// non-block-aligned data.

c.initEncrypt(testKey);
Storage=c.crypt(BlockAligned);
Storage=c.crypt(NotAligned);

// Perform a test decryption on the block-aligned data.
// (Since we perform padding, all data to be decrypted should
// be block-aligned.)

c.initDecrypt(testKey);
Storage=c.crypt(BlockAligned);
Storage=c.crypt(NotAligned);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
ProviderTest pt=new ProviderTest();
java.security.Security.addProvider(pt);
Driver x=new Driver();
}
}

-----------------------------------------

As output from executing Driver(), I receive :

-----------------------------------------
Performing key scheduling, setting state value to ENCRYPT.
Performing actual encryption/decryption.
java.security.IllegalBlockSizeException: Input data length not a multiple of blocksize.
at java.security.Cipher.outBufferSize(Cipher.java:417)
at java.security.Cipher.outBufferSize(Cipher.java:392)
at java.security.Cipher.crypt(Cipher.java:520)
at java.security.Cipher.crypt(Cipher.java:497)
at provider.test.Driver.<init>(Driver.java:26)
at provider.test.Driver.main(Driver.java:42)
-----------------------------------------

Note the lack of a message from engineCrypt() and the exception.

- Next message: George Chung: "RE: Certificate chaining w/javakey generated DSA certificates"
- Previous message: George Chung: "RE: Certificate chaining w/javakey generated DSA certificates"