Naïve RSA decryption in PythonIs my Encryption Module Secure?Encoding and decoding small strings of textC# AES + RSA Encryption ImplementationEncryption in C#My images have secrets A.K.A. the making of aesthetic passwords V.2ISO mode encryption/decryption with BouncyCastleEncryption/decryption by matrix multiplication in CC++ RSA ImplementationGenerate two random primes and find their totientPython RSA/DSA File Cryptography, Key Generation, Key Protection

Why does AES have exactly 10 rounds for a 128-bit key, 12 for 192 bits and 14 for a 256-bit key size?

How can "mimic phobia" be cured or prevented?

How does a computer interpret real numbers?

Multiplicative persistence

What are the advantages of simplicial model categories over non-simplicial ones?

Strong empirical falsification of quantum mechanics based on vacuum energy density

Mimic lecturing on blackboard, facing audience

Moving brute-force search to FPGA

Picking the different solutions to the time independent Schrodinger eqaution

What does chmod -u do?

Plot of a tornado-shaped surface

Why did the EU agree to delay the Brexit deadline?

How could a planet have erratic days?

Hero deduces identity of a killer

Does Doodling or Improvising on the Piano Have Any Benefits?

A social experiment. What is the worst that can happen?

Temporarily disable WLAN internet access for children, but allow it for adults

Store Credit Card Information in Password Manager?

On a tidally locked planet, would time be quantized?

What is the highest possible scrabble score for placing a single tile

I'm the sea and the sun

Can a Canadian Travel to the USA twice, less than 180 days each time?

How to cover method return statement in Apex Class?

How much character growth crosses the line into breaking the character



Naïve RSA decryption in Python


Is my Encryption Module Secure?Encoding and decoding small strings of textC# AES + RSA Encryption ImplementationEncryption in C#My images have secrets A.K.A. the making of aesthetic passwords V.2ISO mode encryption/decryption with BouncyCastleEncryption/decryption by matrix multiplication in CC++ RSA ImplementationGenerate two random primes and find their totientPython RSA/DSA File Cryptography, Key Generation, Key Protection













3












$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$
    You can trivially make the code simpler/shorter and also (minimally) more efficient by removing the unnecessary variable assignment. But of course this isn’t what your professor meant.
    $endgroup$
    – Konrad Rudolph
    Mar 19 at 9:55
















3












$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$
    You can trivially make the code simpler/shorter and also (minimally) more efficient by removing the unnecessary variable assignment. But of course this isn’t what your professor meant.
    $endgroup$
    – Konrad Rudolph
    Mar 19 at 9:55














3












3








3





$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 Mar 19 at 4:09









200_success

130k17155419




130k17155419










asked Mar 18 at 23:55









Chad TChad T

311




311







  • 1




    $begingroup$
    You can trivially make the code simpler/shorter and also (minimally) more efficient by removing the unnecessary variable assignment. But of course this isn’t what your professor meant.
    $endgroup$
    – Konrad Rudolph
    Mar 19 at 9:55













  • 1




    $begingroup$
    You can trivially make the code simpler/shorter and also (minimally) more efficient by removing the unnecessary variable assignment. But of course this isn’t what your professor meant.
    $endgroup$
    – Konrad Rudolph
    Mar 19 at 9:55








1




1




$begingroup$
You can trivially make the code simpler/shorter and also (minimally) more efficient by removing the unnecessary variable assignment. But of course this isn’t what your professor meant.
$endgroup$
– Konrad Rudolph
Mar 19 at 9:55





$begingroup$
You can trivially make the code simpler/shorter and also (minimally) more efficient by removing the unnecessary variable assignment. But of course this isn’t what your professor meant.
$endgroup$
– Konrad Rudolph
Mar 19 at 9:55











1 Answer
1






active

oldest

votes


















12












$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$








  • 1




    $begingroup$
    And of course, it's even faster not to have decrypt at all when all it does is call pow.
    $endgroup$
    – MSalters
    Mar 19 at 10:41










  • $begingroup$
    Keeping decrypt would be a good idea. If you were actually implementing RSA, you would also want PKCS or something there, and the performance penalty of a func call will be small compared to the time to call pow.
    $endgroup$
    – Oscar Smith
    Mar 19 at 16:50






  • 1




    $begingroup$
    Also note that pow probably doesn't exhibit timing independent of base and exponent ("constant-time") allowing for timing side-channel attacks which one may want / need to defend against.
    $endgroup$
    – SEJPM
    Mar 19 at 20:16










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









12












