0

Androidで画像を暗号化し、サーバーに送信して処理しようとしています。サーバーは、受信したメッセージを復号化する必要があります。私はすでにこの質問にコードを投稿しました

Android側で暗号化機能を呼び出し、Javaサーバー側で復号化機能を呼び出しました(画像はTCP経由で送信されます)。

ただし、次のエラーが表示されます。

javax.crypto.BadPaddingException: Given final block not properly padded 

Androidでキーを出力して取得しました:

 javax.crypto.spec.SecretKeySpec@652

Javaサーバー(Netbeansを使用して開発)では、次のようになりました。

javax.crypto.spec.SecretKeySpec@148dd

パディングが違うと思ったので使ってみました

AES/ECB/PKCS5Padding 

AES の代わりに

しかし、Java サーバーはエラーを出力しました。

should use AES.

この問題を解決するにはどうすればよいですか?

Android 側で送信する場合:

 public void send(Bitmap mRgbImage1_array, int port_number)
        throws IOException {

socket = new Socket("192.168.0.107", port_number);
boolean encrypt = HomeScreen.checkbox2.isChecked();
ByteArrayOutputStream stream = new ByteArrayOutputStream();

mRgbImage1_array.compress(CompressFormat.JPEG, 100, stream);
InputStream photoStream = new ByteArrayInputStream(stream.toByteArray());
BufferedInputStream bis = new BufferedInputStream(photoStream);
byte[] mybytearray = new byte[photoStream.available()];
bis.read(mybytearray, 0, mybytearray.length);
photoStream.close();

if(encrypt)
   {
 try {
byte[] dst = Security.encrypt(mybytearray);
mybytearray = new byte[10000];
for(int i=0; i<dst.length;i++)
{
     mybytearray[i] = dst[i];   
}

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

}
    os = socket.getOutputStream();
    os.write(mybytearray);
            os.flush();
    os.close();
if (os != null)
{
try {
os.close();
    } 

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

}

Java サーバー側で受信する場合:

    public static void receive(int port_number) {
    boolean received = false;

    Socket socket = null;
    InputStream is = null;
    int bytesRead;
    int current = 0;

    BufferedOutputStream bos = null;
    try {
        if (serverSocket == null) {
            serverSocket = new ServerSocket(port_number);
        }
        System.out.println("Listening :" + port_number);
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    while (!received) {
        try {
            socket = serverSocket.accept();
            InetAddress ip = socket.getInetAddress();
            String[] ip1 = ip.toString().split("/");
            ip2 = ip1[1];
            System.out.println("ip is " + ip2);
            byte[] mybytearray = new byte[10000000];
            is = socket.getInputStream();
            FileOutputStream fos = new    FileOutputStream("source-image.jpeg");
            bos = new BufferedOutputStream(fos);
            bytesRead = is.read(mybytearray, 0, mybytearray.length);
           current = bytesRead;
            do {
                bytesRead =
                        is.read(mybytearray, current, (mybytearray.length - current));
                if (bytesRead >= 0) {
                    current += bytesRead;
                }

            } while (bytesRead > -1);
if(Networker.should_encrypt)
            {
         try {
     mybytearray = Security1.decrypt(mybytearray);
        } catch (Exception e1) {
            /// TODO Auto-generated catch block
            e1.printStackTrace();
        }
            }
            bos.write(mybytearray, 0, current);
            bos.flush();
            bos.close();

            received = true;
        } catch (IOException ex) {
            Logger.getLogger(MyServer1.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            if (socket != null) {
                try {
                    socket.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }
   }
4

1 に答える 1

2

これが問題だと思います:

mybytearray = Security1.decrypt(mybytearray);

実際に少量のデータしか書き込んでいない場合でも、常に10000000 バイトを復号化します。メソッドを変更して、復号化するデータの量を指定してから、 を呼び出す必要があります。decryptdoFinal(byte[], int, int)

また、10MB を事前に割り当てるのではなく、ストリーミング方式で暗号化/復号化を処理することをお勧めします (これはほとんどの場合無駄になり、他の場合には短すぎる可能性があります) が、それはより大きな変更です。

さらに、これは暗号化コードでは悪い考えです。

byte[] mybytearray = new byte[photoStream.available()];
bis.read(mybytearray, 0, mybytearray.length);
photoStream.close();

最初に利用できる量はファイル全体であると想定しています。そうではないかもしれません。通常は、ファイル ストリームから読み取り、暗号化ストリームに書き込み、ループ ラウンドする必要があります。ああ、close()呼び出しはfinallyブロックにあるはずです。

本当にすべての暗号化/復号化を 1 回の呼び出しで実行したい場合は、ファイルまたはネットワーク ストリームからの読み取りと への書き込みをループすることができByteArrayOutputStreamますavailable()。次にByteArrayOutputStream.toByteArray()、正しいサイズのバイト配列を取得するために使用します。(確かに、これには追加のコピーが含まれます。)

于 2012-05-12T17:50:02.123 に答える