非常に遅い内蔵のAES暗号化のJavaで

ルーカスNothhelfer:

私は必要性を暗号化して暗号化された形式で、TCP経由でリモートサーバーに送信することは、非常に小さなデータ(19バイト)をたくさん持っています。私はこれを行うには、以下のコードを使用しています。

package aesclient;

import java.io.OutputStream;
import java.net.Socket;

import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class AESClient {
    static byte[] plaintext = new byte[] {0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53};
    public static void main(String[] args) {
        try {
            Socket socket = new Socket("127.0.0.1", 1337); // connecting to server on localhost
            OutputStream outputStream = socket.getOutputStream();
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
            String s_key = "Random09" + "Random09"; // 16 Byte = 128 Bit Key
            byte[] b_key = s_key.getBytes();
            SecretKeySpec sKeySpec = new SecretKeySpec(b_key, "AES");
            SecureRandom random = SecureRandom.getInstanceStrong();
            byte[] IV = new byte[16]; // initialization vector
            int num = 10000;
            long start = System.nanoTime();
            for (int i = 0; i < num; ++i) {
                random.nextBytes(IV);
                IvParameterSpec ivSpec = new IvParameterSpec(IV);
                cipher.init(Cipher.ENCRYPT_MODE, sKeySpec, ivSpec);
                byte[] msg = new byte[16 + 32];
                System.arraycopy(IV, 0, msg, 0, IV.length);
                byte[] encrypted = cipher.doFinal(plaintext);
                System.arraycopy(encrypted, 0, msg, IV.length, encrypted.length);
                outputStream.write(msg);
                outputStream.flush();      
            }
            long end = System.nanoTime();
            long duration = end - start;
            double drate = ((double)plaintext.length*(double)num)/((double)duration/1000000000);
            System.out.println("Verschlüsselung:\n" + num + " mal 19 Bytes in " + ((double)duration/1000000000) + " s\nData Rate = " + drate/1000.0 + " kBytes/s");
        }
        catch (Exception e) {
            System.err.println(e.getMessage());
        }
    } 
}

それは非常に遅いですなぜ私が疑問に思って。私はこのような出力が得られます。

Verschlüsselung:
10000 mal 19 Bytes in 2.566016627 s
Data Rate = 74.04472675694785 kBytes/s

これは私は、元の(暗号化されていない)データの74キロバイト/秒のデータレートを有することを意味します。私はTCP(それは100kByte /秒のことだ)を介して送信省略した場合、データレートは無視できるほど増加します。私も高い20MByte / sの周りされているか、データレートについて読んだことがあります。私は、Windows 10およびi5プロセッサを搭載したノートパソコンを持っています。私は任意の助けいただければ幸いです。私が言ったように、私は暗号化された小さなデータパケット(19バイト)の多くを転送する必要があります。

rustyx:

SecureRandom でもPRNGモードで低速ではなく、十分なエントロピーが利用可能な場合でも、ブロックすることができます。

私はかつて、ランダムなIVを調達し、CTRモードに似繰り返しの間、それをインクリメントお勧めします。それとも、CTRモードを使用します。

public class Test {
    static byte[] plaintext = new byte[] { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51,
            0x52, 0x53 };

    public static void main(String[] args) {
        try {
            Cipher cipher = Cipher.getInstance("AES/CTR/PKCS5PADDING");
            String s_key = "Random09" + "Random09"; // 16 Byte = 128 Bit Key
            byte[] b_key = s_key.getBytes();
            SecretKeySpec sKeySpec = new SecretKeySpec(b_key, "AES");
            SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
            byte[] IV = new byte[16]; // initialization vector
            random.nextBytes(IV);
            int num = 10000;
            long start = System.nanoTime();
            for (int i = 0; i < num; ++i) {
                IvParameterSpec ivSpec = new IvParameterSpec(IV);
                cipher.init(Cipher.ENCRYPT_MODE, sKeySpec, ivSpec);
                byte[] msg = new byte[16 + 32];
                System.arraycopy(IV, 0, msg, 0, IV.length);
                byte[] encrypted = cipher.doFinal(plaintext);
                System.arraycopy(encrypted, 0, msg, IV.length, encrypted.length);
                increment(IV);
            }
            long end = System.nanoTime();
            long duration = end - start;
            double drate = ((double) plaintext.length * (double) num) / ((double) duration / 1000000000);
            System.out.println("Verschlüsselung:\n" + num + " mal 19 Bytes in " + ((double) duration / 1000000000) + " s\nData Rate = " + drate
                    / 1000.0 + " kBytes/s");
        } catch (Exception e) {
            System.err.println(e.getMessage());
        }
    }

    private static void increment(byte[] iv) {
        for (int i=0; i<4; ++i) {
            if (++iv[i] != 0)
                break;
        }
    }
}

版画:

Verschlüsselung:
10000 mal 19 Bytes in 0.0331898 s
Data Rate = 5724.650344382912 kBytes/s

少なくとも30倍高速私のマシン上で。

おすすめ

転載: http://43.154.161.224:23101/article/api/json?id=200244&siteId=1