簡體   English   中英

Java密碼填充錯誤

[英]Java Cipher padding Error

我是Java的新手,它嘗試使用CipherSecretKey加密和解密兩條文本消息,如下面的代碼bellow(第241行的代碼)所示。 每當我嘗試Decrypt此加密消息時,都會收到一條錯誤消息:
javax.crypto.BadPaddingException: Given final block not properly padded javax.crypto.IllegalBlockSizeException: Input length must be multiple of 8 when decrypting with padded cipher
我在這段代碼中使用了3個線程和兩個分別稱為q1和q2的緩沖區/隊列。 首先,我將消息放入緩沖區/隊列中。 然后,在下一個類中,我檢索該消息並將其加密,然后發送到下一個類。 然后,該類將再次將其放入緩沖區/隊列。 最后,在最后一個類中,它將從緩沖區中檢索並解密。 這是發生問題的地方。 發生同步錯誤。 我已經嘗試解決這個錯誤很多天了,沒有運氣。 其他在線文檔也沒有幫助。 如果您可以編輯此代碼或通過示例向我展示,我將不勝感激

import java.security.KeyPairGenerator;
import java.security.KeyPair;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.PrivateKey;
import java.security.Signature;
import java.io.*;
import java.util.*;
import java.util.concurrent.TimeUnit;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;



class Q5 { //Queue/Buffer   
    byte[] shipmentConfirmation;//will include the actual message content been delivered
    boolean valueSet = false;
    synchronized byte[] get() 
    {       
        while(!valueSet) 
        try 
        {
            wait();
        } 
        catch(InterruptedException e) 
        {
            System.out.println("InterruptedException caught");
        }
        //System.out.println("Got: " + n);
        valueSet = false;
        notify();
        return shipmentConfirmation;
    }
    synchronized void put(byte[] shipmentCinfirm) 
    {
        while(valueSet)
        try 
        {
            wait();
        } 
        catch(InterruptedException e) 
        {
            System.out.println("InterruptedException caught");
        }
        this.shipmentConfirmation = shipmentCinfirm;
        valueSet = true;
        //System.out.println("Put: " + n);
        notify();
    }
}

class Global5{
    public static int sendcouter = 0;
    public static SecretKey secret_Key;
    public static Cipher desCipher;
}


//<<security pattern>> SymmetricEncryptionEncryptor
class SecurityEncryptor//<<security>> Encryptor
{
    static byte[] Encryptor(byte shipmentConfirmation[],Cipher c) throws Exception //Encryptor
    {       
        byte[] ciphertext = SecurityEncryptionAlgorithm.EncryptionAlgorithm(shipmentConfirmation,c,Global5.secret_Key);
        return ciphertext;
    }   
}
class SecurityEncryptionAlgorithm//<<security>> EncryptionAlgorithm
{
    static byte[] EncryptionAlgorithm(byte shipmentConfirmation[],Cipher c,SecretKey sk) throws Exception 
    {
        c.init(Cipher.ENCRYPT_MODE, sk);
        return c.doFinal(shipmentConfirmation);
    }
}



//<<security pattern>> aSecureAsynchronousMCReceiverConnector
class SecurityDecryptor//<<Security>> Decryptor
{
    static byte[] Decryptor(byte EncryptedShipmentConfirmation[],Cipher c,SecretKey sk) throws Exception //Decryptor
    {
        byte[] ct = SecurityDecryptionAlgorithm.DecryptionAlgorithm(EncryptedShipmentConfirmation,c,sk);
        return ct;
    }   
}
class SecurityDecryptionAlgorithm//<<Security>> DecryptionAlgorithm
{
    static byte[] DecryptionAlgorithm(byte EncryptedShipmentConfirmation[],Cipher c,SecretKey sk) throws Exception 
    {
        c.init(Cipher.DECRYPT_MODE, sk);
        return c.doFinal(EncryptedShipmentConfirmation);
    }
}



public class testFigure1 { //Main
       public static void main(String args[]) throws Exception {          
            Q5 q1 = new Q5();//creating buffer/queue
            Q5 q2 = new Q5();

            System.out.println("How many messages to send: ");
            Scanner in = new Scanner(System.in);
            int input = in.nextInt();//Get input from the supplier          

            aSupplierInterface Supplier = new aSupplierInterface(q1, input);    
            aSecuritySenderCoordinator SenderCoordinator = new aSecuritySenderCoordinator(q1, input, q2);           
            aSecurityReceiverCoordinator receive = new aSecurityReceiverCoordinator(q2, input);   
            Supplier.t_pro.join();
            SenderCoordinator.t_coordinator5.join();
            receive.t_SecurityReceiverCoordinator5.join();
            System.out.println("End of Program!");
       }   
}

