Jump to content

How can I (RSA) encrypt data in PHP so that .NET can decrypt them?


Recommended Posts

I'm trying to decrypt a cipher, which has been encrypted in PHP, using RSA in C#. Here is my PHP code that encrypts data:

public static function encrypt($dataToEncrypt, $userPublicKey) {
    if (openssl_public_encrypt($dataToEncrypt, $encrypted, $userPublicKey, OPENSSL_PKCS1_PADDING)) {
         return $encrypted;
    } else {
        throw new Exception('Unable to encrypt data. Perhaps it is bigger than the key size?');
    }
}

And the C# code is:

public byte[] Decrypt(byte[] dataToDecrypt)
{
    byte[] plain;

    using (var rsa = new RSACryptoServiceProvider(2048))
    {
        rsa.PersistKeyInCsp = false;

        rsa.ImportParameters(PrivateKey);
        plain = rsa.Decrypt(dataToDecrypt, false);
    }

    return plain;
} 

I get no exceptions or errors in C#. The problem is that if I convert the byte array output of the Decrypt() function to a string, it would be very different from the original plain text passed to 'encrypt' function in PHP.

To be more precise, the input data - i.e. $dataToEncrypt - that I'm trying to encrypt in PHP is:

$sessionKey = mcrypt_create_iv(32, MCRYPT_DEV_URANDOM);
// which as a base64 string it could be like:
// VPA13tGd8HMlaB3yKxlFBb8/dAXlCjX5Rr1SzE4L6TY=

If I convert the output of my C# 'Decrypt()' function to base64 string, it would be like the following, which is total garbage:

UTgfMQfl82FV4D4HfHPiwmo7jOygBmtXBap0Hn+fAoT4zZcGmLXiY1rGIhmEr90tNxzTGHhknx6PhgJ5eZDK2c9aWi/gD3FJz8MksRjbOkX09GMabcdekdwcyvu9JEWJZi2wOSaRLTRkf90uOArq7pG1g8CPwPLkghj39nUF+XYdGyAB4SXmKkPHshg+dk1acEaXhj9mnAF2fluDEJnfQEU= 

Any idea why are they different? What am I missing?

p.s. I'd like to add that I have code to encrypt data in C# and decrypt it back in PHP, in a very similar fashion. It works like a charm with no problems. This at least proves that the public and private keys are paired-up properly and there is no issue on that side. Here I bring both keys, just in case if they help to solve this mystery. 

