RSA Encryption using the user-defined keys in python - python

I am trying to encrypt a small amount of data using RSA algorithm using python. The problem is I have the public and private RSA key. Both are stored in .pem and .ppk respectively. I am not able to find any help in google which will help me encrypt it using my keys. All the code and examples I saw generates its own keys. Is there a way where I can use my own keys to encrypt and decrypt the data?

You can use the rsa module .
import rsa
with open('public.ppm','r') as key_pub_file:
key_pub = key_pub_file.read()
message = "hello".encode('utf8')
enc_msg = rsa.encrypt(message, key_pub)
print(enc_msg)

from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5 as Cipher_PKCS1_v1_5
from base64 import b64decode,b64encode
f1 = open('public.ppm','r')
pubkey = f1.read()
#pubkey = 'MIGfMA0GCSqGSIb3DQEBA3UAWE0HSQ77CwP/8UbX07W2XKwng/nMT1R7vaz+2EeNR/FitFXwIDAQAB'
msg = "test"
keyDER = b64decode(pubkey)
keyPub = RSA.importKey(keyDER)
cipher = Cipher_PKCS1_v1_5.new(keyPub)
cipher_text = cipher.encrypt(msg.encode())
emsg = b64encode(cipher_text)
print(emsg)
While trying, I found this code to be working. msg variable contains the data to be encrypted and pubkey contains the public key which ill be taking from ppm file.

Related

Produce different signing messages with ECDSA

I have following code to sign messages with ecdsa library. I am getting different result on each run.
import ecdsa
from hashlib import sha256
random_number_for_private_key = 31334737451456268050498185842994455999554006395290392504114029053954839148697
private_key_hex = hex(random_number_for_private_key)[2:]
private_key_bytes = bytes.fromhex(private_key_hex)
private_key_object=ecdsa.SigningKey.from_string(private_key_bytes, curve=ecdsa.SECP256k1, hashfunc=sha256)
public_key = private_key_object.get_verifying_key()
sig = private_key_object.sign(b"message")
print(sig.hex())
Results are:
91654d84e462a4f55429a9f8ea6458c6c11387859d6fa9c53e7376a131e49cd76ee8462c9e0ceb0ce7d1116609fe52d4c6c80d6fe84a0f72ffdde4223152a262
2b96a77ee8fe1058c97c32c2146999f7e0b0305d449de81a3ee9ce0c7d909c65d42f2d7eabfd02b214ca591a19760f69e47ca7b7331547cda2d5d759d09e8106
fb41a7b8fd59b60035f4f4d66ee7aac41a62376b78885d8df3bcce95b3a4de1161cdd5029a5cf1e9dae67aaa792e1d0b79e32663d7c3bfcb82892443c7abde91
when I verify with following code, it returns true for all results
import ecdsa
from hashlib import sha256
message = b"message"
public_key = '46454399998223bdb3771f08341844c485cd6b0e35383635cbc56940a755e5b6986ef0dbd1381267575bf290843540d3061f089fbab1b8f60cfe3d3d0d6aef52'
sig = '91654d84e462a4f55429a9f8ea6458c6c11387859d6fa9c53e7376a131e49cd76ee8462c9e0ceb0ce7d1116609fe52d4c6c80d6fe84a0f72ffdde4223152a262'
vk = ecdsa.VerifyingKey.from_string(bytes.fromhex(public_key), curve=ecdsa.SECP256k1, hashfunc=sha256)
vk.verify(bytes.fromhex(sig), message)
So, is it expected to give different signing results?
P.S: Private and public keys are real but not used in any production env.

Porting python PKCS1_v1_5 encryption code to java but java code not work

I have a backend,which receives codes and returns true or false.
I send it codes using my python encryption,it returns true(the result varible):
from Cryptodome.Cipher import PKCS1_v1_5
from Cryptodome.PublicKey import RSA
import base64
prsa = RSA.importKey('''-----BEGIN RSA PUBLIC KEY-----
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
-----END RSA PUBLIC KEY-----''')
pcipher = PKCS1_v1_5.new(prsa)
result=base64.b64encode(pcipher.encrypt(bytes))
But my java encryption always return false:
public static String encrypt(byte[] bytes, String publicKeyFilePath)
throws Exception {
byte[] keyBytes = Files.readAllBytes(Paths.get(publicKeyFilePath));
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
Key key = keyFactory.generatePublic(keySpec);
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1PADDING");
cipher.init(1, key);
byte[] result = cipher.doFinal(bytes);
return java.util.Base64.getEncoder().encodeToString(result);
}
Both java and python codes can be well decrypted by my java decryption codes(I have private key).
I have tryed different kinds of cipher,such as:
Cipher cipher = Cipher.getInstance("RSA/None/PKCS1Padding");
And trying to set provider:
Cipher cipher = Cipher.getInstance("RSA/None/PKCS1Padding",new org.bouncycastle.jce.provider.BouncyCastleProvider());
But all return false.I am confused about the "PKCS1_v1_5",for don't know which kind of padding it is,and what is the right code porting to java?

Python rsa module troubles

