How to encrypt long strings in PHP? - php

I'm using PHP's openssl_public_encrypt() to encrypt data using RSA. But it won't encrypt data larger than a certain size.
How can I get it to encrypt data of an arbitrary length?

RSA, using PKCS1 padding, only lets you do do strings that are the length the key (in bytes) - 11. This isn't an OpenSSL or PHP restriction but rather an RSA restriction.
If you want to do longer strings using the openssl_* set of functions use openssl_seal and openssl_open. openssl_seal generates a random string, encrypts it with RSA and then encrypts the data you're actually trying to encrypt with RC4 using the previously mentioned random string as the key.
phpseclib, a pure PHP RSA implementation, takes a different approach. If you insist on encrypting a string larger than the RSA key it'll split that string into chunks that are the max size RSA can handle and then concatenate the results.
The phpseclib OpenSSL Interoperability page discusses how you can use phpseclib to do the same thing as openssl_seal / openssl_open.
Hope that helps!

The php.net page has an excellent hint for this problem (as usual) http://www.php.net/manual/en/function.openssl-public-encrypt.php#95307

You can either:
Encrypt the data using a symmetric encryption method, using a random key that is then encrypted using the public key of an asymmetric encryption method (The random key, encrypted with the public key, is necessary to the user who decrypts the data.)
Encrypt the data using an asymmetric encryption method, after splitting the data in chunks of the size handled by the asymmetric encryption method
The first implements a hybrid cryptosystem. Using PHP and the openSSL extension you can use openssl_seal(), which (since PHP 5.3.0) allows to set the cipher method (by default, RC4) and (since PHP 7.0.0) the initialization vector. If you aren't using PHP 7.x, or you want to write code compatible with PHP 5.3.3 and higher versions, and you want to be able the initialization vector, you could
use openssl_random_pseudo_bytes() to generate the random key, openssl_encrypt() to encrypt the data, and openssl_public_encrypt() to encrypt the random key.
I would not use openssl_seal() with a PHP version that doesn't allow me to set the cipher method (but then, I would not use that PHP version because it's not supported anymore), and I would not use RC4 as cipher method, on PHP versions that allows me to select the cipher method.

Related

Encrypt and decrypt long strings in PHP

I want to encrypt and decrypt data strings that are longer than 2500 characters. Is it possible to encrypt and decrypt such long data strings. It's like essays. Please tell me which encryption and decryption technique should I choose for such long data in PHP. Also what will be the effects of this on the database? Will the database will become heavy. What will be the length of the encrypted string that it will return?
I have never encrypted data in PHP rather than using only md5().
MD5 is NOT encryption, it's a hash function, a one-way method to obfuscate data.
For encryption of data that you can also decrypt, take a look at Simplest two-way encryption using PHP.
md5() isn't usually used for encryption, but for hashing purposes.
There are many extensions in PHP that deal with encryption. You can find them all here:
http://www.php.net/manual/en/refs.crypto.php
The most well known extensions are Mcrypt and OpenSSL.
With OpenSSL, you can use openssl_encrypt() to encrypt your data.
With Mcrypt, you can use mcrypt_encrypt() to encrypt your data.
Check the relevant sections of each extension for more information

How do I sign w/ private key in Node.js

I'm trying to do the equivalent for the following PHP function
openssl_private_encrypt
to use my private key to sign a string
Here's what I'm doing
var signer = crypto.createSign('RSA-SHA256').update(timestamp + '|' + userId);
var signature = signer.sign(privKey, 'base64');
My first question is what does it mean when RSA and SHA256 are put together? I understand what it means to encrypt something with RSA private key, or to hash something using SHA256. But I can't comprehend what it means to have those two together.
I put it there because createSign requires a string parameter, ("RSA" is not supported), and RSA-SHA256 is the closest thing I found.
My second question is how do I
openssl_private_encrypt
in Node.js?
Normal signing operations consist of a hash calculation, which is then (if required for the function) and then encrypted by the private key. The hash is the compressed - smaller - representation of the message, for which no duplicate hashes (collisions) can be found. For RSA the message is then padded using a scheme found in PKCS#1 v2.1 (public standard), after which modular exponentiation is performed.
The modular exponentiation is often incorrectly called encryption, encryption requires a different padding method for RSA (and hashing is not performed for encryption either).
You should not use openssl_private_encrypt to sign a string, it is a deprecated function, mainly required for relatively particular authentication purposes. When used on its own it encrypts the data using the padding used for signing, but it does leave out the hash and the hash indicator.
To create an equivalent for openssl_private_encrypt you need to be able to perform the PKCS#1 v1.5 padding method and modular exponentiation. You can probably retrieve those functions from the source code of Node.js, it's unlikely you will find them in a higher level API. You are however advised to do away with the openssl_private_encrypt function in PHP and use a higher level signature function.