-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAzMzT6e4CVC11E1w9bXhnIVgZIAfs5McBeewW3bZtS8NBelHs
HyxiZjkHgMZp6BGSsux0gl0e+DkeISHe5dOQEX7WJBaARxiGJxTzhEo556rrmSXz
7h5TSht/ivTWPZTYfAaYwLC71C/IKWfRPGSVuqHTlflVc0JSUF3M6dgWPqLRF7G3
qqYFdx3+2CoVyCQkNogvkICZNbGGtx7RlGHJ1LCeCyEdC+6AIyNItBbXGtBOf/IZ
bdL+QioWCV/VzQAhm01QVn8g6CHiCMvAIMMj2RXUg/1tL2vw0QNS2ZJgfsM3x67s
M47T1zHj/OTaX6lAp77FHkof1tKmTwlV1RSj7wIDAQABAoIBAGHMbmYHgpUwH/he
0/ayyIzjxRvGrRmS7uGKHGFD/G1xkJMZC+jXCSZHlY2pMmnf+m32/KxES8W9gOXR
ht+5Z9Ly/s+87wUEcQu4tZE24PAAbwFzXkkXsi5xczaoNKazra2MeOWLgCaTqsIb
EZAFeHrnTGMR7fxcb3JxWKlSx0yhGDzt4bF6rNokN6928d2Y77QdqD280XNsEP1r
RpXfHchTPPUUVpzTXEt/tVMzpsE12oMxPbwVkmCAtDYQsFhreSeWsJzFuXk1wXbR
9JkJ0BoU30KP2HxdxVZjD/+2TzJFphceW+YMXc/w/9tanR3234xjgQcE6PncuKuV
gVmEmgECgYEA0kNaMG3YAa3Xmc2KfiZuFVvH8xrCOaKufBle4uh0fQ+S0w6t8R8N
MJ9futVS9maW6aNKCXNb687cy2/8+7QGXqjgRVbni7Tgj/YaDHralIWO0UL5zl04
eZFPuSthdTAkx4F2m+lfPvooIGh5U6lX7PvX3TmaP+KkGJH+KWDQAdMCgYEA+VlD
6Frvy5l+yetavSgqsY/HVV1b0+yNvMvZjUm4ho7LCLFyB2aELkfalQtz1DsOwybm
Wnh5kkUTiPkmVU+3p5FyFIY3Etpk9p3KebWggF/KE9CYmgJxwB1Xq7gWGQtwK3VM
1kYxHtcohbQjV6gE6eTwvjAGYtfdhMVN0Po9Z/UCgYBzyomRX/xzuEOiPJIHNKys
8HVliJfrW46RYvthJDh6YqgtuMjLn5kI7MuwPShJ72cuVTFBkRjO/IWVNx/vkU1s
tb2EEf7DbiG4xgPEWaej4QUscqDVJ3shX4ey5pPuEExA3ifuZo+ARAzzA/XEv95e
8LYI617pzasmqMd6DAmg5wKBgQD3SVr6fe0g6xp94CZ+P+6PZ/sVIuBl/UzX9wbL
g1g4QjcDaQ+gXUArseEKPXBjAyrxyYtcH+zZbh4gko88vjFyQuFzj2PhE6xblENw
jvsdNWJwYkhlPJVZJQCEca2gquJUhyFrw/MFFfa/GtaOITi2SfGjfHdo4ZJ0EUTK
QtJRXQKBgQC8nppgSxh0yy0zXOj04URAt2NLBrBWZVh6kHFgaNPIsLNXqyFQQ+Sy
EX/w3HADQI4PRE90iauZ0DYGJyxY1jHqa0X64W/5nZqH/uv58+Hf6uv47l3n3n0T
58WFfKgXY5AaLCbi1UERdeHKPXNXDFkTKuuOb190M+RNbGgzwN9fcQ==
-----END RSA PRIVATE KEY-----
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA498EWxuZK/KsUgIEusEt
QOJulgTHwb8C4avtzJnzhosTeKooXvyGFPpex6HcQGSRqrWpNr2yhw1BvJvH2UyE
Jisl5BJA5Za+ofmbGifCFwCllZ37U1YpOmqpB2Yt+yYElGh5dp+lqs5Q3u3nPknd
nLS3bxH7qlZBvR9YPWj9x7IuSXJyopAmdJato8xeNHzmBxWD8FgQKICFpLtGsPXq
XRwT0imTs6/EcMqq6fdlp0OyBKyZjw6t47gMeqiuSYz6k41Nf/SbtIC4snUyoUgI
TvnHjWe1cY7js4kY62A9ZpHX0NpG7JXctxVb+aZOv1rS36bUjcP+bug1W3ZKrTG6
hwIDAQAB
-----END PUBLIC KEY-----
Edited by CloudWindMoonSun
Link to comment
Share on other sites

What on earth are you even trying to achieve? Messing with raw RSA and inventing your own security protocols is highly suspect and a recipe for disaster. For a non-expert, there's no valid reason to do that.

 

So what's the bigger picture here? Who gave you that task? What are the goals? And I don't mean “I want to encrypt data”. I'm talking about the nature of the data, the threat model etc.

Link to comment
Share on other sites

So we have got PHP running on the web server. It encrypts data (RSA) and sends to users, whom on their machine they have an application written in C# that is supposed to decrypt it.

 

The scenario is as simple as that. There is no invention. This is just a matter of encrypt/decrypt. The complexity is that encryption is done in PHP and decryption done in .NET. 

Link to comment
Share on other sites

Bullshit. What you're trying to implement is ultra-low-level cryptography (appearently some kind of hybrid encryption), and the only scenario where this would be valid is if you were a cryptographer trying to design a new protocol.

 

Since you clearly aren't a cryptographer, I'm asking how on earth you've ended up with this approach. Did somebody give you that task? Is it your own idea?

 

If you just want to encrypt data (what data?), you're horribly confused. You do not use raw RSA for that. You use an existing tool or protocol like GnuPG/SSH/HTTPS/... which has been carefully designed by actual cryptographers. The right tool depends on your requirements, which is why I asked you what those requirements are.

 

I repeat: Your current approach is completely inappropriate for the goal you've stated.

