JavaAES加密在单元测试中工作。但从UDP/TCP传入时失败

JavaAES加密在单元测试中工作。但从UDP/TCP传入时失败,java,encryption,Java,Encryption,我的代码 运行时,等待udp数据包到来时,我会收到此消息 Plain Text : 6 75 3 Encrypted Text : 74 43 117 Decrypted Text : 6 75 3 TestServer使用 javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher at com.sun.crypto.

我的代码

运行时,等待udp数据包到来时,我会收到此消息

Plain Text : 6 75 3
Encrypted Text : 74 43 117
Decrypted Text : 6 75 3
TestServer使用

   javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher
    at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
    at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
    at com.sun.crypto.provider.AESCipher.engineDoFinal(DashoA13*..)
    at javax.crypto.Cipher.doFinal(DashoA13*..)

好的,这是一个可怕的例子,我将在以后更新,我将不得不睡觉

请注意,对于正常数据,使用ECB编码总是不安全的。当有可能发生中间人攻击(填充Oracle攻击)时,CBC编码非常不安全。但它应该起作用。如果您有更新的Java 7,请尝试使用
“AES/GCM/NoPadding”
,并且不要忘记将随机IV发送到另一端

private static void udpServer()
    {
        try
        {      //This is whats coming in ==> byte[] password={6,75,3};

            DatagramSocket serverSocket = new DatagramSocket(18000);
            byte[] receiveData = new byte[64];

            while (true)
            {
                DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
                serverSocket.receive(receivePacket);

                byte[] b = decrpytBytes(receivePacket.getData());
            }
        }
        catch(Exception e)
        {
            //blahh
        }
    }

好的,这是一个可怕的例子,我将在以后更新,我将不得不睡觉

请注意,对于正常数据,使用ECB编码总是不安全的。当有可能发生中间人攻击(填充Oracle攻击)时,CBC编码非常不安全。但它应该起作用。如果您有更新的Java 7,请尝试使用
“AES/GCM/NoPadding”
,并且不要忘记将随机IV发送到另一端

private static void udpServer()
    {
        try
        {      //This is whats coming in ==> byte[] password={6,75,3};

            DatagramSocket serverSocket = new DatagramSocket(18000);
            byte[] receiveData = new byte[64];

            while (true)
            {
                DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
                serverSocket.receive(receivePacket);

                byte[] b = decrpytBytes(receivePacket.getData());
            }
        }
        catch(Exception e)
        {
            //blahh
        }
    }

希望这些线程对您有所帮助:如果您以二进制格式传输数据,为什么要将数据转换为base64?从
getData()
?@Mrshll187的字节数组长度是多少?@Mrshll187:我怀疑问题实际上是您只是使用
getData()
,而没有调用
getLength()
,但是base64使事情更加混乱。除此之外,如果您需要base64,您不应该使用
sun.misc
,而应该使用Apache编解码器库。就我个人而言,我不喜欢输出字节数组的Base64编码器,顺便说一下,整个想法是Base64是文本,而不是二进制。想象一下,当您将base 64编码的二进制文件插入到与ASCII不兼容的内容中时会有多有趣(但如果这超出了您的想象,请首先从UDP数据包中取出base 64)。希望这些线程对您有所帮助:您为什么要将数据转换为base 64,如果您是以二进制格式传输它,那么
getData()
的字节数组的长度是多少?@Mrshll187:我怀疑问题实际上是您只是在使用
getData()
而没有调用
getLength()
,但是base64会让事情更加混乱。此外,您不应该使用
sun.misc
,如果需要base 64,请使用Apache编解码器库。就我个人而言,我不喜欢输出字节数组的Base64编码器,顺便说一下,整个想法是Base64是文本,而不是二进制。想象一下,当您将base64编码的二进制文件插入到与ASCII不兼容的内容中时会有多有趣(但如果这超出了您的想象,请首先从UDP数据包中删除base64)。谢谢,我感谢您的回复。这似乎奏效了。我不太喜欢IvParameterSpec到底在做什么,虽然如果你用同一个密钥加密多条消息,你总是需要一个IV。对于大多数密码模式,IV应该是随机化的,并且大部分时间是在密文之前。ECB不使用V,但加密文本时不安全。谢谢。我感谢您的回复。这似乎奏效了。我不太喜欢IvParameterSpec到底在做什么,虽然如果你用同一个密钥加密多条消息,你总是需要一个IV。对于大多数密码模式,IV应该是随机化的,并且大部分时间是在密文之前。ECB不使用V,但加密(如文本)不安全。
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketException;
import java.nio.charset.Charset;

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

public class UDP_AES {


    /**
     * @param args
     * @throws SocketException 
     */
    public static void main(String[] args) throws SocketException {


        Thread t = new Thread(new Runnable() {
            DatagramSocket socket;
            byte[] receiveData = new byte[1024];
            Cipher aesCipher;

            {
                try {
                    socket = new DatagramSocket(18000);
                    aesCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
                    IvParameterSpec zeroIV = new IvParameterSpec(new byte[aesCipher.getBlockSize()]);
                    SecretKey key = new SecretKeySpec(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7,}, "AES");
                    aesCipher.init(Cipher.DECRYPT_MODE, key, zeroIV);
                } catch (Exception e) {
                    throw new IllegalStateException("Could not create server socket or cipher", e);
                }

            }

            @Override
            public void run() {
                while (true) {
                    DatagramPacket packet = new DatagramPacket(receiveData, receiveData.length);

                    try {
                        socket.receive(packet);
                        final byte[] plaintextBinary = aesCipher.doFinal(packet.getData(), 0, packet.getLength());
                        String plaintext = new String(plaintextBinary, Charset.forName("UTF-8"));
                        System.out.println(plaintext);
                    } catch (Exception e) {
                        throw new IllegalStateException("Could not receive or decrypt packet");
                    }
                }
            }

        });
        t.start();

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            // yeah, whatever
        }

        DatagramSocket sendingSocket = new DatagramSocket();
        String plaintext = "1234";
        byte[] plaintextBinary = plaintext.getBytes(Charset.forName("UTF-8"));

        try {
            Cipher aesCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            SecretKey key = new SecretKeySpec(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7,}, "AES");
            IvParameterSpec zeroIV = new IvParameterSpec(new byte[aesCipher.getBlockSize()]);
            aesCipher.init(Cipher.ENCRYPT_MODE, key, zeroIV);
            final byte[] ciphertextBinary = aesCipher.doFinal(plaintextBinary);

        DatagramPacket sendingPacket = new DatagramPacket(ciphertextBinary, ciphertextBinary.length);
        sendingPacket.setSocketAddress(new InetSocketAddress("localhost", 18000));
            sendingSocket.send(sendingPacket);
        } catch (Exception e) {
            throw new IllegalStateException("Could not send or encrypt", e);
        }
    }

}