2012-03-27 29 views
6

在生產環境(Windows 2008 R2,AMD 64,8 GB RAM)中,應用程序有時會拋出以下異常 - 重新啓動應用程序可解決問題。在Windows中Java SecureRandom.generateSeed失敗:意外的CryptoAPI故障

Caused by: java.lang.InternalError: Unexpected CryptoAPI failure generating seed 
at sun.security.provider.NativeSeedGenerator.getSeedBytes(NativeSeedGenerator.java:43) 
at sun.security.provider.SeedGenerator.generateSeed(SeedGenerator.java:117) 
at sun.security.provider.SecureRandom.engineGenerateSeed(SecureRandom.java:114) 
at java.security.SecureRandom.generateSeed(SecureRandom.java:475) 

的代碼應該沒有問題:

public void generateToken() 
    { 
     SecureRandom secureRandom = new SecureRandom(); 
     int seedByteCount = 20; 
     byte[] seed = secureRandom.generateSeed(seedByteCount); 
     secureRandom.setSeed(seed); 
     String random = String.valueOf(secureRandom.nextLong()); 
     setToken(random); 
    } 

看了看JDK的代碼,找出錯誤是因爲Java_sun_security_provider_NativeSeedGenerator_nativeGenerateSeed回報

OpenJDK的-7U2 -fcs-src-b13-17_nov_2011 \ jdk \ src \ windows \ native \ sun \ security \ provider \ WinCAPISeedGenerator.c:

JNIEXPORT jboolean JNICALL Java_sun_security_provider_NativeSeedGenerator_nativeGenerateSeed(JNIEnv *env, jclass clazz, jbyteArray randArray) 
    { 
     HCRYPTPROV hCryptProv; 
     jboolean result = JNI_FALSE; 
     jsize numBytes; 
     jbyte* randBytes; 

     if (CryptAcquireContextA(&hCryptProv, "J2SE", NULL, PROV_RSA_FULL, 0) == FALSE) { 
      /* If CSP context hasn't been created, create one. */ 
      if (CryptAcquireContextA(&hCryptProv, "J2SE", NULL, PROV_RSA_FULL, 
        CRYPT_NEWKEYSET) == FALSE) { 
       return result; 
      } 
     } 

     numBytes = (*env)->GetArrayLength(env, randArray); 
     randBytes = (*env)->GetByteArrayElements(env, randArray, NULL); 
     if (CryptGenRandom(hCryptProv, numBytes, randBytes)) { 
      result = JNI_TRUE; 
     } 
     (*env)->ReleaseByteArrayElements(env, randArray, randBytes, 0); 

     CryptReleaseContext(hCryptProv, 0); 

     return result; 
    } 

CryptGenRandomCryptAcquireContextA回報,但我不知道它爲什麼失敗,以及如何解決它。

任何人都知道爲什麼會發生這種情況,解決這個問題或如何繼續調查這個問題?

感謝您的任何建議或答覆。謝謝...

順便說一句 - 我發現了以下資源 - 但對這個問題並不是很有用。

+1

看看答案[here](http://stackoverflow.com/questions/8667129/cryptacquirecontexta-fails-in-c-clr-換aloaha的加密提供者)。你的環境中是否有可能的競爭條件? – Mersenne 2012-03-27 09:23:51

回答

2

雖然你的問題聞起來像一個併發訪問問題,我有一個解決方法:使用bouncycastle作爲JCE提供程序,看看是否可以解決您的問題。把jar放到你的類路徑中,然後在某些時候運行下面的代碼:Security.addProvider(new BouncyCastleProvider());

+0

感謝您的回覆,是的,正如您所說這是一個併發訪問相關問題,我們優化了我們的代碼:在舊代碼中,我們可以爲每個請求生成Seeds,這是不好的,因爲generateSeed會消耗大量資源。在新代碼中,我們只調用一次generateSeed。這似乎解決了客戶遇到的問題。 – 2012-09-01 16:53:19