Naïve RSA decryption in Python












1












$begingroup$


I am making a code with basic RSA encryption/decryption. My professor wants me to speed up this function but it is already so simple and I am lost. Any ideas?



def decrypt(kenc,d,n):            
kdec=(kenc**d)%n
return kdec









share|improve this question











$endgroup$

















    1












    $begingroup$


    I am making a code with basic RSA encryption/decryption. My professor wants me to speed up this function but it is already so simple and I am lost. Any ideas?



    def decrypt(kenc,d,n):            
    kdec=(kenc**d)%n
    return kdec









    share|improve this question











    $endgroup$















      1












      1








      1





      $begingroup$


      I am making a code with basic RSA encryption/decryption. My professor wants me to speed up this function but it is already so simple and I am lost. Any ideas?



      def decrypt(kenc,d,n):            
      kdec=(kenc**d)%n
      return kdec









      share|improve this question











      $endgroup$




      I am making a code with basic RSA encryption/decryption. My professor wants me to speed up this function but it is already so simple and I am lost. Any ideas?



      def decrypt(kenc,d,n):            
      kdec=(kenc**d)%n
      return kdec






      python performance homework cryptography






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited 2 hours ago









      200_success

      130k17154419




      130k17154419










      asked 6 hours ago









      Chad TChad T

      211




      211






















          1 Answer
          1






          active

          oldest

          votes


















          4












          $begingroup$

          Simple does not mean fast, so you cannot judge performance based on how simple the implementation looks. Usually the most efficient way to perform a non-trivial task is not also the simplest way to do it. In this case though, there is a much more efficient solution that is about equally simple, and is probably sufficient.



          There is a serious problem with this implementation: it computes kenc**d.



          kenc**d is in general a very big number that takes a long time to compute, and then it takes a long time again to reduce it modulo n. For example, trying it out with 1024bit RSA (the lowest setting!):



          import Crypto
          from Crypto.PublicKey import RSA
          from Crypto import Random

          random_generator = Random.new().read
          key = RSA.generate(1024, random_generator)

          def decrypt(kenc,d,n):
          kdec=(kenc**d)%n
          return kdec

          (ciphertext,) = key.encrypt(42, 0)
          print(decrypt(ciphertext, key.d, key.n))


          This does not finish in a reasonable time. Estimating the size of kenc**d, it is expected to be up to (and usually close to) 1024*1024 = 1048576 bits (both kenc and d are 1024 bit numbers), that will certainly fit on a computer these days, but that's still a very big number and calculations on such large numbers take a lot of time, especially multiplication and remainder.



          There is a simple remedy: use modular exponentiation, which keeps the size of the numbers that it is working with low throughout the whole calculation by reducing modulo n as it goes along. You could implement it yourself, but Python handily provides a built-in function for this: pow(x, e, n)



          So decrypt can be written as:



          def decrypt(kenc, d, n):
          return pow(kenc, d, n)


          With that change, the code above decodes the message quickly.



          Further improvements are possible, but more complicated, and won't be drop-in replacements.






          share|improve this answer









          $endgroup$













            Your Answer





            StackExchange.ifUsing("editor", function () {
            return StackExchange.using("mathjaxEditing", function () {
            StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
            StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
            });
            });
            }, "mathjax-editing");

            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: "196"
            };
            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: false,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: null,
            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%2fcodereview.stackexchange.com%2fquestions%2f215712%2fna%25c3%25afve-rsa-decryption-in-python%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            1 Answer
            1






            active

            oldest

            votes








            1 Answer
            1






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            4












            $begingroup$

            Simple does not mean fast, so you cannot judge performance based on how simple the implementation looks. Usually the most efficient way to perform a non-trivial task is not also the simplest way to do it. In this case though, there is a much more efficient solution that is about equally simple, and is probably sufficient.



            There is a serious problem with this implementation: it computes kenc**d.



            kenc**d is in general a very big number that takes a long time to compute, and then it takes a long time again to reduce it modulo n. For example, trying it out with 1024bit RSA (the lowest setting!):



            import Crypto
            from Crypto.PublicKey import RSA
            from Crypto import Random

            random_generator = Random.new().read
            key = RSA.generate(1024, random_generator)

            def decrypt(kenc,d,n):
            kdec=(kenc**d)%n
            return kdec

            (ciphertext,) = key.encrypt(42, 0)
            print(decrypt(ciphertext, key.d, key.n))


            This does not finish in a reasonable time. Estimating the size of kenc**d, it is expected to be up to (and usually close to) 1024*1024 = 1048576 bits (both kenc and d are 1024 bit numbers), that will certainly fit on a computer these days, but that's still a very big number and calculations on such large numbers take a lot of time, especially multiplication and remainder.



            There is a simple remedy: use modular exponentiation, which keeps the size of the numbers that it is working with low throughout the whole calculation by reducing modulo n as it goes along. You could implement it yourself, but Python handily provides a built-in function for this: pow(x, e, n)



            So decrypt can be written as:



            def decrypt(kenc, d, n):
            return pow(kenc, d, n)


            With that change, the code above decodes the message quickly.



            Further improvements are possible, but more complicated, and won't be drop-in replacements.






            share|improve this answer









            $endgroup$


















              4












              $begingroup$

              Simple does not mean fast, so you cannot judge performance based on how simple the implementation looks. Usually the most efficient way to perform a non-trivial task is not also the simplest way to do it. In this case though, there is a much more efficient solution that is about equally simple, and is probably sufficient.



              There is a serious problem with this implementation: it computes kenc**d.



              kenc**d is in general a very big number that takes a long time to compute, and then it takes a long time again to reduce it modulo n. For example, trying it out with 1024bit RSA (the lowest setting!):



              import Crypto
              from Crypto.PublicKey import RSA
              from Crypto import Random

              random_generator = Random.new().read
              key = RSA.generate(1024, random_generator)

              def decrypt(kenc,d,n):
              kdec=(kenc**d)%n
              return kdec

              (ciphertext,) = key.encrypt(42, 0)
              print(decrypt(ciphertext, key.d, key.n))


              This does not finish in a reasonable time. Estimating the size of kenc**d, it is expected to be up to (and usually close to) 1024*1024 = 1048576 bits (both kenc and d are 1024 bit numbers), that will certainly fit on a computer these days, but that's still a very big number and calculations on such large numbers take a lot of time, especially multiplication and remainder.



              There is a simple remedy: use modular exponentiation, which keeps the size of the numbers that it is working with low throughout the whole calculation by reducing modulo n as it goes along. You could implement it yourself, but Python handily provides a built-in function for this: pow(x, e, n)



              So decrypt can be written as:



              def decrypt(kenc, d, n):
              return pow(kenc, d, n)


              With that change, the code above decodes the message quickly.



              Further improvements are possible, but more complicated, and won't be drop-in replacements.






              share|improve this answer









              $endgroup$
















                4












                4








                4





                $begingroup$

                Simple does not mean fast, so you cannot judge performance based on how simple the implementation looks. Usually the most efficient way to perform a non-trivial task is not also the simplest way to do it. In this case though, there is a much more efficient solution that is about equally simple, and is probably sufficient.



                There is a serious problem with this implementation: it computes kenc**d.



                kenc**d is in general a very big number that takes a long time to compute, and then it takes a long time again to reduce it modulo n. For example, trying it out with 1024bit RSA (the lowest setting!):



                import Crypto
                from Crypto.PublicKey import RSA
                from Crypto import Random

                random_generator = Random.new().read
                key = RSA.generate(1024, random_generator)

                def decrypt(kenc,d,n):
                kdec=(kenc**d)%n
                return kdec

                (ciphertext,) = key.encrypt(42, 0)
                print(decrypt(ciphertext, key.d, key.n))


                This does not finish in a reasonable time. Estimating the size of kenc**d, it is expected to be up to (and usually close to) 1024*1024 = 1048576 bits (both kenc and d are 1024 bit numbers), that will certainly fit on a computer these days, but that's still a very big number and calculations on such large numbers take a lot of time, especially multiplication and remainder.



                There is a simple remedy: use modular exponentiation, which keeps the size of the numbers that it is working with low throughout the whole calculation by reducing modulo n as it goes along. You could implement it yourself, but Python handily provides a built-in function for this: pow(x, e, n)



                So decrypt can be written as:



                def decrypt(kenc, d, n):
                return pow(kenc, d, n)


                With that change, the code above decodes the message quickly.



                Further improvements are possible, but more complicated, and won't be drop-in replacements.






                share|improve this answer









                $endgroup$



                Simple does not mean fast, so you cannot judge performance based on how simple the implementation looks. Usually the most efficient way to perform a non-trivial task is not also the simplest way to do it. In this case though, there is a much more efficient solution that is about equally simple, and is probably sufficient.



                There is a serious problem with this implementation: it computes kenc**d.



                kenc**d is in general a very big number that takes a long time to compute, and then it takes a long time again to reduce it modulo n. For example, trying it out with 1024bit RSA (the lowest setting!):



                import Crypto
                from Crypto.PublicKey import RSA
                from Crypto import Random

                random_generator = Random.new().read
                key = RSA.generate(1024, random_generator)

                def decrypt(kenc,d,n):
                kdec=(kenc**d)%n
                return kdec

                (ciphertext,) = key.encrypt(42, 0)
                print(decrypt(ciphertext, key.d, key.n))


                This does not finish in a reasonable time. Estimating the size of kenc**d, it is expected to be up to (and usually close to) 1024*1024 = 1048576 bits (both kenc and d are 1024 bit numbers), that will certainly fit on a computer these days, but that's still a very big number and calculations on such large numbers take a lot of time, especially multiplication and remainder.



                There is a simple remedy: use modular exponentiation, which keeps the size of the numbers that it is working with low throughout the whole calculation by reducing modulo n as it goes along. You could implement it yourself, but Python handily provides a built-in function for this: pow(x, e, n)



                So decrypt can be written as:



                def decrypt(kenc, d, n):
                return pow(kenc, d, n)


                With that change, the code above decodes the message quickly.



                Further improvements are possible, but more complicated, and won't be drop-in replacements.







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered 4 hours ago









                haroldharold

                1,32867




                1,32867






























                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Code Review Stack Exchange!


                    • 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.


                    Use MathJax to format equations. MathJax reference.


                    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%2fcodereview.stackexchange.com%2fquestions%2f215712%2fna%25c3%25afve-rsa-decryption-in-python%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

                    How to label and detect the document text images

                    Vallis Paradisi

                    Tabula Rosettana