Link to comment
Share on other sites

Your guess is correct hybrid cryptography - obviously. No new protocol is to be invented but to re-use the wellknown cryptography techniques - i.e. good old RSA+AES+DigitalSignature+HMAC+etc.

 

I'm not born a cryptographer either. That's correct. But I'm interested in this field although I'm still at the beginning of the road. However I don't know why you think someone asked/forced/tasked/paid me to do this!!! I've just asked a technical question and whether I'm tasked by somebody or not, is not relevant here. And the answer is nobody anyway. There is no financial gain involved in this little project either. And the intention is to use open-source only. 

 

What data? Suppose everything from trivial data to sensitive data like personal information, emails and passwords to credit card details.

 

The idea is to have PHP on the server and .NET on users' machines. I hope I could answer all you questions about motivation and intention behind this post. Please let me know if you need more information. 

 

So if you think what I'm trying to do is 'completely inappropriate'. Can you shed some light on protocols you mentioned? Can they be implemented by PHP on the server and then used by the users running .NET app? Is there any cost involved like, license fees, etc.? Can you suggests some resources that give full detail about practically implementing them?  

 

However if you can help me to find a solution to my original question, I'd be very grateful. I cannot sleep until I find what I was missing, to find why I can encrypt/decrypt one way but not the other way around.

 

Cheers 

Edited by CloudWindMoonSun
Link to comment
Share on other sites

What you don't understand is that implementing a cryptographic solution is far more difficult than putting a bunch of cryptographic primitives like RSA or AES together. Anybody can use algorithms, but using them correctly in the right context in the right order with the right data requires expert knowledge which laymen don't have.

 

Have you ever looked at a professional protocol like the TLS handshake? Can you see that this is a lot more than “Let's encrypt an AES session key with RSA”? TLS has been developed over a long period of time by actual crytographers and still had several vulnerabilities. So maybe cryptography isn't as super-simple as you think.

 

The problem is that attackers don't play by the rules. Your protocol (yes, it is a protocol) may look great on paper, but when you're using it in the real world, it will be sabotaged and circumvented in all possible ways with techniques you probably haven't even heard of. In theory, you just have to combine RSA and AES. Easy, right? In reality, you have to deal with replay attacks, side channel attacks, padding oracles etc. If you get just one tiny aspect wrong, chances are the whole thing can be broken by a teenager on his $200 laptop. You seem to think that RSA and AES somehow make you immune to attacks. That's not the case. Both algorithms are extremely fragile and will leak the entire plaintext when used in a naive fashion. For example, breaking ciphertexts which have been encrypted with AES in CBC mode is a very popular exercise for students.

 

This is why there's one important rule in cryptography: Don't roll your own. Don't invent your own algorithms, protocols or encryption schemes. Even professional crytographers avoid this whenever possible. The right approach is to use an existing protocol which has been extensively peer-reviewed and survived real attacks over a course of many years.

 

If you want specific advice for the protocol, then you need to provide specific information. “I want to encrypt all kinds of data” is meaningless. I need a concrete scenario.

  • You want to protect the network traffic between the clients to the server? Use HTTPS.
  • You want to protect the passwords and prevent them from being stolen from the server? Hash them with bcrypt. There are also public-key authentication schemes (like HTTPS with client certificates) which don't require any passwords at all.
  • You want to protect credit card information? Don't collect them in the first place. Use an external provider which does that for you.
  • You want to protect the data in your database? Learn how to harden the configuration. Database encryption isn't very useful, unless you're willing to spend thousands of dollars on a hardware security module to hold your key. Putting the key onto the same server right next to the encrypted data is obviously ill-advised.
  • ...
Link to comment
Share on other sites

Specific information:

 

User is gonna communicate back and forth to the server which runs the database. In the database the following data will be stored.

- name, address, email (these data are to be protected by all means)

- business specific data, which are not sensitive at all, and are only meaningful to people in the business with no harm being leaked.

- their shopping orders and payments (not very sensitive data, so I see no harm to be seen by public even if they are leaked).

- credit card information (super sensitive data, should not be intercepted at all)

 

Obviously the user is going to be authenticated using their user name and passwords (which are done by hash_hmac, PBKDF2, salt, iteration, etc.). Their name and hashed password gonna be saved in the database table.

 

The database is going to be protected by password.

Link to comment
Share on other sites