I need to encrypt some data, so I decided to use rsa module. I need to generate public and private keys. I want to send my public keys to some clients. How can I do this?
import rsa
(public_key, private_key) = rsa.newkeys(512)
So I've already generated it, but public_key now is a structure with two fields e and n. how can I transform it into bytes? And back from bytes to such structure?
You can use PyCrypto module
from Crypto.PublicKey import RSA
key = RSA.generate(512)
private_key = key.exportKey(passphrase='', pkcs=8)
public_key = key.publickey().exportKey()
In your case, try using save_pkcs1 method for saving into PEM format.
UPD:
Code sample for encrypt using rsa:
message = b'message'
# Alternative way - message = 'message'.encode('utf-8')
encrypted = rsa.encrypt(message, public_key)
For decrypt:
rsa.decrypt(encrypted, private_key).decode('utf-8')

Decode text encoded with RSA

I have a RSA public/private key pair and passphrase. I am trying to decode text encrypted using using above key(s). The encoded text is always 512 chars long alpha-num string.
I have tried using the code provided at SOF question Decrypt using an RSA public key with PyCrypto
First I used my private key which was encoded with AES-256-CBC from a PEM file.
This is start of privkey.pem which made me think its AES-256 encrypted
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-256-CBC
<rest of the data>
-----END RSA PRIVATE KEY-----
but I received following error message.
ValueError: PEM encryption format not supported.
So I asked the source for a private key without AES encryption which they gave me. Now using this key the decrypted works and the decrypted text looks like below (I am only showing some of the text)
b'\x93\n(\x92\x02\x9aF*?\x18"\x19\x12Gn\xc2\<rest of the text>'
This is not my plain text. What am I doing wrong? can someone help me to decode this text.
EDIT 1:
Based on Maarten's answer below, I have tried the following code but I am still getting errors.
Here is my code for decryption
from Crypto.Cipher import PKCS1_OAEP
from Crypto.PublicKey import RSA
import ast
encrypted_text = "39085fc25e<HIDDEN>2fcce845760391ff"
key = RSA.importKey(open("\\path_to_key\\private.der", encoding="utf8").read())
cipher = PKCS1_OAEP.new(key)
message = cipher.decrypt(ast.literal_eval(str(uid)))
and I get error:
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x82 in position 1: invalid start byte
Note that I had to convert my private key from PEM to DER using the code below becasue using PEM file I was getting SyntaxError: unexpected EOF while parsing
openssl rsa -in private_key.pem -out private_key.der -outform DER
becasue
Here is the solution that I have found.
First of all I am using pycryptodome librray instead of pycrypto.
Below are my encode and decode functions.
from Crypto.Cipher import PKCS1_OAEP
from Crypto.PublicKey import RSA
def encode_rsa(message, key_path):
key = RSA.importKey(open(key_path).read())
cipher = PKCS1_OAEP.new(key)
ciphertext = cipher.encrypt(message)
return ciphertext
def decode_rsa(ciphertext, key_path):
key = RSA.importKey(open(key_path).read())
cipher = PKCS1_OAEP.new(key)
# before decrypt convert the hex string to byte_array
message = cipher.decrypt(bytearray.fromhex(ciphertext))
return message
Using above two functions I was able to encode/deode the data correctly.

Parse RSA key pair from string in Python

I'm trying to generate/read a RSA-keypair from the publicKey and the privateKey as a String.
Something like this:
priK = "-----BEGIN RSA PRIVATE KEY-----MIIBOQIBAAJAVJhUS0gLqXLOmVv2xG23oFPwim9+rVxGhLUXqKShQCvB3iRMOHn7/GNJumpwmnglcsNXuqAhN0OxqKGGJdtYdwIDAQABAkBP0VrXnSbDvvuIX+k59Xvo3sp7FDAmSoaO+H9WM9+ht5H/f/geIrSEXSIkFLnzniMwtOJ422GmkDkL1F67HuDhAiEAlNauDiq3RqoXufbauyPEOG9fMS2pvB+auT2XCHJhhKsCIQCRgIo7WIRZYnNpNRWaoppUQK3g+aM8sdeBYpbs2nwDZQIgZXIxrmxFAUAb7d+oVFdbfc/DRSTHhPbRoaKuF87GUwMCIFmzaATsLjO42TPMETSS+BfnBAtFe5hIf3Z5pFgC3h9tAiEAgYjug92fmVvE+CcRSg6at7meSEbK/Kxg7Ar4mlkXMlI=-----END RSA PRIVATE KEY-----"
pubK = "-----BEGIN PUBLIC KEY-----MFswDQYJKoZIhvcNAQEBBQADSgAwRwJAVJhUS0gLqXLOmVv2xG23oFPwim9+rVxGhLUXqKShQCvB3iRMOHn7/GNJumpwmnglcsNXuqAhN0OxqKGGJdtYdwIDAQAB-----END PUBLIC KEY-----"
keyPair = RSA.importKey(priK + pubK)
My error that I'm getting is:
in importKey
if lines[1].startswith(b('Proc-Type:4,ENCRYPTED')):
I don't even know if it's possible like that. I didn't really find information about that.
RSA.importKey(key) imports one key. It cannot import concatenated keys.
If you import a private key, then you can extract a public key from that, because common PKCS#1 and PKCS#8 format have all the necessary information to create public key. So, you don't even need to concatenate the public key to it.
Use:
privateKey = RSA.importKey(priK)
publicKey = privateKey.publickey()

Categories