DES加密:给定最终块未正确填充

时间:2013-11-18 23:31:08

标签: java encryption padding des

我得到了这段代码:

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();
    }

}

加密无异常。 但是当我尝试解密数据(mode == DECRYPT_MODE和切换文件名)

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)
弹出来了。

我尝试使用不同的键,但没有成功。 任何帮助将不胜感激。 [我必须使用频道,此代码仅测试更大类的一部分]

2 个答案:

答案 0 :(得分:2)

两件事:

  1. 首先,password方法与makeKeyFromPassword变量没有关联。返回的SecretKey是随机的,因此无法在程序的两个单独运行中解码数据。
  2. 其次,writeBuffer.flip(); - )
  3. 之后应该cipher.doFinal(readBuffer, writeBuffer)

    工作代码(请注意,用于生成DES密钥的密码必须至少为8个字符):

    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.");
        }
    
    }
    

答案 1 :(得分:0)

我有一个类似的问题,但是在我使-passin和-passout字段不同之后(在我的pkcs12 -export命令中)解决了