At 12:17 PM 1/27/2014, Matthew Hall wrote: >I have often had good luck accelerating such operations using the PKCS #11 >provider with a recent copy of libnss to get the native crypto. And the things >needed for this are built into Java already.
Yup. https://developer.mozilla.org/en-US/docs/NSS/NSS_3.14.2_release_notes >-- >Sent from my mobile device. > >Michael StJohns <mstjo...@comcast.net> wrote: >At 09:23 AM 1/27/2014, Mark Christiaens wrote: >>Silly me, forgot to mention that I'm working on Ubuntu, 64 bit, 13.10. >> >>So, AES-CBC seems to be reasonably fast (100 MiB/s) but AES-GCM is slow (5.2 >>MiB/s). à I'm particularly curious about the GCM one because I get the >>impression that OpenSSL should be able to reach in the GB/s for AES-GCM >>encryption/authentication.à >> >>Mark > > >GCM uses a GF2 multiply as part of the integrity calculation. That operation >is pretty expensive. My guess is that if the code was profiled, you'd find a >lot of time being spent in com.sun.crypto.provider.GHASH. > >The more recent intel processors have a set of instructions that substantially >improve this performance - http://en.wikipedia.org/wiki/CLMUL_instruction_set >- but the code in the standard provider is all pure java and doesn't take >advantage of this as far as I can tell. I believe that the more recent >versions of OpenSSL *have* been updated to take advantage of the new >instructions which explains their performance. > >The same processors generally also support an AES instruction set so if >someone were to build a native version of this it might be useful to also >replace/augment the default AES block cipher implementation. > >Also see >http://software.intel.com/en-us/articles/intel-aes-ni-performance-testing-on-linuxjava-stack > > >Mike > > > >>On Mon, Jan 27, 2014 at 3:19 PM, Xuelei Fan >><<mailto:xuelei....@oracle.com>xuelei....@oracle.com> wrote: >>What's the platform are you using for the testing? à Windows, Linux, >>Solaris or Mac OS? à GCM are now only implemented in SunJCE provider. à I >>want to make sure the crypto provider for AES-CBC, which is different >>for different platforms by default, is not the major cause of the >>performance impact. >>Thanks for the performance measure. >>Regards, >>Xuelei >>On 1/27/2014 5:34 PM, Chris Hegarty wrote: >>> Cross posting to security-dev, since the question cipher related. >>> >>> -Chris. >>> >>> On 27/01/14 09:28, Mark Christiaens wrote: >>>> I wrote à a little test client/server setup that transfers 100 MB of data >>>> over an SSL socket configured to use TLS 1.2 AES GCM >>>> (TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256). à On my i7-4770 CPU @ 3.40GHz >>>> with OpenJDK 1.8.0-ea-b124 I get a transfer rate of around 5.2 >>>> MiB/second. à I expected a higher speed. à Using >>>> TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 I reach 100 MiB/s. à Is this to >>>> be expected? >>>> >>>> For reference, here is my code: >>>> >>>> ///// Client.java >>>> >>>> package ssl; >>>> >>>> import javax.net.ssl.*; >>>> import java.io.*; >>>> import java.util.Arrays; >>>> >>>> public class Client { >>>> >>>> à à à public static void main(String[] arstring) { >>>> à à à à à try { >>>> à à à à à à à SSLSocketFactory sslsocketfactory = >>>> (SSLSocketFactory) >>>> SSLSocketFactory.getDefault(); >>>> à à à à à à à SSLSocket sslsocket = (SSLSocket) >>>> sslsocketfactory.createSocket("localhost", 9999); >>>> à à à à à à à Helper.requireAESCipherSuites(sslsocket); >>>> à à à à à à à sslsocket.setEnabledProtocols(new >>>> String[]{"TLSv1.2"}); >>>> >>>> à à à à à à à try (OutputStream outputstream = >>>> sslsocket.getOutputStream()) { >>>> à à à à à à à à à byte[] buf = new byte[Helper.BUF_SIZE]; >>>> à à à à à à à à à Arrays.fill(buf, (byte) 1); >>>> à à à à à à à à à for (int i = 0; i < Helper.BUF_COUNT; >>>> ++i) { >>>> à à à à à à à à à à à outputstream.write(buf); >>>> à à à à à à à à à } >>>> >>>> à à à à à à à à à System.out.println("Using cipher suite: >>>> " + >>>> (sslsocket.getSession()).getCipherSuite()); >>>> >>>> à à à à à à à à à outputstream.flush(); >>>> à à à à à à à } >>>> >>>> à à à à à } catch (IOException exception) { >>>> à à à à à à à exception.printStackTrace(); >>>> à à à à à } >>>> à à à } >>>> } >>>> >>>> ///// Server.java >>>> >>>> package ssl; >>>> >>>> import javax.net.ssl.*; >>>> import java.io.*; >>>> >>>> public class Server { >>>> >>>> à à à public static void main(String[] arstring) { >>>> à à à à à try { >>>> à à à à à à à SSLServerSocketFactory sslserversocketfactory = >>>> (SSLServerSocketFactory) SSLServerSocketFactory.getDefault(); >>>> à à à à à à à SSLServerSocket sslserversocket = >>>> (SSLServerSocket) >>>> sslserversocketfactory.createServerSocket(9999); >>>> à à à à à à à SSLSocket sslsocket = (SSLSocket) >>>> sslserversocket.accept(); >>>> >>>> à à à à à à à InputStream inputstream = >>>> sslsocket.getInputStream(); >>>> >>>> à à à à à à à byte[] buf = new byte[Helper.BUF_SIZE]; >>>> à à à à à à à long bytesToRead = BYTES_TO_READ; >>>> >>>> à à à à à à à long startTime = System.currentTimeMillis(); >>>> >>>> à à à à à à à while (bytesToRead > 0) { >>>> à à à à à à à à à bytesToRead -= inputstream.read(buf); >>>> à à à à à à à } >>>> >>>> à à à à à à à long stopTime = System.currentTimeMillis(); >>>> à à à à à à à long totalTimeMs = stopTime - startTime; >>>> à à à à à à à double mbRead = BYTES_TO_READ / (1024.0 * >>>> 1024); >>>> à à à à à à à double totalTimeSeconds = totalTimeMs / 1000.0; >>>> à à à à à à à double mibPerSecond = mbRead / >>>> totalTimeSeconds; >>>> >>>> à à à à à à à System.out.println("Using cipher suite: " + >>>> (sslsocket.getSession()).getCipherSuite()); >>>> à à à à à à à System.out.println("Read " + mbRead + "MiB in " >>>> + >>>> totalTimeSeconds + "s"); >>>> à à à à à à à System.out.println("Bandwidth: " + mibPerSecond >>>> + "MiB/s"); >>>> >>>> à à à à à } catch (IOException exception) { >>>> à à à à à à à exception.printStackTrace(); >>>> à à à à à } >>>> à à à } >>>> >>>> à à à private static final int BYTES_TO_READ = Helper.BUF_COUNT * >>>> Helper.BUF_SIZE; >>>> } >>>> >>>> ///// Helper.java >>>> >>>> package ssl; >>>> >>>> import java.util.*; >>>> import java.util.regex.*; >>>> import javax.net.ssl.*; >>>> >>>> public class Helper { >>>> >>>> à à à static int BUF_SIZE = 1024 * 1024; >>>> à à à static int BUF_COUNT = 100; >>>> >>>> à à à static SSLSocket requireAESCipherSuites(SSLSocket socket) { >>>> à à à à à String supportedCipherSuites[] = >>>> socket.getSupportedCipherSuites(); >>>> >>>> à à à à à System.out.println("Supported cipher suite: " + >>>> Arrays.toString(supportedCipherSuites)); >>>> >>>> à à à à à List<String> selectedCipherSuites = new ArrayList<>(); >>>> >>>> // à à à à String patternString = ".*"; >>>> à à à à à String patternString = >>>> "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256"; >>>> // à à à à String patternString = >>>> "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256"; >>>> >>>> à à à à à Pattern pattern = Pattern.compile(patternString); >>>> >>>> à à à à à for (String cipherSuite : supportedCipherSuites) { >>>> à à à à à à à Matcher matcher = pattern.matcher(cipherSuite); >>>> à à à à à à à if (matcher.find()) { >>>> à à à à à à à à à selectedCipherSuites.add(cipherSuite); >>>> à à à à à à à } >>>> à à à à à } >>>> >>>> à à à à à System.out.println("Selected cipher suites: " + >>>> selectedCipherSuites); >>>> >>>> à à à à à >>>> socket.setEnabledCipherSuites(selectedCipherSuites.toArray(new >>>> String[0])); >>>> >>>> à à à à à return socket; >>>> à à à } >>>> } >>>> >> >> >> >> >>-- >>Mark Christiaens >>Ganzeplas 23 >>9880 Aalter >>09 / 325 07 40