Can PHP's OpenSSL functions use the AES cipher with public/private keys?

I have seen many examples of how to use AES through OpenSSL with symmetric encryption. But I am using asymmetric encryption. My webapp is storing some sensitive data encrypted with a public key, which is later only decrypted with the private key if the admin can provide the private key passphrase.
My implementation is working well, however, I am noticing very small inputs produce rather large encrypted results. For example, a 16 character input becomes 288 bytes encrypted (it decrypts to the original 16 characters). Since these encrypted results are stored in a database table, I would like to achieve encrypted values that are much closer to the input size. Predictable storage lengths is desired, too.
I am using RSA public/private keys, but what cipher does PHP's OpenSSL implementation use by default? I haven't found a single example of how to specify a cipher when using public/private keys, and the openssl_public_encrypt function doesn't allow one of the cipher constants to be specified. Am I supposed to be specifying the cipher somehow when the pub/pri keys are generated (using openssl_pkey_new)?
AES is a symmetric encryption algorithm, it doesn't support public/private key pairs. Whoever can encrypt can also decrypt the ciphertext.
One can combine AES with an asymmetric algorithm like RSA to obtain a hybrid scheme: One uses RSA to encrypt a (random) AES key, and then uses AES to encrypt the actual data. You will still have the RSA overhead of a minimum ciphertext size of about the size of the RSA modulus (since this is RSA's output), though.
I suppose this is actually what your OpenSSL function does, maybe depending on the key type.
There are other public-key schemes, specially those based on elliptic curves, which allow a smaller size overhead for similar security as RSA. (I don't know if these are supported by OpenSSL or its PHP bindings, though.)
I would recommend creating RSA private and public keys. See This great article

PHP AES256 Encryption - VB Decryption

I have a project that I'm working on that requires me to send data out to a third party in an encrypted format. We chose AES-256 as the encryption for the data.
I'm using PHP and the other party is using VB. I'm using the MCrypt Library to do my encryption on my end.
I can't seem to match my encryption to their encryption. Is a shared initial vector required, in addition to a shared key phrase? Are there any other things to take into consideration to make allow my data to be decrypted by the other party?
Additionally I've been told that VB uses a byte array for the IV. With the MCrypt library the examples use regular strings such as "1234567890123456" for the IV. Should I assume all that is required is a conversion from the above string to a byte array and all will be well?
Everything needs to be the same at both ends: IV, key, mode (use CBC or CTR) and padding (use PKCS#7). If any of these if different then things will fail. Crypto systems are designed to fail if anything is wrong.

High performance encrypt/decrypt in both PHP AND MySQL

Id like to redesign some aspects of my database/website, and am looking for reasonably strong crypto functions in PHP, which are also supported by MySQL.
I also need the encrypt/decrypt to be 100% portable & compatible
Mostly I will be crypting in PHP, selecting the crypted version from MySQL, and then decrypting in PHP.
But occasionally I will need to run a query which decrypts the field in MySQL, for reporting purposes etc
I had a look at mycrypt php library, but its not clear which of these ciphers are supported by MySQL.
Any recommendations plase?
After a bit of Google-fu it appears MySQL uses 128-bit AES with Electronic Codebook (ECB) mode. For the key, you'll need to use exactly value that's exactly 16 bytes.
Lets say I use _My-16-byte-key_ as my secret key.
SELECT AES_ENCRYPT('The rooster crows at midnight!', '_My-16-byte-key_')
Result is: 7e41520667dc20457db2f18644bad06dd62a2120be8b93cd5596d8ffea45ef0f
Over in PHP, I can use mcrypt_decrypt to reverse it:
$secret = '7e41520667dc20457db2f18644bad06dd62a2120be8b93cd5596d8ffea45ef0f';
$key = '_My-16-byte-key_';
print mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, pack('H*', $secret), 'ecb');
Result:
The rooster crows at midnight!
I'll leave the reverse flow as an exercise to the reader. =)
Here: http://dev.mysql.com/doc/refman/5.5/en/encryption-functions.html
Is a list of all the encryption functions in MySQL.
I recommend to use AES.
All the other encryption options are no longer secure.
AES supports a 128 bit key length (and a 256 bit key length with a recompile of the MYSQL source).
Don't forget to salt everything you encrypt with AES to prevent rainbow table attacks.
If you use the same key to encrypt decrypt everything all the attacker needs to do is get that key, with the hash function (and salt) you don't have to worry about losing the key, with this option you run a huge risk of losing the key and all your passwords with it.
Use a hash function instead: SHA256 with a salt.
I also recommend AES, it is designed to be fast and since it is industry standard it is strong enough. However, what the reason to encrypt data inside database? If your encryption key will be stored in PHP scripts, it will not be more secure than using cleartext records. It has benefits only if many scripts access the same database.

Categories