Question

I'm following this tutorial to use 3DES encryption, and i needed to make some changes in cipher settings, so here's my code:

public class TripleDES {

public static int MAX_KEY_LENGTH = DESedeKeySpec.DES_EDE_KEY_LEN;
private static String ENCRYPTION_KEY_TYPE = "DESede";
private static String ENCRYPTION_ALGORITHM = "DESede/ECB/PKCS7Padding";
private final SecretKeySpec keySpec;
private final static String LOG = "TripleDES";

public TripleDES(String passphrase) {
    byte[] key;
    try {
        // get bytes representation of the password
        key = passphrase.getBytes("UTF8");
    } catch (UnsupportedEncodingException e) {
        throw new IllegalArgumentException(e);
    }

    key = padKeyToLength(key, MAX_KEY_LENGTH);
    key = addParity(key);
    keySpec = new SecretKeySpec(key, ENCRYPTION_KEY_TYPE);
}

// !!! - see post below
private byte[] padKeyToLength(byte[] key, int len) {
    byte[] newKey = new byte[len];
    System.arraycopy(key, 0, newKey, 0, Math.min(key.length, len));
    return newKey;
}

// standard stuff
public byte[] encrypt(String message) throws GeneralSecurityException, UnsupportedEncodingException {
    byte[] unencrypted = message.getBytes("UTF8");
    return doCipher(unencrypted, Cipher.ENCRYPT_MODE);
}

public byte[] decrypt(byte[] encrypted) throws GeneralSecurityException {
    return doCipher(encrypted, Cipher.DECRYPT_MODE);
}

private byte[] doCipher(byte[] original, int mode)
        throws GeneralSecurityException {
    Cipher cipher = Cipher.getInstance(ENCRYPTION_ALGORITHM);
    // IV = 0 is yet another issue, we'll ignore it here
    // IvParameterSpec iv = new IvParameterSpec(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 });
    cipher.init(mode, keySpec); //, iv);
    return cipher.doFinal(original);
}

// Takes a 7-byte quantity and returns a valid 8-byte DES key.
// The input and output bytes are big-endian, where the most significant
// byte is in element 0.
public static byte[] addParity(byte[] in) {
    byte[] result = new byte[8];

    // Keeps track of the bit position in the result
    int resultIx = 1;

    // Used to keep track of the number of 1 bits in each 7-bit chunk
    int bitCount = 0;

    // Process each of the 56 bits
    for (int i = 0; i < 56; i++) {
        // Get the bit at bit position i
        boolean bit = (in[6 - i / 8] & (1 << (i % 8))) > 0;

        // If set, set the corresponding bit in the result
        if (bit) {
            result[7 - resultIx / 8] |= (1 << (resultIx % 8)) & 0xFF;
            bitCount++;
        }

        // Set the parity bit after every 7 bits
        if ((i + 1) % 7 == 0) {
            if (bitCount % 2 == 0) {
                // Set low-order bit (parity bit) if bit count is even
                result[7 - resultIx / 8] |= 1;
            }
            resultIx++;
            bitCount = 0;
        }
        resultIx++;
    }

    Log.d(LOG, "result: " + result);
    return result;
}
}

But i'm getting InvalidKeyException on this line:

cipher.init(mode, keySpec);

LogCat:

W/System.err(758): java.security.InvalidKeyException: src.length=8 srcPos=8 dst.length=8 dstPos=0 length=8
W/System.err(758):  at org.bouncycastle.jce.provider.JCEBlockCipher.engineInit(JCEBlockCipher.java:584)
W/System.err(758):  at org.bouncycastle.jce.provider.JCEBlockCipher.engineInit(JCEBlockCipher.java:631)
W/System.err(758):  at javax.crypto.Cipher.init(Cipher.java:511)
W/System.err(758):  at javax.crypto.Cipher.init(Cipher.java:471)

I'm new on encrytion so i probably overlook something but i cannot find what it is. Any help is appreciated...

Was it helpful?

Solution 2

I've found solution by changing these lines:

try {
    // get bytes representation of the password
    key = passphrase.getBytes("UTF8");
} catch (UnsupportedEncodingException e) {
    throw new IllegalArgumentException(e);
}

key = padKeyToLength(key, MAX_KEY_LENGTH);
key = addParity(key);
keySpec = new SecretKeySpec(key, ENCRYPTION_KEY_TYPE);

into these:

Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
byte[] keyBytes = GetKeyAsBytes(key);
keySpec = new SecretKeySpec(keyBytes, "DESede");

while GetKeyAsBytes method is this:

public byte[] GetKeyAsBytes(String key) {
    byte[] keyBytes = new byte[24]; // a Triple DES key is a byte[24] array

    for (int i = 0; i < key.length() && i < keyBytes.length; i++) 
        keyBytes[i] = (byte) key.charAt(i);

    return keyBytes;
}

OTHER TIPS

Triple DES requires a 24 byte key, not an 8 byte one.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top