RSA online encryption/decryption tool, supporting 1024,2048,4096 bits keys. Because the public key can be deduced by the private key, it can be encrypted and decrypted as long as the private key is provided. RSA-Calculator with tkinter GUI in python. RSA is the algorithm used by modern computers to encrypt and decrypt messages. It is an asymmetric cryptographic algorithm. Asymmetric means that there are two different keys. This is also called public key cryptography, because one of them can be given to everyone. The other key must be kept private. Welcome to CryptoTools.net! This site contains a suite of cryptographic utilities for convenience that operate entirely on the client side. No calculations take place on the server, nor is any data generated or used here sent to the server. If you like, you can view our source on GitHub.
The RSA cryptosystem is one of the first public-key cryptosystems. The encryption key is public, while the decryption key is secret. The RSA encryption security is based on the practical difficulty of 'the factoring problem'. It is constructed using two large prime numbers and only by knowing them can the decryption key be calculated. It is named after the inventors, Ron Rivest, Adi Shamir and Leonard Adleman.
The key for the RSA encryption is generated in the following steps:
If you only have n and e, without access to the prime numbers, p and q, it will be extremely difficult (practically impossible) to calculate d. Therefore, there is no need to keep n and e secret.
Encryption is done using the public key (e and n). This means that anyone can encrypt. If m is the message, calculate:
c ≡ me (mod n)
This calculation is called modular exponentiation and can be done pretty fast, especially if e is not too large.
Decryption is done using the private key (d and n). This means that only the holder of the private key can decrypt. If c is the encrypted message, calculate:
m ≡ cd (mod n)
Choose the prime numbers p = 62273 and q = 56767 (for demo purposes, small prime numbers are chosen, while in a real-world case MUCH bigger prime numbers would have been chosen).
Calculate n = pq = 62273 x 56767. Therefore n = 3535051391.
Calculate (p-1)(q-1) = 62272 x 56766 = 3534932352. Choose and exponent e which has no common divisor with (p-1)(q-1). We cannot choose e = 3, because 3534932352 is divisibly by 3. However, we can choose e = 5.
Calculate the modular multiplicative inverse. It can easily be done using this modular multiplicative inverse tool. The result is d = 1413972941.
Let's encrypt the number 1234567890. We get:
c ≡ 12345678905 (mod 3535051391).
This can easily be calculated using this modular exponentiation tool. The result is 855907849.
Note: To encrypt text, you will first have to convert the text that you want to encrypt to a number (or series of numbers) between 0 and n-1 (3535051390). The text could for instance be converted to ASCII codes, and then divided into blocks of 3 bytes each, which would represent 24-bit integers. You then fill up the remaining bits with a padding, and then each block will be a number between 0 and n-1.
Using the numbers from the previous examples, we get:
m ≡ 8559078491413972941 (mod 3535051391)
Again, this can easily be calculated using this modular exponentiation tool. The result is 1234567890, which is the number we encrypted.
Checksec:
Running binary:
Main function:
First bug: menu_input
can be -1 or 0 resulting in func
array underflow.
Set key function looks ok. It just gets key params as unsigned ints, validate them, compute some other params and save them all in global section. Only validation part is not super restrictid:
Encryption:
Variables:
int g_ebuf[256]
(global encryption buf)char g_pbuf[1024]
(global plaintext buf)int data_counter
is at most 1024Bug1 is that g_ebuf
will overflow (256 vs 1024). Bug2 is that encrypted_result
will overflow (and is not fully zeroed). In general, data_counter
should count words (4 bytes) instead of bytes. Also note that it doesn’t implement real RSA, encryption is done byte-by-byte.
Decryption function:
Bugs:
sscanf
with “%02x”: it is two-times too long.ciphertext
is 512 bytes long, but memcpy
may copy up to 1024 bytesdata_counter / 8
should be data_counter / 4
We can go with bug1 in encryption function (g_ebuf
overflow). Globals layout is:
So we need 256 + 1 + 7 bytes of padding and then pointer to shellcode (for example). Main drawback is that the pointer have to be “encrypted”. That is we need to send some x, such that pow(x, e, n) address. For that we may use dsks
function from CryptoAttacks (it’s “Duplicate-Signature Key Selection” attack described in cryptopals set8). Another thing: program treats params as signed ints, so care should be taken not to overflow anything.
The shellcode may be placed in g_pbuf
. As we have system
address in global section, the shellcode just needs to set args and jump to it.