Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RSA Encrypt in PHP to decrypt in .NET

Tags:

.net

php

rsa

pear

In PHP I am RSA encrypting a message to be decrypted by .NET application... but I keep getting a "Bad Key" exception from .NET....

For RSA encryption, I am using PEAR class Crypt_RSA-> encrypting with the public key (which is a modulus, exponent pair) I get from working encryption system in .NET...

I guess the easiest question would be-> does "Bad Key" mean it is not able to decrypt the message whatsoever? IE, it is not encrypted correctly?

The harder question is-> Is there anything specific about RSA encryption that causes quirks between .NET and PHP?

like image 681
user312904 Avatar asked Apr 09 '10 15:04

user312904


People also ask

How do I decrypt RSA encrypted text?

As RSA is asymmetric encryption technique, if text is encrypted using public key then for decryption we should use the private key and vice versa. Select the Decryption Algorithm. Some Algorithms need to have key size greater than 512 bits. This should be the same algorithm you had used during encryption.

How do you use encrypt and decrypt in PHP?

In PHP, Encryption and Decryption of a string is possible using one of the Cryptography Extensions called OpenSSL function for encrypt and decrypt. openssl_encrypt() Function: The openssl_encrypt() function is used to encrypt the data. Parameters: $data: It holds the string or data which need to be encrypted.


2 Answers

Security Warning: Use OAEP, not PKCS#1.

If you want to use a solution that doesn't require the openssl extension, try phpseclib's Crypt_RSA. Examples follow:

Decryption with PKCS#1 padding:

openssl rsautl -inkey privatekey.txt -encrypt -in plaintext.txt -out ciphertext.txt

<?php
include('Crypt/RSA.php');

$rsa = new Crypt_RSA();
$rsa->loadKey(file_get_contents('privatekey.txt'));
$rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1);
echo $rsa->decrypt(file_get_contents('ciphertext.txt'));
?>

Encryption with PKCS#1 padding:

<?php
include('Crypt/RSA.php');

$rsa = new Crypt_RSA();
$rsa->loadKey(file_get_contents('privatekey.txt'));
$rsa->loadKey($rsa->getPublicKey());
$rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1);
echo $rsa->encrypt('1234567890');
?>

openssl rsautl -inkey privatekey.txt -decrypt -in ciphertext.txt -out plaintext.txt

Decryption with OAEP padding:

openssl rsautl -inkey privatekey.txt -encrypt -oaep -in plaintext.txt -out ciphertext.txt

<?php
include('Crypt/RSA.php');

$rsa = new Crypt_RSA();
$rsa->loadKey(file_get_contents('privatekey.txt'));
echo $rsa->decrypt(file_get_contents('ciphertext.txt'));
?>

Encryption with OAEP padding:

<?php
include('Crypt/RSA.php');

$rsa = new Crypt_RSA();
$rsa->loadKey(file_get_contents('privatekey.txt'));
$rsa->loadKey($rsa->getPublicKey());
echo $rsa->encrypt('1234567890');
?>

openssl rsautl -inkey privatekey.txt -decrypt -oaep -in ciphertext.txt -out plaintext.txt

phpseclib can be downloaded from http://phpseclib.sourceforge.net/

Good luck!

like image 99
user260294 Avatar answered Sep 28 '22 10:09

user260294


The Crypt_RSA on PEAR is not using PKCS#1 encoding. I suspect that is why .NET is giving you an error message.

As an example of it breaking, I created a php script using Crypt_RSA to encrypt the string "1234567" (I'll skip showing key loading):

print $rsa_obj->encryptBinary("1234567", $key_pair->getPublicKey());

Taking the output of that and piping it through the openssl command line tool gives the following error:

$ ./crypt | openssl rsautl -inkey privkey.pem -decrypt
RSA operation error
18437:error:04065084:rsa routines:RSA_EAY_PRIVATE_DECRYPT:data too large for modulus:fips_rsa_eay.c:558:

openssl expects PKCS#1 padding by default, but adding the -raw (no padding) flag to openssl doesn't help either.

Using the openssl extension in php gives the proper padding (defaults to PKCS#1, others available):

$pem = file_get_contents("pubkey.pem");
$key = openssl_pkey_get_public($pem);

$encrypted = "";
if(openssl_public_encrypt("1234567", $encrypted, $key)) {
  print $encrypted;
} else {
  print "failed\n";
}

And the decrypt code in php:

$pem = file_get_contents("privkey.pem");
$key = openssl_pkey_get_private($pem);

$enc_data = file_get_contents("openssl.crypted");
$decrypted = "";
if(openssl_private_decrypt($enc_data, $decrypted, $key)) {
  print "$decrypted\n";
} else {
  print "failed\n";
}

Certificates in the context of RSA are X.509 certificates, which are the RSA keys plus data about those keys. X.509 certificates are used in SSL, but are not required to use RSA.

like image 44
ddrown Avatar answered Sep 28 '22 10:09

ddrown