I Windows mislykkedes Java SecureRandom.generateSeed: Uventet CryptoAPI-fejl

Indlæg af Hanne Mølgaard Plasc

Problem



I produktionsmiljøet (Windows 2008 R2, AMD 64, 8 GB RAM) kaster applikationen nogle gange følgende undtagelse: genstart applikationen løser problemet.


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)


Koden skal ikke have noget problem:


    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);
    }


Kig på JDK kode, find ud af at fejlen skyldes, at Java\_sun\_security\_provider\_NativeSeedGenerator\_nativeGenerateSeed returnerer 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;
    }


CryptGenRandom eller CryptAcquireContextA returnerer false , men jeg ved ikke, hvorfor det fejler, og hvordan man arbejder rundt om det.


Alle ved, hvorfor dette sker, arbejdet rundt eller hvordan man fortsætter med at undersøge dette problem?


Tak for ethvert råd eller svar. Tak...


Btw - Jeg fandt følgende ressourcer - men ikke helt nyttige til dette problem.



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

  • http://bugs.sun.com/view\_bug.do?bug\_id=6202721 [9]

  • Korrekt brug af Java's SecureRandom [10]

  • Sikre tilfældig talgenerering i JAVA [11]


Bedste reference


Mens dit problem lugter som et samtidigt adgangsproblem, har jeg en løsning for dig: Brug bouncycastle som JCE-udbyder og se om det løser dit problem. Sæt krukken i din klassepath, og kør så lidt på dette tidspunkt: Security.addProvider(new BouncyCastleProvider());