Java Mac.getInstance for HmacSHA1 slow

I am running the following Java program on a Macbook Air with OSX 10.9.4, 1.7GHz i7, 8GB memory. I have Java Cryptography Extension (JCE) installed.

import javax.crypto.Mac; public class Main { public static void main(String[] args) throws Exception { Mac.getInstance("HmacSHA1"); } } 

Running this simple program will lead to a runtime of more than 5 seconds!

 $ javac -version javac 1.7.0_45 $ javac Main.java $ java -version java version "1.7.0_45" Java(TM) SE Runtime Environment (build 1.7.0_45-b18) Java HotSpot(TM) 64-Bit Server VM (build 24.45-b08, mixed mode) $ time java Main real 0m5.326s user 0m0.390s sys 0m0.033s 

I did a bunch of searches, but did not find many workarounds or explanations.

  • Mac.getInstance () for an HmacSHA1 requiring age to execute

    This seems like my problem, but all the sources that I read show that /dev/random and /dev/urandom same on OSX.

  • How to solve the performance problem using Java SecureRandom?

    Again, the discussion of the source of randomness is SecureRandom, but it does not seem to apply to OSX.

Has anyone heard of this issue before? Or do you know how I can debug what happens? It really upsets taking a 5 second penalty for your unit tests when they were instant so far.

Edit: Here is the time inside the program and the list of security providers:

 import java.security.Provider; import java.security.Security; import javax.crypto.Mac; public class Main { public static void main(String[] args) throws Exception { for (Provider p: Security.getProviders()) { System.out.println(p.getName() + " " + p.getVersion() + " " + p.getInfo()); } long start = System.currentTimeMillis(); Mac.getInstance("HmacSHA1"); System.out.println(System.currentTimeMillis() - start + "ms"); } } $ java Main SUN 1.7 SUN (DSA key/parameter generation; DSA signing; SHA-1, MD5 digests; SecureRandom; X.509 certificates; JKS keystore; PKIX CertPathValidator; PKIX CertPathBuilder; LDAP, Collection CertStores, JavaPolicy Policy; JavaLoginConfig Configuration) SunRsaSign 1.7 Sun RSA signature provider SunEC 1.7 Sun Elliptic Curve provider (EC, ECDSA, ECDH) SunJSSE 1.7 Sun JSSE provider(PKCS12, SunX509 key/trust factories, SSLv3, TLSv1) SunJCE 1.7 SunJCE Provider (implements RSA, DES, Triple DES, AES, Blowfish, ARCFOUR, RC2, PBE, Diffie-Hellman, HMAC) SunJGSS 1.7 Sun (Kerberos v5, SPNEGO) SunSASL 1.7 Sun SASL provider(implements client mechanisms for: DIGEST-MD5, GSSAPI, EXTERNAL, PLAIN, CRAM-MD5, NTLM; server mechanisms for: DIGEST-MD5, GSSAPI, CRAM-MD5, NTLM) XMLDSig 1.0 XMLDSig (DOM XMLSignatureFactory; DOM KeyInfoFactory) SunPCSC 1.7 Sun PC/SC provider Apple 1.1 Apple Provider 5224ms 

Edit 2:

We figured out how to run HPROF in code.

 $ java -agentlib:hprof=cpu=times Main $ cat java.hprof.txt ... TRACE 308670: java.net.InetAddress$1.lookupAllHostAddr(InetAddress.java:Unknown line) java.net.InetAddress.getAddressesFromNameService(InetAddress.java:Unknown line) java.net.InetAddress.getLocalHost(InetAddress.java:Unknown line) javax.crypto.JarVerifier.getSystemEntropy(JarVerifier.java:Unknown line) ... CPU TIME (ms) BEGIN (total = 6680) Sat Aug 16 05:59:39 2014 rank self accum count trace method 1 74.87% 74.87% 1 308670 java.net.InetAddress$1.lookupAllHostAddr ... 

So it seems that for some reason, JarVerifier is trying to get entropy from the system, and this causes the program to spend 5 seconds in InetAddress $ 1.lookupAllHostAddr ...

Edit 3:

Upgrading Java to version "1.7.0_67" does not fix the problem.

+7
java random cryptography hmac macos
source share
1 answer

I have found a solution. As you can see in Edit 2 , Mac.getInstance() appears to call javax.crypto.JarVerifier.getSystemEntropy() , which ultimately calls java.net.InetAddress.getLocalHost() . According to this article , Java 7 has changed the way InetAddress searches InetAddress local host. For some reason, this causes my machine to have a lookupAllHostAddr value, which takes ~ 5 seconds to complete.

One comment on the article presented a solution that worked for me, which was to add my hostname to /etc/hosts . Following:

 127.0.0.1 localhost 255.255.255.255 broadcasthost ::1 localhost fe80::1%lo0 localhost 

changes to

 127.0.0.1 localhost <replace-me>.local 255.255.255.255 broadcasthost ::1 localhost fe80::1%lo0 localhost 

After changing the hosts file, my time will return to a reasonable 200 ms.

 $ time java Main real 0m0.242s user 0m0.379s sys 0m0.034s 
+6
source share

All Articles