Secure PHP - Credit Card processing system
Moderator: General Moderators
Re: Secure PHP - Credit Card processing system
If you don't preauth the credit card when the user enters it how are you going to know they entered it correctly and that it's a valid card? You don't have to take the payment immediately, you just need to authenticate the transaction so you know it'll work when you authorise it. Most payment gateways have that option.
Re: Secure PHP - Credit Card processing system
Thanks so much for your detailed response. I feel like I am a little out of my league on this project as I dont know too much about these issues.
Just something you mentioned below was bothering me...
I was just interested to know why its not better to do what I had mentioned?
Thanks again
Just something you mentioned below was bothering me...
My original plan, which I thought was pretty safe, was never to store the full CC number. Rather store half in DB and email half to admin - all encrypted of course - and then when admin logs in he will decrypt everything and put both parts together. It sounds like you saying it makes no difference to do this and its better to just encrypt (the way you explained) and store all 16 digits in DB.Hannes2k wrote: My solution would be:
Use an one-way encryption, e.g. RSA. Create an RSA key pair, store the public key in your php file and encrypt the whole credit card number (all informations in one single block!) with RSA.
I was just interested to know why its not better to do what I had mentioned?
Thanks again
Re: Secure PHP - Credit Card processing system
Hi,
So this decryption should happen on the pc of your admin.
But using your schema seems to be okay (on first look), but please split the CC in two halfs and make sure you get realy good random numbers (by using /dev/random or /dev/urandom).
And for sending an encrypted mail to your admin it would be best using GnuPG (or some thing like that), but this uses also an asymmetric algorithm.
So you do not realy get a security advantage. If the pc of your admin is compromised, he just needs to get the private key of GnuPG and the password for the admin control panel of the web app.
For my suggestion the attacker, if he has comprimised the admins pc, needs the password for the private key (for decrypting the CCs) and the program itself.
But: It depends on what your admin needs. If he just do a manual card checking once, both solutions would be sufficient (at fist view).
But if he wanna store the CCs for a longer time...
And as a final advice:
The biggest enemy of security is complexity! Don't try to build to complex systems, because it's hard to make sure that they are secure. Use easy systems/schemes, because it's easier to finger out all possible attacks.
If this happens on the server (admin sends his encrypted Part2 to the server), it would be a bad idea. Is the server or the PC of your admin compromised, the attacker can get the full CC.and then when admin logs in he will decrypt everything and put both parts together.
So this decryption should happen on the pc of your admin.
But using your schema seems to be okay (on first look), but please split the CC in two halfs and make sure you get realy good random numbers (by using /dev/random or /dev/urandom).
And for sending an encrypted mail to your admin it would be best using GnuPG (or some thing like that), but this uses also an asymmetric algorithm.
So you do not realy get a security advantage. If the pc of your admin is compromised, he just needs to get the private key of GnuPG and the password for the admin control panel of the web app.
For my suggestion the attacker, if he has comprimised the admins pc, needs the password for the private key (for decrypting the CCs) and the program itself.
But: It depends on what your admin needs. If he just do a manual card checking once, both solutions would be sufficient (at fist view).
But if he wanna store the CCs for a longer time...
And as a final advice:
The biggest enemy of security is complexity! Don't try to build to complex systems, because it's hard to make sure that they are secure. Use easy systems/schemes, because it's easier to finger out all possible attacks.
Re: Secure PHP - Credit Card processing system
Hi Hannes, It's good to hear someone else come up with the solution I used for phpcreditcard. Untill then I had done a lot of reading but nobody had recommended doing it this way.And for sending an encrypted mail to your admin it would be best using GnuPG (or some thing like that), but this uses also an asymmetric algorithm.
So you do not realy get a security advantage. If the pc of your admin is compromised, he just needs to get the private key of GnuPG and the password for the admin control panel of the web app.
For my suggestion the attacker, if he has comprimised the admins pc, needs the password for the private key (for decrypting the CCs) and the program itself.
Re: Secure PHP - Credit Card processing system
Hi Hannes,Hannes2k wrote:Hi,
And as a final advice:
The biggest enemy of security is complexity! Don't try to build to complex systems, because it's hard to make sure that they are secure. Use easy systems/schemes, because it's easier to finger out all possible attacks.
Yes I think you are making a very good point here about complexity.
I think I am getting closer to a solution. The admin doesnt need to do any long term CC storing. They will login, get CC details, process transaction and delete. I also want to avoid at all costs storing a full CC in a database even if its encrypted.
So basically based on what you mentioned and my major issues how does the following sound:
- On website split CC number into two parts - encrypt both parts using a RSA public key (private key on admin local machine). Save one half on DB and send encrypted email to admin with other half. (also with an id which references record in db)
- Admin machine has some kind of local application (maybe even a windows program) which stores the private key (password protected ofcourse).
- Admin will then run this application and will provide the application with the contents of the email (simple copy and paste), likewise he will login to the website page and can retrieve the other half of the encrypted CC and also copy and paste into this application
- Application will combine and decrypt and display all cc details
- Admin will process cc and then on website admin page he will press delete button, deleting all stored data in db (for this CC)
This keeps the private key safe as you recommended. Never stores a full CC anywhere. And doesnt require dealing with the other security issues of having the application talk directly to the database.
What do you think?
Re: Secure PHP - Credit Card processing system
Hi,
storing the full CC (encrypted) in database until the admin receives the new CCs (and delete them from database) won't be a problem, as long as the private key is just know by the admin.
But: It's realy important to use a padding schema. Otherwise, without padding, cracking CCs would be easy (especial if you split them).
You have to consider that the public key is know by everyone. So if you just perform: {creditcardnumber}^e mod n, an attacker can just try all possible creditcardnumbers and check whether the CC is in your database or not.
With a good padding schema (a simple one is random padding, with a good random source), this won't be possible, because the ciphertext of a CC is always another one so the attacker cannot compare if he guess a valid CC.
You should also consider the handling of the whole system. Users like simple systems and don't wanna enter a password x times (or using x applications for one task). And you cannot make sure that a user handle it the right way, maybe your admin do not delete the CCs from database or from his email box.
This is also an aspect you have to consider.
storing the full CC (encrypted) in database until the admin receives the new CCs (and delete them from database) won't be a problem, as long as the private key is just know by the admin.
But: It's realy important to use a padding schema. Otherwise, without padding, cracking CCs would be easy (especial if you split them).
You have to consider that the public key is know by everyone. So if you just perform: {creditcardnumber}^e mod n, an attacker can just try all possible creditcardnumbers and check whether the CC is in your database or not.
With a good padding schema (a simple one is random padding, with a good random source), this won't be possible, because the ciphertext of a CC is always another one so the attacker cannot compare if he guess a valid CC.
You should also consider the handling of the whole system. Users like simple systems and don't wanna enter a password x times (or using x applications for one task). And you cannot make sure that a user handle it the right way, maybe your admin do not delete the CCs from database or from his email box.
This is also an aspect you have to consider.
Re: Secure PHP - Credit Card processing system
makes sense. thanks so much for all the help.Hannes2k wrote: But: It's realy important to use a padding schema. Otherwise, without padding, cracking CCs would be easy (especial if you split them).
You have to consider that the public key is know by everyone. So if you just perform: {creditcardnumber}^e mod n, an attacker can just try all possible creditcardnumbers and check whether the CC is in your database or not.
With a good padding schema (a simple one is random padding, with a good random source), this won't be possible, because the ciphertext of a CC is always another one so the attacker cannot compare if he guess a valid CC.
Re: Secure PHP - Credit Card processing system
I am working on this project as discussed and have run into a problem and was hoping you or someone could help.
I have written a simple .net application to generate a public and private key.
The problem is that I need php to be doing the encrypting on the webserver.
So firstly I am having problems finding a good RSA library for php. Any ideas?
Secondly, .net stores their public key in an xml format string and I dont know how it translates into a standard public key (I am missing something simple here). For example the .net public key looks as follows:
Public Key: <RSAKeyValue><Modulus>4QiPe0pZWkRVzmfGkK5o68iIM7pTgeQaUB+sv4fTPS252iakxccrGdtwLTuAqwO5qkwxOpzINGfehVRNJV+HVdK747N3U6UolkgXoKVPq5so5AuBvs7LN0BKVbk7fd/SXDTZ4atOlys+WYtOIqDU+UjgEeDZdFx8BE5odpQPbT8=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>
Please help?
Thanks
I have written a simple .net application to generate a public and private key.
The problem is that I need php to be doing the encrypting on the webserver.
So firstly I am having problems finding a good RSA library for php. Any ideas?
Secondly, .net stores their public key in an xml format string and I dont know how it translates into a standard public key (I am missing something simple here). For example the .net public key looks as follows:
Public Key: <RSAKeyValue><Modulus>4QiPe0pZWkRVzmfGkK5o68iIM7pTgeQaUB+sv4fTPS252iakxccrGdtwLTuAqwO5qkwxOpzINGfehVRNJV+HVdK747N3U6UolkgXoKVPq5so5AuBvs7LN0BKVbk7fd/SXDTZ4atOlys+WYtOIqDU+UjgEeDZdFx8BE5odpQPbT8=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>
Please help?
Thanks
Re: Secure PHP - Credit Card processing system
Hi,
you can use the pear package Crypt RSA, but mainly you have just to call bcpowmod for encryption.
In .Net the key is base64 encoded, but try to get the public key in hexadecimal representation (you can get the bytes of the modulus by calling rsa.ExportParameters().Modulus, then convert this to a hecadecimal string).
you can use the pear package Crypt RSA, but mainly you have just to call bcpowmod for encryption.
In .Net the key is base64 encoded, but try to get the public key in hexadecimal representation (you can get the bytes of the modulus by calling rsa.ExportParameters().Modulus, then convert this to a hecadecimal string).
Re: Secure PHP - Credit Card processing system
Ok so managed to convert the modulus to hex - thanks.
I am trying to use the following php code to do the encryption:
So I understand I now have modulus, but I still need the public key dont I (e) - how do I get that out of .NET.
Also surely this code requires an integer representation and hex wont do?
I will also need to generate a key pair only once and store it from within the application. What do you recommend is the best way to do that? (store the private key) ie whats the most secure?
thanks for all your help. As youi can see I really dont know much about this.
I am trying to use the following php code to do the encryption:
Code: Select all
/*
* ENCRYPT function returns
* X = M^E (mod N)
*/
public function encrypt ($m, $e, $n, $s=3) {
$coded = '';
$max = strlen($m);
$packets = ceil($max/$s);
for($i=0; $i<$packets; $i++){
$packet = substr($m, $i*$s, $s);
$code = '0';
for($j=0; $j<$s; $j++){
$code = bcadd($code, bcmul(ord($packet[$j]), bcpow('256',$j)));
}
$code = bcpowmod($code, $e, $n);
$coded .= $code.' ';
}
return trim($coded);
}Also surely this code requires an integer representation and hex wont do?
I will also need to generate a key pair only once and store it from within the application. What do you recommend is the best way to do that? (store the private key) ie whats the most secure?
thanks for all your help. As youi can see I really dont know much about this.
Re: Secure PHP - Credit Card processing system
Hi,
if you have the modulus, you can encrypt a plaintext $x by:
$c = bcpowmod($x, "65537", $n);
But $n have to be a decimal number (thought hex would also be fine).
But converting hex to dec is easy (I hope so):
$n_dec = base_convert($n_hex, 10, 16);
$x must also be a decimal number (a string with just 0-9). So if you wanna encrypt a CC, you can use:
In .Net the default value of 'e' is 2^16+1=65537 (or: rsa.ExportParameters().e or rsa.ExportParameters().Exponent).
In .Net just decrypt the value and read the last 12 integers.
if you have the modulus, you can encrypt a plaintext $x by:
$c = bcpowmod($x, "65537", $n);
But $n have to be a decimal number (thought hex would also be fine).
But converting hex to dec is easy (I hope so):
$n_dec = base_convert($n_hex, 10, 16);
$x must also be a decimal number (a string with just 0-9). So if you wanna encrypt a CC, you can use:
Code: Select all
<?php
//Untested
$n_dec = "...";
$e = "65537";
$cc = "123456789012"; //Exactly 12 numbers
$fill_up_cc = str_pad($cc, 12, "0", STR_PAD_LEFT); //Pad it with 0's if length of CC < 12
//Speed this up, it would be slow
$random_padding = $fill_up_cc;
while(strlen($random_padding) < (strlen($n_dec)-1)) {
$random_padding = good_random_function(0,9).$random_padding;
}
$c = bcpowmod($random_padding, $e, $n_dec);
echo "Ciphertext: $c";
?>In .Net the default value of 'e' is 2^16+1=65537 (or: rsa.ExportParameters().e or rsa.ExportParameters().Exponent).
In .Net just decrypt the value and read the last 12 integers.
Re: Secure PHP - Credit Card processing system
So have been trying it out but something is going wrong in the php.
Just as an example I think the hex-dec conversions are messing things up. For example, in the following code I take my modulus, convert to dec and then back to hex and its all messed up as you can see.
produces
HEX:AD65DE25B8C0F4CC116A03348FAF939C9EB33A89A2DAF654D564A2674FF440072E1753A29BCED7C0DD81E5F13DF35096BAC9CF588EE996EAA1AD22E5AE4FD652993E8135463655ED41BDD7F80D643F205AA0A35B8DE61B75F4AFE7EEED0D50226B19892F0E5F4369606CF67D861DA380A81496CF122D3E4669957637FFC8A4A5
N DEC:2420662424280642486440866040406848822064266040086668862666646884
N2 HEX:5e261c5d44786c000000000000000000000000000000000000000
Any idea whats going on. The encryption and decryption is not looking anything like the .NET results and I am sure this is the problem
Thanks
Just as an example I think the hex-dec conversions are messing things up. For example, in the following code I take my modulus, convert to dec and then back to hex and its all messed up as you can see.
Code: Select all
$n_hex = "AD65DE25B8C0F4CC116A03348FAF939C9EB33A89A2DAF654D564A2674FF440072E1753A29BCED7C0DD81E5F13DF35096BAC9CF588EE996EAA1AD22E5AE4FD652993E8135463655ED41BDD7F80D643F205AA0A35B8DE61B75F4AFE7EEED0D50226B19892F0E5F4369606CF67D861DA380A81496CF122D3E4669957637FFC8A4A5";
$n_dec = base_convert($n_hex, 16, 10);
$n2_hex = base_convert($n_dec, 10, 16);
echo "<br>N HEX:$n_hex<br>N DEC:$n_dec<Br>N2 HEX:$n2_hex";HEX:AD65DE25B8C0F4CC116A03348FAF939C9EB33A89A2DAF654D564A2674FF440072E1753A29BCED7C0DD81E5F13DF35096BAC9CF588EE996EAA1AD22E5AE4FD652993E8135463655ED41BDD7F80D643F205AA0A35B8DE61B75F4AFE7EEED0D50226B19892F0E5F4369606CF67D861DA380A81496CF122D3E4669957637FFC8A4A5
N DEC:2420662424280642486440866040406848822064266040086668862666646884
N2 HEX:5e261c5d44786c000000000000000000000000000000000000000
Any idea whats going on. The encryption and decryption is not looking anything like the .NET results and I am sure this is the problem
Thanks
Re: Secure PHP - Credit Card processing system
Hi,
hmm okay try this function:
Or from the php manual (comments):
hmm okay try this function:
Code: Select all
<?php
function hex2dec ($numstring, $frombase="0123456789abcdef", $tobase="0123456789")
{
$numstring = strtolower($numstring);
$from_count = strlen($frombase);
$to_count = strlen($tobase);
$length = strlen($numstring);
$result = '';
for ($i = 0; $i < $length; $i++)
{
$number[$i] = strpos($frombase, $numstring{$i});
}
do // Loop until whole number is converted
{
$divide = 0;
$newlen = 0;
for ($i = 0; $i < $length; $i++) // Perform division manually (which is why this works with big numbers)
{
$divide = $divide * $from_count + $number[$i];
if ($divide >= $to_count)
{
$number[$newlen++] = (int)($divide / $to_count);
$divide = $divide % $to_count;
}
elseif ($newlen > 0)
{
$number[$newlen++] = 0;
}
}
$length = $newlen;
$result = $tobase{$divide} . $result; // Divide is basically $numstring % $to_count (i.e. the new character)
}
while ($newlen != 0);
return $result;
}
?>Or from the php manual (comments):
Code: Select all
rithiur at mbnet dot fi
Here is a simple function that works like the function provided by Mr. Fips (See below) with the exception that this can convert numbers of any size. However, note that as the division is performed manually to the number, this function is not very efficient and may not be suitable for converting strings with more than a few hundred numbers (depending on the number bases).
<?php
function custombase_convert_big ($numstring, $frombase, $tobase)
{
$from_count = strlen($frombase);
$to_count = strlen($tobase);
$length = strlen($numstring);
$result = '';
for ($i = 0; $i < $length; $i++)
{
$number[$i] = strpos($frombase, $numstring{$i});
}
do // Loop until whole number is converted
{
$divide = 0;
$newlen = 0;
for ($i = 0; $i < $length; $i++) // Perform division manually (which is why this works with big numbers)
{
$divide = $divide * $from_count + $number[$i];
if ($divide >= $to_count)
{
$number[$newlen++] = (int)($divide / $to_count);
$divide = $divide % $to_count;
}
elseif ($newlen > 0)
{
$number[$newlen++] = 0;
}
}
$length = $newlen;
$result = $tobase{$divide} . $result; // Divide is basically $numstring % $to_count (i.e. the new character)
}
while ($newlen != 0);
return $result;
}
$HEX = "0123456789ABCDEF";
$DEC = "0123456789";
print custombase_convert_big ("FFFFFF", $HEX, $DEC); // Prints "16777215"
$BIN = "01";
$ASCII = "";
for ($i = 0; $i < 256; $i++)
{
$ASCII .= chr($i);
}
$msg = "0100100101110100001000000101011101101111011100100110101101110011";
print custombase_convert_big($msg, $BIN, $ASCII); // Prints "It Works"
?>Re: Secure PHP - Credit Card processing system
Thanks the HEX converter worked great.
I took modulus and exponent out of the public key in .NET
The exponent was actually AQAB (41131)
I then ran the encryption just on the 12 letter cc number, before trying any padding.
Unfortunately though, the encrypted string being generated is not being accepted by .NET - its saying its invalid with the following exception "Index and length must refer to a location within the string. Parameter name: length"
So the length of the actual encrypted value is correct but something else is going on.
It must be that .NET is doing something we dont know about. What do you think?
The .NET encrypt/decrypt function I am using breaks down the string it is encrypting or decrypting into 58 byte blocks - but that shouldnt make a difference, right?
The other thing I noticed was that everytime I run the .NET encryption the encrypted string comes out different (even though they all work in decrypt) which also makes me think something else is going on. Or it could just be my lack of knowledge of RSA?
Just because I am about to give up and this is my last ditch effort - I am going to include the .NET encrypt decrypt function I am using in the hope you might see what the issue is. Thanks
Thanks again for your help!
I took modulus and exponent out of the public key in .NET
The exponent was actually AQAB (41131)
I then ran the encryption just on the 12 letter cc number, before trying any padding.
Unfortunately though, the encrypted string being generated is not being accepted by .NET - its saying its invalid with the following exception "Index and length must refer to a location within the string. Parameter name: length"
So the length of the actual encrypted value is correct but something else is going on.
It must be that .NET is doing something we dont know about. What do you think?
The .NET encrypt/decrypt function I am using breaks down the string it is encrypting or decrypting into 58 byte blocks - but that shouldnt make a difference, right?
The other thing I noticed was that everytime I run the .NET encryption the encrypted string comes out different (even though they all work in decrypt) which also makes me think something else is going on. Or it could just be my lack of knowledge of RSA?
Just because I am about to give up and this is my last ditch effort - I am going to include the .NET encrypt decrypt function I am using in the hope you might see what the issue is. Thanks
Code: Select all
Private Shared Function RSAEncrypt(ByVal plainText As Byte()) As Byte()
'Make sure that the public and private key exists
ValidateRSAKeys()
Dim publicKey As String = GetTextFromFile(KEY_PUBLIC)
Dim privateKey As String = GetTextFromFile(KEY_PRIVATE)
'Dim strPub As String
'The RSA algorithm works on individual blocks of unencoded bytes. In this case, the
'maximum is 58 bytes. Therefore, we are required to break up the text into blocks and
'encrypt each one individually. Each encrypted block will give us an output of 128 bytes.
'If we do not break up the blocks in this manner, we will throw a "key not valid for use
'in specified state" exception
'Get the size of the final block
Dim lastBlockLength As Integer = plainText.Length Mod RSA_BLOCKSIZE
Dim blockCount As Integer = Math.Floor(plainText.Length / RSA_BLOCKSIZE)
Dim hasLastBlock As Boolean = False
If Not lastBlockLength.Equals(0) Then
'We need to create a final block for the remaining characters
blockCount += 1
hasLastBlock = True
End If
'Initialize the result buffer
Dim result() As Byte = New Byte() {}
'Initialize the RSA Service Provider with the public key
Dim Provider As New RSACryptoServiceProvider(KeySize.RSA)
Provider.FromXmlString(publicKey)
'Break the text into blocks and work on each block individually
For blockIndex As Integer = 0 To blockCount - 1
Dim thisBlockLength As Integer
'If this is the last block and we have a remainder, then set the length accordingly
If blockCount.Equals(blockIndex + 1) AndAlso hasLastBlock Then
thisBlockLength = lastBlockLength
Else
thisBlockLength = RSA_BLOCKSIZE
End If
Dim startChar As Integer = blockIndex * RSA_BLOCKSIZE
'Define the block that we will be working on
Dim currentBlock(thisBlockLength - 1) As Byte
Array.Copy(plainText, startChar, currentBlock, 0, thisBlockLength)
'Encrypt the current block and append it to the result stream
Dim encryptedBlock() As Byte = Provider.Encrypt(currentBlock, False)
Dim originalResultLength As Integer = result.Length
Array.Resize(result, originalResultLength + encryptedBlock.Length)
encryptedBlock.CopyTo(result, originalResultLength)
Next
'Release any resources held by the RSA Service Provider
Provider.Clear()
Return result
End Function
Private Shared Function RSADecrypt(ByVal encText As String) As Byte()
'Make sure that the public and private key exists
ValidateRSAKeys()
Dim publicKey As String = GetTextFromFile(KEY_PUBLIC)
Dim privateKey As String = GetTextFromFile(KEY_PRIVATE)
'When we encrypt a string using RSA, it works on individual blocks of up to
'58 bytes. Each block generates an output of 128 encrypted bytes. Therefore, to
'decrypt the message, we need to break the encrypted stream into individual
'chunks of 128 bytes and decrypt them individually
'Determine how many bytes are in the encrypted stream. The input is in hex format,
'so we have to divide it by 2
Dim maxBytes As Integer = encText.Length / 2
'Ensure that the length of the encrypted stream is divisible by 128
If Not (maxBytes Mod RSA_DECRYPTBLOCKSIZE).Equals(0) Then
Throw New System.Security.Cryptography.CryptographicException("Encrypted text is an invalid length")
Return Nothing
End If
'Calculate the number of blocks we will have to work on
Dim blockCount As Integer = maxBytes / RSA_DECRYPTBLOCKSIZE
'Initialize the result buffer
Dim result() As Byte = New Byte() {}
'Initialize the RSA Service Provider
Dim Provider As New RSACryptoServiceProvider(KeySize.RSA)
Provider.FromXmlString(privateKey)
'Iterate through each block and decrypt it
For blockIndex As Integer = 0 To blockCount - 1
'Get the current block to work on
Dim currentBlockHex = encText.Substring(blockIndex * (RSA_DECRYPTBLOCKSIZE * 2), RSA_DECRYPTBLOCKSIZE * 2)
Dim currentBlockBytes As Byte() = HexToBytes(currentBlockHex)
'Decrypt the current block and append it to the result stream
Dim currentBlockDecrypted() As Byte = Provider.Decrypt(currentBlockBytes, False)
Dim originalResultLength As Integer = result.Length
Array.Resize(result, originalResultLength + currentBlockDecrypted.Length)
currentBlockDecrypted.CopyTo(result, originalResultLength)
Next
'Release all resources held by the RSA service provider
Provider.Clear()
Return result
End FunctionRe: Secure PHP - Credit Card processing system
Hi,
the RSA function of .Net is a bit strange, because you have to use a special padding schema. The RSA (RSAManaged) implementation of Mono is much easier to handle.
But, for decryption you need also just a 'pow mod' function. So you can use a BigInteger Class (e.g. from Mono or from Codeproject.com).
In PHP the decryption looks like:
$cc_with_padding = bcpowmod($cipher_text, $private_key, $public_key);
And in the same way you can use your BigInteger Class for decryption.
the RSA function of .Net is a bit strange, because you have to use a special padding schema. The RSA (RSAManaged) implementation of Mono is much easier to handle.
But, for decryption you need also just a 'pow mod' function. So you can use a BigInteger Class (e.g. from Mono or from Codeproject.com).
In PHP the decryption looks like:
$cc_with_padding = bcpowmod($cipher_text, $private_key, $public_key);
And in the same way you can use your BigInteger Class for decryption.