Frage

I got this piece of code:

static ReadableByteChannel readChannel = null;
static WritableByteChannel writeChannel = null;
static SecretKey key = makeKeyFromPassword("chuj".getBytes());

public static SecretKey makeKeyFromPassword(byte[] password) {

    try {
        key = KeyGenerator.getInstance("DES").generateKey();
        byte[] encoded = key.getEncoded();
        return new SecretKeySpec(encoded, "DES");
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    return null;
}

public static void run(int mode) throws Exception {
    ByteBuffer readBuffer = ByteBuffer.allocate(1024);
    ByteBuffer writeBuffer = ByteBuffer.allocate(1024);

    //initializing cipher...
    Cipher cipher = javax.crypto.Cipher.getInstance("DES");                                                         
    cipher.init(mode, key);  

    int read = -1;
    while((read = readChannel.read(readBuffer)) != -1){
        readBuffer.flip();
        cipher.doFinal(readBuffer, writeBuffer);
        writeChannel.write(writeBuffer);
        readBuffer.clear();
        writeBuffer.clear();
    }
}

public static void main(String[] args) {
    // TODO Auto-generated method stub\
    FileOutputStream fos = null;
    String inFileString = "C:\\test.txt"; // Valid file pathname
    String fileString = "C:\\des.txt"; // Valid file pathname
    int mode = Cipher.ENCRYPT_MODE;
    FileSystem fs = FileSystems.getDefault();
    Path fp = fs.getPath(inFileString);

    try {
        readChannel = FileChannel.open(fp, EnumSet.of(StandardOpenOption.READ));
        fos = new FileOutputStream(fileString);
        writeChannel = Channels.newChannel(fos);
        run(mode);
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

}

Encryption works without exceptions. But when I try decrypt data (mode == DECRYPT_MODE and switched filenames)

javax.crypto.BadPaddingException: Given final block not properly padded
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:811)
at com.sun.crypto.provider.DESCipher.engineDoFinal(DESCipher.java:357)
at javax.crypto.CipherSpi.bufferCrypt(CipherSpi.java:767)
at javax.crypto.CipherSpi.engineDoFinal(CipherSpi.java:721)
at javax.crypto.Cipher.doFinal(Cipher.java:2382)
at Test.run(Test.java:57)
at Test.main(Test.java:77)

pops out.

I tried with different keys, but unsuccessfully. Any help will be appreciated. [I have to use channels, this code is only test for part of bigger class]

War es hilfreich?

Lösung

Two things:

  1. First of all, there is no correlation with password variable in the makeKeyFromPassword method. The returned SecretKey is random, so it will be impossible to decode the data in a two separates run of the program.
  2. Secondly, there should be writeBuffer.flip() after cipher.doFinal(readBuffer, writeBuffer) ;-)

Working code (please notice that password which is used to generate DES key need to be at least 8 characters):

public class Test {

    static ReadableByteChannel readChannel = null;
    static WritableByteChannel writeChannel = null;
    static SecretKey key = makeKeyFromPassword("abcdefghi".getBytes()); 
    static byte b[];

    public static SecretKey makeKeyFromPassword(byte[] password) {
        try {
            DESKeySpec dks = new DESKeySpec(password);
            SecretKeyFactory skf = SecretKeyFactory.getInstance("DES");
            return skf.generateSecret(dks);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static void run(int mode) throws Exception {
        ByteBuffer readBuffer = ByteBuffer.allocate(1024);
        ByteBuffer writeBuffer = ByteBuffer.allocate(1024);

        // initializing cipher...
        Cipher cipher = Cipher.getInstance("DES");
        cipher.init(mode, key);

        while (readChannel.read(readBuffer) != -1) {
            readBuffer.flip();
            cipher.doFinal(readBuffer, writeBuffer);
            writeBuffer.flip();
            writeChannel.write(writeBuffer);
            readBuffer.clear();
            writeBuffer.clear();
        }
    }

    static void f(String inFileString, String fileString, int mode) {
        FileOutputStream fos = null;
        FileSystem fs = FileSystems.getDefault();
        Path fp = fs.getPath(inFileString);

        try {
            readChannel = FileChannel.open(fp,
                    EnumSet.of(StandardOpenOption.READ));
            fos = new FileOutputStream(fileString);
            writeChannel = Channels.newChannel(fos);
            run(mode);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        f("C:\\test.txt", "C:\\des.txt", Cipher.ENCRYPT_MODE);
        System.out.println("Encrypted.");
        f("C:\\des.txt", "C:\\undes.txt", Cipher.DECRYPT_MODE);
        System.out.println("Decrypted.");
    }

}

Andere Tipps

i had a similar issue, but was solved after i made the -passin and -passout fields different (in my pkcs12 -export command)

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top