Jump to content

RSA decrypt error


joymis

Recommended Posts

Hello,

 

I have a RSA encrypt / decrypt function from google, and I try it for file upload

 

this is my code

<?php
	const PRIVATE_KEY = 'private_2048.key';
	const PUBLIC_KEY = 'public_2048.crt';

	$file = fopen('test.jpg', "r");
	$fp = fopen('enc.jpg', 'w');
	
	while(! feof($file)){
		$x = public_encrypt(fgets($file));
		var_dump($x);
		
		fwrite($fp, $x);
	}
        /**  it's display this
             string(344) "CZtRordK+BC/fUJX1P2FD8Yt0217bquw.......
             string(344) "I9m8ZLRz1FACXVmWWlmzISS..........
             string(0) ""
             string(344) "dp5vPnpZhEpz6K4Cmh........
             string(0) ""
             string(344) "mT60XZEph87lOz.......
             string(0) ""
             string(0) ""
             string(0) ""
	*/
        fclose($file);
	fclose($fp);
	
	
	$file = fopen('enc.jpg', "r");
	$fp = fopen('dec.jpg', 'w');
	
	while(! feof($file)){
		$z = fgets($file);
		var_dump($z);
		
		fwrite($fp, private_decrypt($z));
	}
	/** it's display this
            string(1376) "CZtRordK+BC/fUJX1P2FD8Yt02..........
        */
	fclose($fp);
	fclose($file);

function public_encrypt($plaintext)
{
    $fp = fopen(PUBLIC_KEY, "r");
    $pub_key = fread($fp, 8192);
    fclose($fp);
    
    $pub_key_res = openssl_get_publickey($pub_key);
    if(!$pub_key_res) {
        throw new Exception('Public Key invalid');
    }
    openssl_public_encrypt($plaintext,$crypttext, $pub_key_res);
    openssl_free_key($pub_key_res);
	
    return(base64_encode($crypttext));
}

function private_decrypt($encryptedext)
{
    $fp = fopen(PRIVATE_KEY, "r");
    $priv_key = fread($fp, 8192);
    fclose($fp);
	
    $private_key_res = openssl_get_privatekey($priv_key);
    if(!$private_key_res) {
        throw new Exception('Private Key invalid');
    }
    openssl_private_decrypt(base64_decode($encryptedext), $decrypted, $private_key_res);
    openssl_free_key($private_key_res);
	
    return $decrypted;
}
?> 

in my code, I var_dump $x and then if I decrypt and var_dump, it's work.

but when I read encrypt file and var_dump $z, it's not the same $x.

how can I do let $z = $x?

 

Thanks.

Edited by joymis
Link to comment
Share on other sites

Why is it necessary for $z to be the same as $x? In one case you are using fgets to read until it finds a newline character, then you encrypt that line, and print the data, and add it to the output file. In the other case you are reading an entire line of that encrypted data. One of those has decrypted newline characters, and one of them doesn't. That's the difference. Why do you think they need to be the same? And, why not just read the entire file at once and encrypt the whole thing? Why use fgets? That's for string data, not binary data.

Link to comment
Share on other sites

Hello justsomeguy,

 

I had think read the entire file at once and encrypt, but I don't know why not work, this is my entire file at once code

$file = fopen('test.png', "rb");
$fp = fopen('enc.png', 'w');

$x = fread($file, filesize('test.png'));
fwrite($fp, public_encrypt($x)); // I got 0 byte file
// fwrite($fp, $x); ==> it's work

fclose($file);
fclose($fp);

And in my original case, I tried more method like this, but after decrypted the file size not equal original file size.

$file = fopen('test.png', "r");
$fp = fopen('enc.png', 'w');
    
while(! feof($file)){
    $x = public_encrypt(fgets($file));
    fwrite($fp, $x."\n");
}
fclose($file);
fclose($fp);
    
    
$file = fopen('enc.png', 'r');
$fp = fopen('dec.png', 'w');
    
while(! feof($file)){
    $z[] = fgets($file);
}
array_pop($z);
foreach($z as $v)
{
    $aaa = explode("\n", $v);
    $z = private_decrypt($aaa[0]);
    fwrite($fp, $z);
}
fclose($fp);
fclose($file);

In addition to RSA encryption, are there more better encryption tools or method can let me reference?

 

Thanks.

Link to comment
Share on other sites

Instead of using fopen, fread, fgets, fwrite, fclose, etc, you can use file_get_contents and file_put_contents.

 

$x = public_encrypt(file_get_contents('test.png'));
file_put_contents('enc.png', $x);
That's all you need to do.

 

And in my original case, I tried more method like this, but after decrypted the file size not equal original file size.

Yeah, I'm not sure what you're doing there. You add an extra line break character to the end of the encrypted data when you write it to the file, and then for some reason when you read the encrypted file you get each line in an array, remove the last line break, and then try to individually decrypt each line. Why are you doing that? The data should all be encrypted and decrypted at once, not in segments. Line breaks do not mean anything in encrypted data, they are just another sequence of bits. Again, this is not text data you are dealing with, it is binary data. Don't look for particular sequences of bits in the encrypted data and treat them like characters like line breaks. It is just a continuous sequence of bits and you should treat the entire thing as one piece of data, not break it up into smaller pieces and then try to decrypt each one. That's why you're getting different sizes, because you are decrypting something totally different than what the data is.
Link to comment
Share on other sites

Yeah, I'm not sure what you're doing there. You add an extra line break character to the end of the encrypted data when you write it to the file, and then for some reason when you read the encrypted file you get each line in an array, remove the last line break, and then try to individually decrypt each line. Why are you doing that? The data should all be encrypted and decrypted at once, not in segments. Line breaks do not mean anything in encrypted data, they are just another sequence of bits. Again, this is not text data you are dealing with, it is binary data. Don't look for particular sequences of bits in the encrypted data and treat them like characters like line breaks. It is just a continuous sequence of bits and you should treat the entire thing as one piece of data, not break it up into smaller pieces and then try to decrypt each one. That's why you're getting different sizes, because you are decrypting something totally different than what the data is.

ok, thank you very much for your explanation, now I fully understand.

 

 

$x = public_encrypt(file_get_contents('test.png'));

file_put_contents('enc.png', $x);

I tried file_get_contents() after the encrypt file still 0 byte, might it openssl_private_encrypt() has special rule?

 

I looks php.net website, it said..

 

openssl_private_encrypt() has a low limit for the length of the data it can encrypt due to the nature of the algorithm.

 

To encrypt the larger data you can use openssl_encrypt() with a random password (like sha1(microtime(true))), and encrypt the password with openssl_public_encrypt().

 

But my test file only had 24KB, is it a large data?

Link to comment
Share on other sites

According to the comments in the manual for that function, the maximum length depends on the key size but looks like it is less than 300 bytes. The comment has functions which demonstrate breaking it up into pieces. Otherwise, openssl_encrypt will encrypt data of arbitrary size.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...