Now we're getting somewhere. So there are two problems: Protecting the network traffic and protecting the data at rest.

 

To protect the traffic, use HTTPS. If configured correctly, this will reliably prevent eavesdropping and manipulation of the data. Note that HTTPS also supports public-key authentication via client certificates, so you could get rid of the passwords altogether. This is more secure, but it requires extra work which may or may not be pratical in your case. You essentially need to run your own mini-CA (certificate authority) on an offline PC, and your users will have to obtain their certificates from you.

 

To protect the data at rest, the first step is to harden the database configuration and minimize privileges. Ideally, the application and the database should be on two separate servers, be it physical machines or VMs. Then you should create restricted database roles for the different parts of your application (public website, admin area, automated tasks, ...) and only allow access to the data which is actually needed. For example, you could block any access to the names and e-mail addresses if there's no need to ever show them on the website (not even to the users themselves). Or you could let the application only see shortened versions of the data (e. g. turning “joe.blow@gmail.com” into “j***@gmail.com”, which should be enough to recognize your own address but doesn't give it away to anybody else).

 

Last but not least, make sure that your overall code quality is good and that you've covered all security basics (prepared statements, thorough escaping, anti-CSRF mechanisms etc.). I've seen several cases where people spent a lot of time on advanced security while their application was wide open to even the most trivial attacks.

 

 

 

- credit card information (super sensitive data, should not be intercepted at all)

 

Like I said, you should leave that to a professional payment provider. You said this is more of a hobby project, so you definitely don't want to get involved in the technical and legal trouble of storing credit card data.

 

 

 

Obviously the user is going to be authenticated using their user name and passwords (which are done by hash_hmac, PBKDF2, salt, iteration, etc.).

 

PBKDF2 is largely obsolete and rather obscure. Use bcrypt. PHP even has an extension for that.

Link to comment
Share on other sites

Thanks for the guidance and explanation.

 

 

 

Note that HTTPS also supports public-key authentication via client certificates, so you could get rid of the passwords altogether. This is more secure, but it requires extra work which may or may not be pratical in your case. You essentially need to run your own mini-CA (certificate authority) on an offline PC, and your users will have to obtain their certificates from you

 

I don't understand how an off-line CA would work. I thought my C# app which runs on users' machines will create private and public keys, and will post their public key to the server. However a little bit research lead me to things like 'ssh2_auth_pubkey_file' and like, which seems to be not too difficult to utilise. 

 

I have done the database side (config, privileges, etc.) before for other projects. So that'd be fine.

 

 

 

Like I said, you should leave that to a professional payment provider. You said this is more of a hobby project, so you definitely don't want to get involved in the technical and legal trouble of storing credit card data.

 

 

Absolutely. I decided not to store credit card information at all. I'm sure the user would be happy to take the pain of entering their card number in full to payment providers, if they know this way they will be safer.

 

cheers

Edited by CloudWindMoonSun
Link to comment
Share on other sites

I don't understand how an off-line CA would work. I thought my C# app which runs on users' machines will create private and public keys, and will post their public key to the server.

 

No. There mustn't be any raw RSA keys in your application.

 

TLS uses certificates. You first need a root CA to act as the root of trust for the entire public-key infrastructure. This is obviously the most critical entity, so it should be completely offline and not attached to any network. Then you create one or more (restricted) sub-CAs to do the actual work. Those may or may not be online, depending on whether you need automated signing. The purpose of this setup is that the root CA can revoke the certificates of the sub-CAs if those get compromised. If you just one CA for everything (maybe even online) and it gets compromised, you're screwed.

 

You then upload the certificates of the root CA and sub-CAs to the server. If you want an online CA for signatures, you need to install that as well.

 

When the user has created an account and been validated (confirmation of the e-mail address etc.), they or the client application send a certificate signing request to the server. Based on the request, you then issue a client certificate for this particular user, signed by one of the sub-CAs. You do not store the certificate or contained public key. Certificates are validated by checking if they've been signed by one of the trusted CAs (let the TLS library do that, don't try to implement it yourself).

 

Be warned that running your own public-key infrastructure is not trivial and requires solid knowledge, good tools and quite a lot of work. Besides issuing certificates, you also need a revocation mechanism in the form of certificate revocation lists (CRLs) or an OCSP server. The revocation data has to be regularly updated.

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.