I need to send a password that's RSA encrypted with a public key (along with some other data). Here are the exact instructions from the documentation for the password:
Encode password in Base64 and ensure UTF-8 encoding
Encrypt password with RSA with provided public key, no block mode, and PKCS1Padding
Encode resulting encryption in Base64 with ensured UTF-8 encoding
Here's the code I'm using that to me seems correct:
function encryptPassword($pass) {
$pass = base64_encode($pass);
$fp = fopen("./cert.crt", "r");
$publicKey = fread($fp, 8192);
fclose($fp);
openssl_get_publickey($publicKey);
openssl_public_encrypt($pass, $cryptedText, $publicKey, OPENSSL_PKCS1_PADDING);
return base64_encode(utf8_encode($cryptedText));
}
I'm getting an error on the other side saying the password can't be decoded. Support from them is basically non-existent other than the error message, and them saying everything is correct on their side. My question is, am I sending what they're asking for according to the documentation?
Thanks in advance!
No, you've taken Base64 with ensured UTF-8 encoding too literally. utf8_encode transforms one textual encoding into another, but $cryptedText is not textual. It is a binary string, so you lose some characters during encoding. Simply remove it, because Base64 gives you already a textual representation of the binary data:
return base64_encode($cryptedText);
Additionally, you probably wanted to pass the public key resource into the encryption function:
$key_resource = openssl_get_publickey($publicKey);
openssl_public_encrypt($pass, $cryptedText, $key_resource, OPENSSL_PKCS1_PADDING);
Related
I'm trying to stringify output from openssl_public_encrypt and other openssl functions i php, and the output don't seem to be utf8 encoded. Here is a sample code that generate the error that is my problem in a nutshell.
<?php
$pubkey=<<<EOD
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAueWffJhr4j+PZhf4QlFF
1HEmcu9d93YYBIQdZBZLWx4uqxsZ6Q3FaBVMkHh0h+sDHx1je2fQprTEMjWGSIu0
HlXRZqPLkVUCpQg2j1oQk2BbZExS6kyziVa1G9ai094WqMz3MjyimOvJxuCAsb+i
rQ/HaC2+vBAdm8wjLYEkqe/q7Q6Tnf+U6bpPYASXTz0WlLJj/G2LLTpEYzF3IgTB
tRsTI6hwpmpHzpKUucEvliEesEPMAs3xp4AaKBdqKQoGFsiA2p1jxJIRUXC/ur7f
2ZgWI59AtemVd+FRZfUapfe5uDD3M5cJy/6Uh9Yg+7vMzuCzi/yBDDFwyy4hD2RJ
YwIDAQAB
-----END PUBLIC KEY-----
EOD;
$jsontest= new \stdClass();
$data="Testing some text ÆØåæøåéè";
openssl_public_encrypt($data,$encrypted,$pubkey,OPENSSL_PKCS1_OAEP_PADDING);
//Next line outputs encoding UTF8 sometimes but not consequently
echo "\n\ndata1: ".mb_detect_encoding($encrypted)."\n";
$jsontest->data1=$encrypted;
$data="Testing some other text ÆØåæøåéè";
openssl_public_encrypt($data,$encrypted,$pubkey,OPENSSL_PKCS1_OAEP_PADDING);
//Next line outputs encoding UTF8 sometimes but not consequently
echo "\n\ndata1: ".mb_detect_encoding($encrypted)."\n";
$jsontest->data2=$encrypted;
header('Content-Type: application/json; charset=UTF-8');
//print_r($jsontest);
$json=null;
try {
$json = json_encode($jsontest, JSON_THROW_ON_ERROR);
} catch (JsonException $e) {
echo 'Error:'.$e;
}
if($json)echo "JSON output:\n$json";
?>
Expected output would be a stringified json object with utf8 encoded property values. Instead i get this error message:
"Error:JsonException: Malformed UTF-8 characters, possibly incorrectly encoded in 'the php file':24"
When i run the above code snippet, the 'mb_detect_encoding' lines output 'UTF-8' sometimes, but not always.
There seems to be a problem in openssl_public_encrypt, where the output is not conform to utf-8 encoding.
A very strange behavior detected: Probably mb_detect_encoding does not detect correct, because the json_encode function fails every time. and probably openssl_public_encrypt is to blame for this behavior.
Anyways i can't stringify the supposedly UTF-8 encoded output from openssl_public_encrypt. I use base64 encoding of encrypted data for now as a solution, but the data overhead is around the double of original data.
I use openssl in php to encrypt/decrypt with rsa, ecdh and aes, in conjuction with javascript webCrypto.
Can anybody help me solve this problem, as i am probably not the only one who has this problem.
Edit:
Got it wrong! The function json_encode in php is the showstopper! It doesn't accept UTF-8 encoded json strings although json is specified for UTF-8 to my knowledge. It certainly is accepted by and retrieved ok in file_get_contents("php://input"). Is there any reason for that?
"Malformed UTF-8 characters" means the input data contains invalid characters.
If the data is hard coded, save your file with UTF-8 (no BOM) encode.
If not, use iconv to convert or check the input data.
Encrypted data is in binary format, you may need do base64 encode before run json encode
$jsontest->data1 = base64_encode($encrypted);
Kindly I am a developer with basics of encryption ,
I have a task which is encrypting data then save the encryption to database,
I am using openssl php function to encrypte and decrypte like below
function encrypte($stringToEncrypte){
$method="AES-128-CBC";
$iv=mcrypt_create_iv(16, MCRYPT_RAND);
$pass=md5('8123jhewe8dnjsdnq');
$encrypted=openssl_encrypt ($stringToEncrypte, $method, $pass, true , $iv);
return $encrypted."---".$iv;
}
function decrypte($stringToDecrypte){
/*
decrypte by remove --- then get iv then get encrypted then decrypte
*/
}
It's working fine but the encrypted text has random encoding and this will cause many errors in saving correctly into my database which saving in UTF-8 Encoding.
Definitely, I tried to convert the encrypted key to utf-8 by mb_convert_encoding() function but logically , the new encoded text will not be decrypted correctly , because the new encoded text will not be the same of the old encoded text .
For example, the encrypted text will have random encoding like ISO-8859-1
and my database encoding is utf-8 and encoding conversion will not generate text could be decrypted again.
i found something may by not very bad ,is to use URLencode PHP function , i tried it and it was working fine ,
but still i need experts answer
If your database is utf8, than all your content should be utf8. You need to convert your $stringToEncrypte to utf8 before you encrypt it. And make shure your $pass and $iv are utf8 as well. Then you can encrypt (also utf8), save in database and decrypt everything in utf8 as well.
I have the following code that creates an encryption in PHP:
$password = "helloworld";
$passwordupper = strtoupper($password);
$passwordencode = mb_convert_encoding($passwordupper, 'UTF-16LE');
$passwordsha1 = hash("SHA1", $passwordencode);
$passwordbase64 = base64_encode($passwordsha1);
The instructions I have from the system I'm trying to connect to states:
The encoding process for passwords is: first convert to uppercase, then Unicode it in little-endian UTF 16, then SHA1 it then base64 encode it.
I think I'm doing something wrong in my code. Any ideas?
Answer solved by Marc B above in comments:
sha1 hash can either be raw binary, or a base64-encoded string to
begin with. e.g. $raw = sha1($string, true) v.s. $encoded =
sha1($string). you'd better try both variants, because you may be
double-base64-encoding.
I'm working on a PHP login that takes an ID and logs them in elsewhere after the user is already authenticated. It works for every single ID except three of them, and they all have something in common: They all start with two zeros (e.g.: 0012).
I'm wondering if a double zero holds a special place in the encoding, like a delimiter? Or something to do with OpenSSL? It only breaks on those three. Doesn't matter if I treat the data as a string or an integer, it breaks both ways. Any ideas?
Code (modified slightly):
$fp = fopen("/OpenSSL-Win64/bin/myrsakey.pem", "r");
$priv_key = fread($fp, 8192) or die("File not found.");
fclose($fp);
$pkeyid = openssl_get_privatekey($priv_key);
$data = '0012'; // THIS DOESN'T WORK
$data = '0123'; // THIS DOES WORK
$data = '1234'; // THIS ALSO WORKS
$data = mb_convert_encoding($data, "UTF-16LE");
openssl_sign($data, $signature, $pkeyid, OPENSSL_ALGO_SHA1);
openssl_free_key($pkeyid);
Why would 00 in data break UTF-16 encode / OpenSSL?
The problem is not with OpenSSL. OpenSSL just works with data - it does not care about encodings. It might be related to openssl_sign. But its hard to tell at the moment.
Your problem is likely related to mb_convert_encoding. However, you never stated what the actual problem was.
How does it not work? Does it not work when verifying the signature on a Linux system? Did you check for the presence (or absence) of a Byte Order Mark (BOM)? That's a real problem, especially when working with Java.
I have following steps to perform for decryption
base64 decode the response
Decrypt the first 128 bytes with the RSA1024 public key. Key is in base64 encoded X509 format with PKCS1 padding.
My code looks like this:
$decodedString = $this->base64UrlDecode($string); //does proper url decoding
$publicKey = file_get_contents("public.key",true);
$pub_key = openssl_get_publickey($publicKey);
openssl_public_decrypt($decodedString,$decrypted,$pub_key,OPENSSL_PKCS1_PADDING);
var_dump($decrypted);
I am not able to get anything in $decrypted variable. If I try to base64 decode public key before using it, I am getting error of not a valid public key. What I am missing or doing wrong to achieve mentioned 2 steps?
See this comment for openssl_pkey_get_public:
http://www.php.net/manual/en/function.openssl-pkey-get-public.php#101513
PKCS1 padding poses a problem to that function, it seems.
It was actually a problem with how I was getting response. By doing urldecode before base64 decoding I am able to get proper results.
$decodedString = $this->base64UrlDecode(urldecode($string));