在Windows Java SecureRandom.generateSeed失败:意外的CryptoAPI失败

在生产环境(Windows 2008 R2,AMD 64,8 GB RAM)中,应用程序有时会引发以下exception – 重新启动应用程序可解决问题。

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返回false

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返回false ,但我不知道它为什么失败,以及如何解决它。

任何人都知道为什么会发生这种情况,周围的工作或如何继续调查这个问题?

感谢您的任何build议或答复。 谢谢…

顺便说一句 – 我发现了以下资源 – 但对这个问题不是很有用。

  • https://forums.oracle.com/forums/thread.jspa?threadID=2231037

  • http://bugs.sun.com/view_bug.do?bug_id=6202721

  • 正确使用Java的SecureRandom

  • 在JAVA中安全的随机数生成

虽然你的问题像一个并发访问问题的气味,我有你的解决方法:使用bouncycastle作为JCE提供商,看看是否可以解决您的问题。 把jar放到classpath中,然后运行下面的代码: Security.addProvider(new BouncyCastleProvider());