$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$








  • 1




    $begingroup$
    And of course, it's even faster not to have decrypt at all when all it does is call pow.
    $endgroup$
    – MSalters
    Mar 19 at 10:41










  • $begingroup$
    Keeping decrypt would be a good idea. If you were actually implementing RSA, you would also want PKCS or something there, and the performance penalty of a func call will be small compared to the time to call pow.
    $endgroup$
    – Oscar Smith
    Mar 19 at 16:50






  • 1




    $begingroup$
    Also note that pow probably doesn't exhibit timing independent of base and exponent ("constant-time") allowing for timing side-channel attacks which one may want / need to defend against.
    $endgroup$
    – SEJPM
    Mar 19 at 20:16















12












$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$








  • 1




    $begingroup$
    And of course, it's even faster not to have decrypt at all when all it does is call pow.
    $endgroup$
    – MSalters
    Mar 19 at 10:41










  • $begingroup$
    Keeping decrypt would be a good idea. If you were actually implementing RSA, you would also want PKCS or something there, and the performance penalty of a func call will be small compared to the time to call pow.
    $endgroup$
    – Oscar Smith
    Mar 19 at 16:50






  • 1




    $begingroup$
    Also note that pow probably doesn't exhibit timing independent of base and exponent ("constant-time") allowing for timing side-channel attacks which one may want / need to defend against.
    $endgroup$
    – SEJPM
    Mar 19 at 20:16













12












12








12





$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 Mar 19 at 2:13









haroldharold

1,40868




1,40868







  • 1




    $begingroup$
    And of course, it's even faster not to have decrypt at all when all it does is call pow.
    $endgroup$
    – MSalters
    Mar 19 at 10:41










  • $begingroup$
    Keeping decrypt would be a good idea. If you were actually implementing RSA, you would also want PKCS or something there, and the performance penalty of a func call will be small compared to the time to call pow.
    $endgroup$
    – Oscar Smith
    Mar 19 at 16:50






  • 1




    $begingroup$
    Also note that pow probably doesn't exhibit timing independent of base and exponent ("constant-time") allowing for timing side-channel attacks which one may want / need to defend against.
    $endgroup$
    – SEJPM
    Mar 19 at 20:16












  • 1




    $begingroup$
    And of course, it's even faster not to have decrypt at all when all it does is call pow.
    $endgroup$
    – MSalters
    Mar 19 at 10:41










  • $begingroup$
    Keeping decrypt would be a good idea. If you were actually implementing RSA, you would also want PKCS or something there, and the performance penalty of a func call will be small compared to the time to call pow.
    $endgroup$
    – Oscar Smith
    Mar 19 at 16:50






  • 1




    $begingroup$
    Also note that pow probably doesn't exhibit timing independent of base and exponent ("constant-time") allowing for timing side-channel attacks which one may want / need to defend against.
    $endgroup$
    – SEJPM
    Mar 19 at 20:16







1




1




$begingroup$
And of course, it's even faster not to have decrypt at all when all it does is call pow.
$endgroup$
– MSalters
Mar 19 at 10:41




$begingroup$
And of course, it's even faster not to have decrypt at all when all it does is call pow.
$endgroup$
– MSalters
Mar 19 at 10:41












$begingroup$
Keeping decrypt would be a good idea. If you were actually implementing RSA, you would also want PKCS or something there, and the performance penalty of a func call will be small compared to the time to call pow.
$endgroup$
– Oscar Smith
Mar 19 at 16:50




$begingroup$
Keeping decrypt would be a good idea. If you were actually implementing RSA, you would also want PKCS or something there, and the performance penalty of a func call will be small compared to the time to call pow.
$endgroup$
– Oscar Smith
Mar 19 at 16:50




1




1




$begingroup$
Also note that pow probably doesn't exhibit timing independent of base and exponent ("constant-time") allowing for timing side-channel attacks which one may want / need to defend against.
$endgroup$
– SEJPM
Mar 19 at 20:16




$begingroup$
Also note that pow probably doesn't exhibit timing independent of base and exponent ("constant-time") allowing for timing side-channel attacks which one may want / need to defend against.
$endgroup$
– SEJPM
Mar 19 at 20:16

















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

Adding axes to figuresAdding axes labels to LaTeX figuresLaTeX equivalent of ConTeXt buffersRotate a node but not its content: the case of the ellipse decorationHow to define the default vertical distance between nodes?TikZ scaling graphic and adjust node position and keep font sizeNumerical conditional within tikz keys?adding axes to shapesAlign axes across subfiguresAdding figures with a certain orderLine up nested tikz enviroments or how to get rid of themAdding axes labels to LaTeX figures

Luettelo Yhdysvaltain laivaston lentotukialuksista Lähteet | Navigointivalikko

Gary (muusikko) Sisällysluettelo Historia | Rockin' High | Lähteet | Aiheesta muualla | NavigointivalikkoInfobox OKTuomas "Gary" Keskinen Ancaran kitaristiksiProjekti Rockin' High