SecureRandom with NativePRNG vs SHA1PRNG










31















I need to generate cryptographically strong random numbers and byte arrays. For this purpose, I'm using Java's SecureRandom class. But I'm not sure to choose which PRNG algorithm in terms of their cryptographic strength.



Which of the following instances generates a more unpredictable numbers? Or are they equal?



SecureRandom nativePrng = SecureRandom.getInstance("NativePRNG")
SecureRandom sha1Prng = SecureRandom.getInstance("SHA1PRNG")


Moreover, we are able to generate these instances with "SUN" provider (e.g. SecureRandom.getInstance("SHA1PRNG", "SUN")). Do this make a difference?



Thanks in advance.










share|improve this question


























    31















    I need to generate cryptographically strong random numbers and byte arrays. For this purpose, I'm using Java's SecureRandom class. But I'm not sure to choose which PRNG algorithm in terms of their cryptographic strength.



    Which of the following instances generates a more unpredictable numbers? Or are they equal?



    SecureRandom nativePrng = SecureRandom.getInstance("NativePRNG")
    SecureRandom sha1Prng = SecureRandom.getInstance("SHA1PRNG")


    Moreover, we are able to generate these instances with "SUN" provider (e.g. SecureRandom.getInstance("SHA1PRNG", "SUN")). Do this make a difference?



    Thanks in advance.










    share|improve this question
























      31












      31








      31


      6






      I need to generate cryptographically strong random numbers and byte arrays. For this purpose, I'm using Java's SecureRandom class. But I'm not sure to choose which PRNG algorithm in terms of their cryptographic strength.



      Which of the following instances generates a more unpredictable numbers? Or are they equal?



      SecureRandom nativePrng = SecureRandom.getInstance("NativePRNG")
      SecureRandom sha1Prng = SecureRandom.getInstance("SHA1PRNG")


      Moreover, we are able to generate these instances with "SUN" provider (e.g. SecureRandom.getInstance("SHA1PRNG", "SUN")). Do this make a difference?



      Thanks in advance.










      share|improve this question














      I need to generate cryptographically strong random numbers and byte arrays. For this purpose, I'm using Java's SecureRandom class. But I'm not sure to choose which PRNG algorithm in terms of their cryptographic strength.



      Which of the following instances generates a more unpredictable numbers? Or are they equal?



      SecureRandom nativePrng = SecureRandom.getInstance("NativePRNG")
      SecureRandom sha1Prng = SecureRandom.getInstance("SHA1PRNG")


      Moreover, we are able to generate these instances with "SUN" provider (e.g. SecureRandom.getInstance("SHA1PRNG", "SUN")). Do this make a difference?



      Thanks in advance.







      java random cryptography prng






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Dec 23 '14 at 14:46









      ovunccetinovunccetin

      4,74142940




      4,74142940






















          2 Answers
          2






          active

          oldest

          votes


















          47














          TL;DR: Use new SecureRandom() when you're not sure and let the system figure it out. Possibly use SecureRandom.getInstanceStrong() for long term key generation.



          Do not expect a random number generator to generate a specific output sequence within a runtime application, not even if you seed it yourself.




          With random number generators it is always hard to say which is best. Linux and most Unixes have a pretty well thought out random number generator, so it doesn't hurt to use /dev/random or /dev/urandom, i.e. "NativePRNG". Problem with using /dev/random is that it blocks until enough entropy is available. So I would advice against it unless you've got some special requirements with regards to key generation.




          "SHA1PRNG" uses a hash function and a counter, together with a seed. The algorithm is relatively simple, but it hasn't been described well. It is generally thought of to be secure. As it only seeds from one of the system generators during startup and therefore requires fewer calls to the kernel it is likely to be less resource intensive - on my system it runs about 9 times faster than the "NativePRNG" (which is configured to use /dev/urandom). Both seem to tax only one core of my dual core Ubuntu laptop (at a time, it frequently switched from one core to another, that's probably kernel scheduling that's which is to blame). If you need high performance, choose this one, especially if the /dev/urandom device is slow on the specific system configuration.



          Note that the "SHA1PRNG" present in the retired Apache Harmony implementation is different from the one in the SUN provider (used by Oracle in the standard Java SE implementation). The version within Jakarta was used in older versions of Android as well. Although I haven't been able to do a full review, it doesn't look to be very secure.



          EDIT: and I wasn't half wrong about this, SHA1PRNG has been shown not to be pseudo-random for versions < 4.2.2 and more here.



          Beware that "SHA1PRNG" is not an implementation requirement for Java SE. On most runtimes it will be present, but directly referencing it from code will make your code less portable.




          In general it's not a good idea to require a specific provider either. Specifying a provider may hurt interoperability; not every Java runtime may have access to the SUN provider for instance - Android certainly hasn't. It also makes your application less flexible at runtime, i.e. you cannot put a provider higher in the list and use that instead.



          So only indicate a provider if you are dependent on one of the features that it supplies. For instance, you might want to specify a provider if you have a specific hardware device that generates the randoms, or a cryptographic library that has been FIPS certified. It's probably a good idea to make the algorithm/provider a configuration option for your application if you have to specify a provider.



          The idea of not specifying a provider is also present in this Android developer Security Blog.




          So try and refrain from choosing any specific random generator. Instead, simply go for the empty argument constructor: new SecureRandom() and let the system choose the best random number generator. It is possible to use the new configurable SecureRandom.getInstanceStrong() in Java 8 and higher if you have any specific requirements for e.g. long term key generation.



          Don't cache instances of SecureRandom, just let them seed themselves initially and let the VM handle them. I did not see a noticeable difference in operation.




          When not to use SecureRandom at all:



          As a general warning I strongly advice against using the random number generator for anything other than random number generation. Even if you can seed it yourself and even if you choose Sun's SHA1PRNG, don't count on being able to extract the same sequence of random numbers from the random number generator. So do not use it for key derivation from passwords, to name one example.



          If you do require a repeating sequence then use a stream cipher and use the seed information for the key and IV. Encrypt plaintext consisting of zeros to retrieve the key stream of pseudo random values. Alternatively you could use a extendable-output function (XOF) such as SHAKE128 or SHAKE256 (where available).



          You may want to consider a different, non-secure random number generator instead of SecureRandom if the available RNG's deliver insufficient performance and if security is not an issue. No SecureRandom implementation will be as fast as non secure random number generators such as the Mersenne Twister algorithm or the algorithm implemented by the Random class. Those have been optimized for simplicity and speed rather than security or quality.






          share|improve this answer




















          • 3





            Wouldn't it open a security hole if you just blindly trust any SecureRandom service picked up by the system?

            – neurite
            Mar 29 '15 at 8:38






          • 1





            No, not really. If the system cannot be trusted the random number generator is only a small part of the problem. Besides that, the other random number generators are usually seeded by a random number generator of the OS. So they are still dependent on the security of the system RNG. The only way around that is to have your own entropy source. Newer Intel chips have the RDRAND instruction, but in case of Java, you'll first need to go native before you can use it.

            – Maarten Bodewes
            Mar 29 '15 at 9:11






          • 2





            @MaartenBodewes answer is great, but I prefer to check myself sources, here's the JDK8 source code : sun.security.provider.SecureRandom, sun.security.provider.NativePRNG, sun.security.provider.SeedGenerator

            – Brice
            May 31 '16 at 11:02






          • 2





            @FrederickNord 1) the algorithm is unknown and may (and does) change between implementations and the seed may not be used as only input to the state, the algorithm may be pre-seeded by the operating system. 2) use PBKDF2, functionality is build into Java / JCE.

            – Maarten Bodewes
            Sep 27 '16 at 9:47







          • 2





            @Brice As already indicated - implementation of unspecified algorithms may change between versions. You'll in the end have to rely on the JCE and JavaDoc documentation. After you've don't that, sure, take a look at the source and see if it has been implemented as expected. When buying a car, you don't initially look under the hood to measure the CC, right? Well, with the exception of Volkswagen of course.

            – Maarten Bodewes
            Sep 27 '16 at 9:53



















          4














          As from a ref. here:




          Native PRNG implementation for Solaris/Linux. It interacts with
          /dev/random and /dev/urandom, so it is only available if those files
          are present. Otherwise, SHA1PRNG is used instead of this class.




          The SUN provider might be used as default (mainly dependent on the order of the provider which is present).






          share|improve this answer






















            Your Answer






            StackExchange.ifUsing("editor", function ()
            StackExchange.using("externalEditor", function ()
            StackExchange.using("snippets", function ()
            StackExchange.snippets.init();
            );
            );
            , "code-snippets");

            StackExchange.ready(function()
            var channelOptions =
            tags: "".split(" "),
            id: "1"
            ;
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function()
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled)
            StackExchange.using("snippets", function()
            createEditor();
            );

            else
            createEditor();

            );

            function createEditor()
            StackExchange.prepareEditor(
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader:
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            ,
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            );



            );













            draft saved

            draft discarded


















            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f27622625%2fsecurerandom-with-nativeprng-vs-sha1prng%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown

























            2 Answers
            2






            active

            oldest

            votes








            2 Answers
            2






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            47














            TL;DR: Use new SecureRandom() when you're not sure and let the system figure it out. Possibly use SecureRandom.getInstanceStrong() for long term key generation.



            Do not expect a random number generator to generate a specific output sequence within a runtime application, not even if you seed it yourself.




            With random number generators it is always hard to say which is best. Linux and most Unixes have a pretty well thought out random number generator, so it doesn't hurt to use /dev/random or /dev/urandom, i.e. "NativePRNG". Problem with using /dev/random is that it blocks until enough entropy is available. So I would advice against it unless you've got some special requirements with regards to key generation.




            "SHA1PRNG" uses a hash function and a counter, together with a seed. The algorithm is relatively simple, but it hasn't been described well. It is generally thought of to be secure. As it only seeds from one of the system generators during startup and therefore requires fewer calls to the kernel it is likely to be less resource intensive - on my system it runs about 9 times faster than the "NativePRNG" (which is configured to use /dev/urandom). Both seem to tax only one core of my dual core Ubuntu laptop (at a time, it frequently switched from one core to another, that's probably kernel scheduling that's which is to blame). If you need high performance, choose this one, especially if the /dev/urandom device is slow on the specific system configuration.



            Note that the "SHA1PRNG" present in the retired Apache Harmony implementation is different from the one in the SUN provider (used by Oracle in the standard Java SE implementation). The version within Jakarta was used in older versions of Android as well. Although I haven't been able to do a full review, it doesn't look to be very secure.



            EDIT: and I wasn't half wrong about this, SHA1PRNG has been shown not to be pseudo-random for versions < 4.2.2 and more here.



            Beware that "SHA1PRNG" is not an implementation requirement for Java SE. On most runtimes it will be present, but directly referencing it from code will make your code less portable.




            In general it's not a good idea to require a specific provider either. Specifying a provider may hurt interoperability; not every Java runtime may have access to the SUN provider for instance - Android certainly hasn't. It also makes your application less flexible at runtime, i.e. you cannot put a provider higher in the list and use that instead.



            So only indicate a provider if you are dependent on one of the features that it supplies. For instance, you might want to specify a provider if you have a specific hardware device that generates the randoms, or a cryptographic library that has been FIPS certified. It's probably a good idea to make the algorithm/provider a configuration option for your application if you have to specify a provider.



            The idea of not specifying a provider is also present in this Android developer Security Blog.




            So try and refrain from choosing any specific random generator. Instead, simply go for the empty argument constructor: new SecureRandom() and let the system choose the best random number generator. It is possible to use the new configurable SecureRandom.getInstanceStrong() in Java 8 and higher if you have any specific requirements for e.g. long term key generation.



            Don't cache instances of SecureRandom, just let them seed themselves initially and let the VM handle them. I did not see a noticeable difference in operation.




            When not to use SecureRandom at all:



            As a general warning I strongly advice against using the random number generator for anything other than random number generation. Even if you can seed it yourself and even if you choose Sun's SHA1PRNG, don't count on being able to extract the same sequence of random numbers from the random number generator. So do not use it for key derivation from passwords, to name one example.



            If you do require a repeating sequence then use a stream cipher and use the seed information for the key and IV. Encrypt plaintext consisting of zeros to retrieve the key stream of pseudo random values. Alternatively you could use a extendable-output function (XOF) such as SHAKE128 or SHAKE256 (where available).



            You may want to consider a different, non-secure random number generator instead of SecureRandom if the available RNG's deliver insufficient performance and if security is not an issue. No SecureRandom implementation will be as fast as non secure random number generators such as the Mersenne Twister algorithm or the algorithm implemented by the Random class. Those have been optimized for simplicity and speed rather than security or quality.






            share|improve this answer




















            • 3





              Wouldn't it open a security hole if you just blindly trust any SecureRandom service picked up by the system?

              – neurite
              Mar 29 '15 at 8:38






            • 1





              No, not really. If the system cannot be trusted the random number generator is only a small part of the problem. Besides that, the other random number generators are usually seeded by a random number generator of the OS. So they are still dependent on the security of the system RNG. The only way around that is to have your own entropy source. Newer Intel chips have the RDRAND instruction, but in case of Java, you'll first need to go native before you can use it.

              – Maarten Bodewes
              Mar 29 '15 at 9:11






            • 2





              @MaartenBodewes answer is great, but I prefer to check myself sources, here's the JDK8 source code : sun.security.provider.SecureRandom, sun.security.provider.NativePRNG, sun.security.provider.SeedGenerator

              – Brice
              May 31 '16 at 11:02






            • 2





              @FrederickNord 1) the algorithm is unknown and may (and does) change between implementations and the seed may not be used as only input to the state, the algorithm may be pre-seeded by the operating system. 2) use PBKDF2, functionality is build into Java / JCE.

              – Maarten Bodewes
              Sep 27 '16 at 9:47







            • 2





              @Brice As already indicated - implementation of unspecified algorithms may change between versions. You'll in the end have to rely on the JCE and JavaDoc documentation. After you've don't that, sure, take a look at the source and see if it has been implemented as expected. When buying a car, you don't initially look under the hood to measure the CC, right? Well, with the exception of Volkswagen of course.

              – Maarten Bodewes
              Sep 27 '16 at 9:53
















            47














            TL;DR: Use new SecureRandom() when you're not sure and let the system figure it out. Possibly use SecureRandom.getInstanceStrong() for long term key generation.



            Do not expect a random number generator to generate a specific output sequence within a runtime application, not even if you seed it yourself.




            With random number generators it is always hard to say which is best. Linux and most Unixes have a pretty well thought out random number generator, so it doesn't hurt to use /dev/random or /dev/urandom, i.e. "NativePRNG". Problem with using /dev/random is that it blocks until enough entropy is available. So I would advice against it unless you've got some special requirements with regards to key generation.




            "SHA1PRNG" uses a hash function and a counter, together with a seed. The algorithm is relatively simple, but it hasn't been described well. It is generally thought of to be secure. As it only seeds from one of the system generators during startup and therefore requires fewer calls to the kernel it is likely to be less resource intensive - on my system it runs about 9 times faster than the "NativePRNG" (which is configured to use /dev/urandom). Both seem to tax only one core of my dual core Ubuntu laptop (at a time, it frequently switched from one core to another, that's probably kernel scheduling that's which is to blame). If you need high performance, choose this one, especially if the /dev/urandom device is slow on the specific system configuration.



            Note that the "SHA1PRNG" present in the retired Apache Harmony implementation is different from the one in the SUN provider (used by Oracle in the standard Java SE implementation). The version within Jakarta was used in older versions of Android as well. Although I haven't been able to do a full review, it doesn't look to be very secure.



            EDIT: and I wasn't half wrong about this, SHA1PRNG has been shown not to be pseudo-random for versions < 4.2.2 and more here.



            Beware that "SHA1PRNG" is not an implementation requirement for Java SE. On most runtimes it will be present, but directly referencing it from code will make your code less portable.




            In general it's not a good idea to require a specific provider either. Specifying a provider may hurt interoperability; not every Java runtime may have access to the SUN provider for instance - Android certainly hasn't. It also makes your application less flexible at runtime, i.e. you cannot put a provider higher in the list and use that instead.



            So only indicate a provider if you are dependent on one of the features that it supplies. For instance, you might want to specify a provider if you have a specific hardware device that generates the randoms, or a cryptographic library that has been FIPS certified. It's probably a good idea to make the algorithm/provider a configuration option for your application if you have to specify a provider.



            The idea of not specifying a provider is also present in this Android developer Security Blog.




            So try and refrain from choosing any specific random generator. Instead, simply go for the empty argument constructor: new SecureRandom() and let the system choose the best random number generator. It is possible to use the new configurable SecureRandom.getInstanceStrong() in Java 8 and higher if you have any specific requirements for e.g. long term key generation.



            Don't cache instances of SecureRandom, just let them seed themselves initially and let the VM handle them. I did not see a noticeable difference in operation.




            When not to use SecureRandom at all:



            As a general warning I strongly advice against using the random number generator for anything other than random number generation. Even if you can seed it yourself and even if you choose Sun's SHA1PRNG, don't count on being able to extract the same sequence of random numbers from the random number generator. So do not use it for key derivation from passwords, to name one example.



            If you do require a repeating sequence then use a stream cipher and use the seed information for the key and IV. Encrypt plaintext consisting of zeros to retrieve the key stream of pseudo random values. Alternatively you could use a extendable-output function (XOF) such as SHAKE128 or SHAKE256 (where available).



            You may want to consider a different, non-secure random number generator instead of SecureRandom if the available RNG's deliver insufficient performance and if security is not an issue. No SecureRandom implementation will be as fast as non secure random number generators such as the Mersenne Twister algorithm or the algorithm implemented by the Random class. Those have been optimized for simplicity and speed rather than security or quality.






            share|improve this answer




















            • 3





              Wouldn't it open a security hole if you just blindly trust any SecureRandom service picked up by the system?

              – neurite
              Mar 29 '15 at 8:38






            • 1





              No, not really. If the system cannot be trusted the random number generator is only a small part of the problem. Besides that, the other random number generators are usually seeded by a random number generator of the OS. So they are still dependent on the security of the system RNG. The only way around that is to have your own entropy source. Newer Intel chips have the RDRAND instruction, but in case of Java, you'll first need to go native before you can use it.

              – Maarten Bodewes
              Mar 29 '15 at 9:11






            • 2





              @MaartenBodewes answer is great, but I prefer to check myself sources, here's the JDK8 source code : sun.security.provider.SecureRandom, sun.security.provider.NativePRNG, sun.security.provider.SeedGenerator

              – Brice
              May 31 '16 at 11:02






            • 2





              @FrederickNord 1) the algorithm is unknown and may (and does) change between implementations and the seed may not be used as only input to the state, the algorithm may be pre-seeded by the operating system. 2) use PBKDF2, functionality is build into Java / JCE.

              – Maarten Bodewes
              Sep 27 '16 at 9:47







            • 2





              @Brice As already indicated - implementation of unspecified algorithms may change between versions. You'll in the end have to rely on the JCE and JavaDoc documentation. After you've don't that, sure, take a look at the source and see if it has been implemented as expected. When buying a car, you don't initially look under the hood to measure the CC, right? Well, with the exception of Volkswagen of course.

              – Maarten Bodewes
              Sep 27 '16 at 9:53














            47












            47








            47







            TL;DR: Use new SecureRandom() when you're not sure and let the system figure it out. Possibly use SecureRandom.getInstanceStrong() for long term key generation.



            Do not expect a random number generator to generate a specific output sequence within a runtime application, not even if you seed it yourself.




            With random number generators it is always hard to say which is best. Linux and most Unixes have a pretty well thought out random number generator, so it doesn't hurt to use /dev/random or /dev/urandom, i.e. "NativePRNG". Problem with using /dev/random is that it blocks until enough entropy is available. So I would advice against it unless you've got some special requirements with regards to key generation.




            "SHA1PRNG" uses a hash function and a counter, together with a seed. The algorithm is relatively simple, but it hasn't been described well. It is generally thought of to be secure. As it only seeds from one of the system generators during startup and therefore requires fewer calls to the kernel it is likely to be less resource intensive - on my system it runs about 9 times faster than the "NativePRNG" (which is configured to use /dev/urandom). Both seem to tax only one core of my dual core Ubuntu laptop (at a time, it frequently switched from one core to another, that's probably kernel scheduling that's which is to blame). If you need high performance, choose this one, especially if the /dev/urandom device is slow on the specific system configuration.



            Note that the "SHA1PRNG" present in the retired Apache Harmony implementation is different from the one in the SUN provider (used by Oracle in the standard Java SE implementation). The version within Jakarta was used in older versions of Android as well. Although I haven't been able to do a full review, it doesn't look to be very secure.



            EDIT: and I wasn't half wrong about this, SHA1PRNG has been shown not to be pseudo-random for versions < 4.2.2 and more here.



            Beware that "SHA1PRNG" is not an implementation requirement for Java SE. On most runtimes it will be present, but directly referencing it from code will make your code less portable.




            In general it's not a good idea to require a specific provider either. Specifying a provider may hurt interoperability; not every Java runtime may have access to the SUN provider for instance - Android certainly hasn't. It also makes your application less flexible at runtime, i.e. you cannot put a provider higher in the list and use that instead.



            So only indicate a provider if you are dependent on one of the features that it supplies. For instance, you might want to specify a provider if you have a specific hardware device that generates the randoms, or a cryptographic library that has been FIPS certified. It's probably a good idea to make the algorithm/provider a configuration option for your application if you have to specify a provider.



            The idea of not specifying a provider is also present in this Android developer Security Blog.




            So try and refrain from choosing any specific random generator. Instead, simply go for the empty argument constructor: new SecureRandom() and let the system choose the best random number generator. It is possible to use the new configurable SecureRandom.getInstanceStrong() in Java 8 and higher if you have any specific requirements for e.g. long term key generation.



            Don't cache instances of SecureRandom, just let them seed themselves initially and let the VM handle them. I did not see a noticeable difference in operation.




            When not to use SecureRandom at all:



            As a general warning I strongly advice against using the random number generator for anything other than random number generation. Even if you can seed it yourself and even if you choose Sun's SHA1PRNG, don't count on being able to extract the same sequence of random numbers from the random number generator. So do not use it for key derivation from passwords, to name one example.



            If you do require a repeating sequence then use a stream cipher and use the seed information for the key and IV. Encrypt plaintext consisting of zeros to retrieve the key stream of pseudo random values. Alternatively you could use a extendable-output function (XOF) such as SHAKE128 or SHAKE256 (where available).



            You may want to consider a different, non-secure random number generator instead of SecureRandom if the available RNG's deliver insufficient performance and if security is not an issue. No SecureRandom implementation will be as fast as non secure random number generators such as the Mersenne Twister algorithm or the algorithm implemented by the Random class. Those have been optimized for simplicity and speed rather than security or quality.






            share|improve this answer















            TL;DR: Use new SecureRandom() when you're not sure and let the system figure it out. Possibly use SecureRandom.getInstanceStrong() for long term key generation.



            Do not expect a random number generator to generate a specific output sequence within a runtime application, not even if you seed it yourself.




            With random number generators it is always hard to say which is best. Linux and most Unixes have a pretty well thought out random number generator, so it doesn't hurt to use /dev/random or /dev/urandom, i.e. "NativePRNG". Problem with using /dev/random is that it blocks until enough entropy is available. So I would advice against it unless you've got some special requirements with regards to key generation.




            "SHA1PRNG" uses a hash function and a counter, together with a seed. The algorithm is relatively simple, but it hasn't been described well. It is generally thought of to be secure. As it only seeds from one of the system generators during startup and therefore requires fewer calls to the kernel it is likely to be less resource intensive - on my system it runs about 9 times faster than the "NativePRNG" (which is configured to use /dev/urandom). Both seem to tax only one core of my dual core Ubuntu laptop (at a time, it frequently switched from one core to another, that's probably kernel scheduling that's which is to blame). If you need high performance, choose this one, especially if the /dev/urandom device is slow on the specific system configuration.



            Note that the "SHA1PRNG" present in the retired Apache Harmony implementation is different from the one in the SUN provider (used by Oracle in the standard Java SE implementation). The version within Jakarta was used in older versions of Android as well. Although I haven't been able to do a full review, it doesn't look to be very secure.



            EDIT: and I wasn't half wrong about this, SHA1PRNG has been shown not to be pseudo-random for versions < 4.2.2 and more here.



            Beware that "SHA1PRNG" is not an implementation requirement for Java SE. On most runtimes it will be present, but directly referencing it from code will make your code less portable.




            In general it's not a good idea to require a specific provider either. Specifying a provider may hurt interoperability; not every Java runtime may have access to the SUN provider for instance - Android certainly hasn't. It also makes your application less flexible at runtime, i.e. you cannot put a provider higher in the list and use that instead.



            So only indicate a provider if you are dependent on one of the features that it supplies. For instance, you might want to specify a provider if you have a specific hardware device that generates the randoms, or a cryptographic library that has been FIPS certified. It's probably a good idea to make the algorithm/provider a configuration option for your application if you have to specify a provider.



            The idea of not specifying a provider is also present in this Android developer Security Blog.




            So try and refrain from choosing any specific random generator. Instead, simply go for the empty argument constructor: new SecureRandom() and let the system choose the best random number generator. It is possible to use the new configurable SecureRandom.getInstanceStrong() in Java 8 and higher if you have any specific requirements for e.g. long term key generation.



            Don't cache instances of SecureRandom, just let them seed themselves initially and let the VM handle them. I did not see a noticeable difference in operation.




            When not to use SecureRandom at all:



            As a general warning I strongly advice against using the random number generator for anything other than random number generation. Even if you can seed it yourself and even if you choose Sun's SHA1PRNG, don't count on being able to extract the same sequence of random numbers from the random number generator. So do not use it for key derivation from passwords, to name one example.



            If you do require a repeating sequence then use a stream cipher and use the seed information for the key and IV. Encrypt plaintext consisting of zeros to retrieve the key stream of pseudo random values. Alternatively you could use a extendable-output function (XOF) such as SHAKE128 or SHAKE256 (where available).



            You may want to consider a different, non-secure random number generator instead of SecureRandom if the available RNG's deliver insufficient performance and if security is not an issue. No SecureRandom implementation will be as fast as non secure random number generators such as the Mersenne Twister algorithm or the algorithm implemented by the Random class. Those have been optimized for simplicity and speed rather than security or quality.







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Dec 20 '18 at 16:54

























            answered Dec 24 '14 at 14:28









            Maarten BodewesMaarten Bodewes

            61.8k1078172




            61.8k1078172







            • 3





              Wouldn't it open a security hole if you just blindly trust any SecureRandom service picked up by the system?

              – neurite
              Mar 29 '15 at 8:38






            • 1





              No, not really. If the system cannot be trusted the random number generator is only a small part of the problem. Besides that, the other random number generators are usually seeded by a random number generator of the OS. So they are still dependent on the security of the system RNG. The only way around that is to have your own entropy source. Newer Intel chips have the RDRAND instruction, but in case of Java, you'll first need to go native before you can use it.

              – Maarten Bodewes
              Mar 29 '15 at 9:11






            • 2





              @MaartenBodewes answer is great, but I prefer to check myself sources, here's the JDK8 source code : sun.security.provider.SecureRandom, sun.security.provider.NativePRNG, sun.security.provider.SeedGenerator

              – Brice
              May 31 '16 at 11:02






            • 2





              @FrederickNord 1) the algorithm is unknown and may (and does) change between implementations and the seed may not be used as only input to the state, the algorithm may be pre-seeded by the operating system. 2) use PBKDF2, functionality is build into Java / JCE.

              – Maarten Bodewes
              Sep 27 '16 at 9:47







            • 2





              @Brice As already indicated - implementation of unspecified algorithms may change between versions. You'll in the end have to rely on the JCE and JavaDoc documentation. After you've don't that, sure, take a look at the source and see if it has been implemented as expected. When buying a car, you don't initially look under the hood to measure the CC, right? Well, with the exception of Volkswagen of course.

              – Maarten Bodewes
              Sep 27 '16 at 9:53













            • 3





              Wouldn't it open a security hole if you just blindly trust any SecureRandom service picked up by the system?

              – neurite
              Mar 29 '15 at 8:38






            • 1





              No, not really. If the system cannot be trusted the random number generator is only a small part of the problem. Besides that, the other random number generators are usually seeded by a random number generator of the OS. So they are still dependent on the security of the system RNG. The only way around that is to have your own entropy source. Newer Intel chips have the RDRAND instruction, but in case of Java, you'll first need to go native before you can use it.

              – Maarten Bodewes
              Mar 29 '15 at 9:11






            • 2





              @MaartenBodewes answer is great, but I prefer to check myself sources, here's the JDK8 source code : sun.security.provider.SecureRandom, sun.security.provider.NativePRNG, sun.security.provider.SeedGenerator

              – Brice
              May 31 '16 at 11:02






            • 2





              @FrederickNord 1) the algorithm is unknown and may (and does) change between implementations and the seed may not be used as only input to the state, the algorithm may be pre-seeded by the operating system. 2) use PBKDF2, functionality is build into Java / JCE.

              – Maarten Bodewes
              Sep 27 '16 at 9:47







            • 2





              @Brice As already indicated - implementation of unspecified algorithms may change between versions. You'll in the end have to rely on the JCE and JavaDoc documentation. After you've don't that, sure, take a look at the source and see if it has been implemented as expected. When buying a car, you don't initially look under the hood to measure the CC, right? Well, with the exception of Volkswagen of course.

              – Maarten Bodewes
              Sep 27 '16 at 9:53








            3




            3





            Wouldn't it open a security hole if you just blindly trust any SecureRandom service picked up by the system?

            – neurite
            Mar 29 '15 at 8:38





            Wouldn't it open a security hole if you just blindly trust any SecureRandom service picked up by the system?

            – neurite
            Mar 29 '15 at 8:38




            1




            1





            No, not really. If the system cannot be trusted the random number generator is only a small part of the problem. Besides that, the other random number generators are usually seeded by a random number generator of the OS. So they are still dependent on the security of the system RNG. The only way around that is to have your own entropy source. Newer Intel chips have the RDRAND instruction, but in case of Java, you'll first need to go native before you can use it.

            – Maarten Bodewes
            Mar 29 '15 at 9:11





            No, not really. If the system cannot be trusted the random number generator is only a small part of the problem. Besides that, the other random number generators are usually seeded by a random number generator of the OS. So they are still dependent on the security of the system RNG. The only way around that is to have your own entropy source. Newer Intel chips have the RDRAND instruction, but in case of Java, you'll first need to go native before you can use it.

            – Maarten Bodewes
            Mar 29 '15 at 9:11




            2




            2





            @MaartenBodewes answer is great, but I prefer to check myself sources, here's the JDK8 source code : sun.security.provider.SecureRandom, sun.security.provider.NativePRNG, sun.security.provider.SeedGenerator

            – Brice
            May 31 '16 at 11:02





            @MaartenBodewes answer is great, but I prefer to check myself sources, here's the JDK8 source code : sun.security.provider.SecureRandom, sun.security.provider.NativePRNG, sun.security.provider.SeedGenerator

            – Brice
            May 31 '16 at 11:02




            2




            2





            @FrederickNord 1) the algorithm is unknown and may (and does) change between implementations and the seed may not be used as only input to the state, the algorithm may be pre-seeded by the operating system. 2) use PBKDF2, functionality is build into Java / JCE.

            – Maarten Bodewes
            Sep 27 '16 at 9:47






            @FrederickNord 1) the algorithm is unknown and may (and does) change between implementations and the seed may not be used as only input to the state, the algorithm may be pre-seeded by the operating system. 2) use PBKDF2, functionality is build into Java / JCE.

            – Maarten Bodewes
            Sep 27 '16 at 9:47





            2




            2





            @Brice As already indicated - implementation of unspecified algorithms may change between versions. You'll in the end have to rely on the JCE and JavaDoc documentation. After you've don't that, sure, take a look at the source and see if it has been implemented as expected. When buying a car, you don't initially look under the hood to measure the CC, right? Well, with the exception of Volkswagen of course.

            – Maarten Bodewes
            Sep 27 '16 at 9:53






            @Brice As already indicated - implementation of unspecified algorithms may change between versions. You'll in the end have to rely on the JCE and JavaDoc documentation. After you've don't that, sure, take a look at the source and see if it has been implemented as expected. When buying a car, you don't initially look under the hood to measure the CC, right? Well, with the exception of Volkswagen of course.

            – Maarten Bodewes
            Sep 27 '16 at 9:53














            4














            As from a ref. here:




            Native PRNG implementation for Solaris/Linux. It interacts with
            /dev/random and /dev/urandom, so it is only available if those files
            are present. Otherwise, SHA1PRNG is used instead of this class.




            The SUN provider might be used as default (mainly dependent on the order of the provider which is present).






            share|improve this answer



























              4














              As from a ref. here:




              Native PRNG implementation for Solaris/Linux. It interacts with
              /dev/random and /dev/urandom, so it is only available if those files
              are present. Otherwise, SHA1PRNG is used instead of this class.




              The SUN provider might be used as default (mainly dependent on the order of the provider which is present).






              share|improve this answer

























                4












                4








                4







                As from a ref. here:




                Native PRNG implementation for Solaris/Linux. It interacts with
                /dev/random and /dev/urandom, so it is only available if those files
                are present. Otherwise, SHA1PRNG is used instead of this class.




                The SUN provider might be used as default (mainly dependent on the order of the provider which is present).






                share|improve this answer













                As from a ref. here:




                Native PRNG implementation for Solaris/Linux. It interacts with
                /dev/random and /dev/urandom, so it is only available if those files
                are present. Otherwise, SHA1PRNG is used instead of this class.




                The SUN provider might be used as default (mainly dependent on the order of the provider which is present).







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Dec 23 '14 at 14:58









                nitishagarnitishagar

                5,52731532




                5,52731532



























                    draft saved

                    draft discarded
















































                    Thanks for contributing an answer to Stack Overflow!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid


                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.

                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function ()
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f27622625%2fsecurerandom-with-nativeprng-vs-sha1prng%23new-answer', 'question_page');

                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    Top Tejano songwriter Luis Silva dead of heart attack at 64

                    政党

                    天津地下鉄3号線