class aSupplierInterface  implements Runnable //<<application Component>> aSupplierInterface
{
    Q5 q;   
    int supinput;
    Thread t_pro;//pro to represent producer or suppler
    aSupplierInterface(Q5 qq, int input)
    {
        supinput = input;
        this.q = qq;
        t_pro = new Thread(this, "Producer");
        t_pro.start();
    }
    public void run() 
    {
        int i = 0;
        String shipment;
        byte[] shipmentConfirmation;
        while(i<supinput)
        {
            i++;
            shipment = "This is the Delivery Number: "+ i;
            shipmentConfirmation = shipment.getBytes();

            q.put(shipmentConfirmation);//Putting supplier's goods in a queue/buffer            
        }   
    }       
}

class aSecuritySenderCoordinator implements Runnable //<<security coordinator>> aSecuritySenderCoordinator
{
    Q5 q;
    Q5 q2;
    Thread t_coordinator5;
    int supinput;

    public aSecuritySenderCoordinator(Q5 qq, int input, Q5 q2) throws Exception
    {       
        supinput=input;
        this.q = qq;    
        this.q2=q2;
        t_coordinator5 = new Thread(this, "coordinator5");
        t_coordinator5.start();
    }

    public void run() 
    {
        byte[] pkShipmentConfirmation;
        byte[] shipmentConfirmation;
        int i = 0;
        while(i<supinput) 
        {               
            i++;

                //Getting goods that supplier has put in the queue previously
            pkShipmentConfirmation=q.get();//This will contain content of the message/delivery you are sending
            KeyGenerator keygen;
            try {
            keygen = KeyGenerator.getInstance("DES");
            Global5.sendcouter++;//To Create the key once
            if(Global5.sendcouter==1)//Create once
            {
                Global5.secret_Key = keygen.generateKey();
                Global5.desCipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
            }           
            //String st1 = new String(pkShipmentConfirmation);//just to print a message
            //System.out.println("*ORIGINAL MESSAGE:"+st1);    
            shipmentConfirmation = SecurityEncryptor.Encryptor(pkShipmentConfirmation,Global5.desCipher);//Encrypting 


            new anAsynchronousMCReceiver(q2, shipmentConfirmation);     

            } catch (NoSuchAlgorithmException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}




class anAsynchronousMCReceiver 
{ //<<communication pattern>> anAsynchronousMCReceiver
       Q5 q;

       anAsynchronousMCReceiver( Q5 q2, byte[] shipmentConfirm) throws Exception
       {
           this.q = q2;
           q.put(shipmentConfirm);  //Entering received data in to the Queue/Buffer 
       }
}



class aSecurityReceiverCoordinator implements Runnable//<<security coordinator>> aSecurityReceiverCoordinator
{       
    Thread t_SecurityReceiverCoordinator5;  
    Q5 q;
    int supinput;
    byte[]encryptedShipmentConfirmation;
    public aSecurityReceiverCoordinator(Q5 q2, int input) throws Exception
    {  
        this.q = q2;    
        supinput = input;
        t_SecurityReceiverCoordinator5 = new Thread(this, "SecurityReceiverCoordinator5");
        t_SecurityReceiverCoordinator5.start();

    }
    public void run() 
    {
        try {
            int i = 0;
            while(i<supinput) 
            {           
                i++;
                encryptedShipmentConfirmation = q.get();                
                byte[] confirmation = SecurityDecryptor.Decryptor(encryptedShipmentConfirmation,Global5.desCipher,Global5.secret_Key);//ERROR HAPPENS HERE              
                String shipConfirmation = new String(confirmation);

                System.out.println("AT DelivertyOrder: " +  shipConfirmation);
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

如果您復制並粘貼該程序,它將在您的計算機上運行

不用過多看代碼,我可以看到它使用了Cipher的共享實例。 Cipher不是線程安全的,並且在SecurityDecryptionAlgorithmSecurityEncryptionAlgorithm都使用了SecurityDecryptionAlgorithm ,因此它要求麻煩...而麻煩的是內部緩沖區已損壞並引發了所顯示的異常。

要解決此問題,只需對每個加密/解密(首選解決方案)使用實例密碼,為每個線程創建一個實例,或者使SecurityDecryptionAlgorithmSecurityEncryptionAlgorithm的靜態方法同步,並為每個實例提供不同的Cipher實例。

我將從Global5刪除Cipher ,並在每次調用時實例化一個新的加密或解密對象。

為了使它更加可見,此代碼調用

c.init(Cipher.ENCRYPT_MODE, sk);

c.init(Cipher.DECRYPT_MODE, sk);

在同一情況下...我確信它會使密碼更加混亂。

多線程問題:

如果要使用相同的Cipher對象實例進行加密或解密,則必須特別小心, 尤其是當有多個線程訪問同一Cipher對象(在您的情況下)時,因為它內部使用了緩沖區,填充等,因此即使您可以指定適當的填充方案,就像您指定PKCS5Padding或者您不指定任何填充(使用AES/ECB/NoPadding或使用ECB模式DES/ECB/PKCS5Padding ), 則很可能會遇到異常DES/ECB/PKCS5Padding javax.crypto.BadPaddingException: Given final block not properly padded並且javax.crypto.IllegalBlockSizeException: Input length must be multiple of 8 when decrypting with padded cipher因為內部的Cipher對象被弄亂了。

現在,由於您使用的是相同的Cipher對象,因此即使您正確指定了padding等,但由於它是同一個對象,仍然會出現與padding相關的異常。

密碼學問題:

如果將CBC模式用於Cipher對象,則還應該提供IvParameterSpec對象,否則您可能會遇到java.security.InvalidKeyException異常。

閱讀此答案

另外,建議使用CBC模式而不是ECB模式。

閱讀此答案。

更新的代碼

因此,您的最終代碼如下所示,它將毫無例外地運行,但是您指定的消息數與答案- How many messages to send:

PS:我已經清理了一些代碼以關閉您的Scanner對象,等等,您也應該注意這些事情

import java.security.NoSuchAlgorithmException;
import java.util.Scanner;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;



class Q5 { //Queue/Buffer   
    byte[] shipmentConfirmation;//will include the actual message content been delivered
    boolean valueSet = false;
    synchronized byte[] get() 
    {       
        while(!valueSet) 
        try 
        {
            wait();
        } 
        catch(InterruptedException e) 
        {
            System.out.println("InterruptedException caught");
        }
        //System.out.println("Got: " + n);
        valueSet = false;
        notify();
        return shipmentConfirmation;
    }
    synchronized void put(byte[] shipmentCinfirm) 
    {
        while(valueSet)
        try 
        {
            wait();
        } 
        catch(InterruptedException e) 
        {
            System.out.println("InterruptedException caught");
        }
        this.shipmentConfirmation = shipmentCinfirm;
        valueSet = true;
        //System.out.println("Put: " + n);
        notify();
    }
}

class Global5{
    public static int sendcouter = 0;
    public static SecretKey secret_Key;
    public static Cipher desCipher;
}


//<<security pattern>> SymmetricEncryptionEncryptor
class SecurityEncryptor//<<security>> Encryptor
{
    static byte[] Encryptor(byte shipmentConfirmation[],Cipher c) throws Exception //Encryptor
    {       
        byte[] ciphertext = SecurityEncryptionAlgorithm.EncryptionAlgorithm(shipmentConfirmation,c,Global5.secret_Key);
        return ciphertext;
    }   
}
class SecurityEncryptionAlgorithm//<<security>> EncryptionAlgorithm
{
    static byte[] EncryptionAlgorithm(byte shipmentConfirmation[],Cipher c,SecretKey sk) throws Exception 
    {
        byte[] iv = {0, 0, 0, 0, 0, 0, 0, 0};
        IvParameterSpec ivspec = new IvParameterSpec(iv);
        c.init(Cipher.ENCRYPT_MODE, sk, ivspec);
        return c.doFinal(shipmentConfirmation);
    }
}



//<<security pattern>> aSecureAsynchronousMCReceiverConnector
class SecurityDecryptor//<<Security>> Decryptor
{
    static byte[] Decryptor(byte EncryptedShipmentConfirmation[],Cipher c,SecretKey sk) throws Exception //Decryptor
    {
        byte[] ct = SecurityDecryptionAlgorithm.DecryptionAlgorithm(EncryptedShipmentConfirmation,c,sk);
        return ct;
    }   
}
class SecurityDecryptionAlgorithm//<<Security>> DecryptionAlgorithm
{
    static byte[] DecryptionAlgorithm(byte EncryptedShipmentConfirmation[],Cipher c,SecretKey sk) throws Exception 
    {
        byte[] iv = {0, 0, 0, 0, 0, 0, 0, 0};
        IvParameterSpec ivspec = new IvParameterSpec(iv);
        c.init(Cipher.DECRYPT_MODE, sk, ivspec);
        return c.doFinal(EncryptedShipmentConfirmation);
    }
}



public class testFigure1 { //Main
       public static void main(String args[]) throws Exception {          
            Q5 q1 = new Q5();//creating buffer/queue
            Q5 q2 = new Q5();

            System.out.println("How many messages to send: ");
            Scanner in = new Scanner(System.in);
            int input = in.nextInt();//Get input from the supplier          
            in.close();

            aSupplierInterface Supplier = new aSupplierInterface(q1, input);    
            aSecuritySenderCoordinator SenderCoordinator = new aSecuritySenderCoordinator(q1, input, q2);           
            aSecurityReceiverCoordinator receive = new aSecurityReceiverCoordinator(q2, input);   
            Supplier.t_pro.join();
            SenderCoordinator.t_coordinator5.join();
            receive.t_SecurityReceiverCoordinator5.join();
            System.out.println("End of Program!");
       }   
}

class aSupplierInterface  implements Runnable //<<application Component>> aSupplierInterface
{
    Q5 q;   
    int supinput;
    Thread t_pro;//pro to represent producer or suppler
    aSupplierInterface(Q5 qq, int input)
    {
        supinput = input;
        this.q = qq;
        t_pro = new Thread(this, "Producer");
        t_pro.start();
    }
    public void run() 
    {
        int i = 0;
        String shipment;
        byte[] shipmentConfirmation;
        while(i<supinput)
        {
            i++;
            shipment = "This is the Delivery Number: "+ i;
            shipmentConfirmation = shipment.getBytes();

            q.put(shipmentConfirmation);//Putting supplier's goods in a queue/buffer            
        }   
    }       
}

class aSecuritySenderCoordinator implements Runnable //<<security coordinator>> aSecuritySenderCoordinator
{
    Q5 q;
    Q5 q2;
    Thread t_coordinator5;
    int supinput;

    public aSecuritySenderCoordinator(Q5 qq, int input, Q5 q2) throws Exception
    {       
        supinput=input;
        this.q = qq;    
        this.q2=q2;
        t_coordinator5 = new Thread(this, "coordinator5");
        t_coordinator5.start();
    }

    public void run() 
    {
        byte[] pkShipmentConfirmation;
        byte[] shipmentConfirmation;
        int i = 0;
        while(i<supinput) 
        {               
            i++;

                //Getting goods that supplier has put in the queue previously
            pkShipmentConfirmation=q.get();//This will contain content of the message/delivery you are sending
            KeyGenerator keygen;
            try {
            keygen = KeyGenerator.getInstance("DES");
            Global5.sendcouter++;//To Create the key once
            if(Global5.sendcouter==1)//Create once
            {
                Global5.secret_Key = keygen.generateKey();
                Global5.desCipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
            }           
            //String st1 = new String(pkShipmentConfirmation);//just to print a message
            //System.out.println("*ORIGINAL MESSAGE:"+st1);    
            shipmentConfirmation = SecurityEncryptor.Encryptor(pkShipmentConfirmation,Cipher.getInstance("DES/CBC/PKCS5Padding"));//Encrypting 


            new anAsynchronousMCReceiver(q2, shipmentConfirmation);     

            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}




class anAsynchronousMCReceiver 
{ //<<communication pattern>> anAsynchronousMCReceiver
       Q5 q;

       anAsynchronousMCReceiver( Q5 q2, byte[] shipmentConfirm) throws Exception
       {
           this.q = q2;
           q.put(shipmentConfirm);  //Entering received data in to the Queue/Buffer 
       }
}



class aSecurityReceiverCoordinator implements Runnable//<<security coordinator>> aSecurityReceiverCoordinator
{       
    Thread t_SecurityReceiverCoordinator5;  
    Q5 q;
    int supinput;
    byte[]encryptedShipmentConfirmation;
    public aSecurityReceiverCoordinator(Q5 q2, int input) throws Exception
    {  
        this.q = q2;    
        supinput = input;
        t_SecurityReceiverCoordinator5 = new Thread(this, "SecurityReceiverCoordinator5");
        t_SecurityReceiverCoordinator5.start();

    }
    public void run() 
    {
        try {
            int i = 0;
            while(i<supinput) 
            {           
                i++;
                encryptedShipmentConfirmation = q.get();                
                byte[] confirmation = SecurityDecryptor.Decryptor(encryptedShipmentConfirmation,Cipher.getInstance("DES/CBC/PKCS5Padding"),Global5.secret_Key);//ERROR HAPPENS HERE              
                String shipConfirmation = new String(confirmation);

                System.out.println("AT DelivertyOrder: " +  shipConfirmation);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM