How to encrypt/decrypt CSV file using 128-bit AES in php - php

Can any one please let me know the way, how can i encrypt/decrypt a file instead of string. I mean i need to encrypt the entire file it may be an excel-sheet or document or even text file.

instead of string.
That rather implies that you already know how to encrypt the string - and since you're being specific about the algorithm, that you can create an appropriate representation for the other tools being used to operate on the data. But you haven't said what mode of operation you need to use - implementing this using CBC is trivial.
It's also not stated - but implied in your question, that the data is too large to load into a string (otherwise its simply a case of encrypting file_get_contents()).
There doesn't seem to be much in the way of documentation, but I would expect the modificed key required for ECB is updated in the resource created by mcrypt_module_open() and modified by mcrypt_generic_init(). Then its just a matter of feeding in parts from the file sized as a multiple of the block size (see mcrypt_get_block_size)
See http://www.php.net/manual/en/function.mcrypt-module-open.php
C.

I'm a little confused, can't you just read/write the string to a file using functions like file_get_contents and file_put_contents?
If you need an encryption-class there are some over at PHP classes. There is also a paid solution here: phpAES.

I guess it is better to create your own library for it and expose an API that just accepts a filepath instead of it content. It can open read the file and do the encryption / decryption.
You can use your own or pre-existing algo for encrypt/decrypt. Also you can have an argument in that API to accept the filepath to store the decrypted data or replace with the same file or whatever.

Related

Turning data inside a string into numbers in php

I'm currently working with data I'd like to temporarily store in my database as encrypted data. I'm not worried about the database getting hacked into, I just want to ensure the people that had entered the data that it is not reachable by any other than themselves. (and me of course)
The data is not meant to be stored permanently in the database since I'm exporting it to a third party application using their API, but since they have a rate limit I need to store the data in our database until the limit is over and I can upload it. (Assuming the rate limit occurs)
The process:
The request I receive from the form is in an array, so to begin with I serialize() the array to get a long string which I will unserialize() later.
Then I want to use a method that lets me convert the string into numbers and back again without losing information.
The reason I want to turn the data into numbers is because I use the HashIds library, which only encodes numbers. To my knowledge it's an extra layer of security I'm happy to add.
Read more on HashIds here: http://hashids.org/
What I have tried:
I tried converting the string into hex numbers, and then the hex numbers into decimals. Unfortunately the number was too large, and i haven't had any luck using biginteger with it.
base64_encode() which is not going to turn the data into numbers, but then base_converting them is. But I couldn't figure out the base converting in php since apparently it's rather odd.
Conclusion:
How can I convert the data I'm receiving from a form request into a short encoded string which can be converted back into the data without too much hassle? I don't quite know all the options PHP offers yet.
UPDATE:
To conclude this thread, I ended up using OpenSSL to encrypt my serialized array. Only problem I ran into was if the request contained a file I wouldn't be able to serialize it and save the object to the database. I do still need a way around this, since the third party application expects the file to be a multipart/formdata object i can't just save the filepath to the database and upload that. But I guess I will have to figure out that one later.
That link http://hashids.org/ provides a pretty clear example. Lets assume that your integer is 15.
$hashids = new Hashids\Hashids('some random string for a salt. Make sure you use the same salt if you want to be able to decode');
$encoded = $hashids->encode(15);
print_r(['hashedId' => $encoded]);
$decoded = $hashids->decode($hashed);
print_r(['decoded' => $decoded]);
So the value of $decoded should equal 15
Update
Sorry - the hashids bit of your question threw me and as such, I misunderstood what you were asking. I will update my answer:
You should really be using https://secure.php.net/openssl_encrypt and https://secure.php.net/manual/en/function.openssl-decrypt.php

Image versioning - Best approach

I am developing a site framework in php (codeigniter) and want to introduce image versioning on image uploads so that I can take advantage of image caching. The easiest approach would just be to md5 the image and use that as the file name but I don't like this approach for the following reasons:
1)Not SEO friendly on the image names
2)md5 hashes seem unnecessarily long - and therefore larger database
field required.
So I am considering using an approach such as the following:
Start the filename with the entered name of the image with underscores instead of spaces then add a randomly generated integer, say 8 digits long. This will mean I have to check for an existing image by that name and then regenerate the integer if one exists (however unlikely that is).
Presumably I will also have to unique filename for every image size, so I guess the solution here would be to add a prefix representing the file size.
Now I want to get this right first time since it will be a pain to change once the framework is deployed so I am really just looking for input on
a)Whether my concerns are justified (particularly does the filename do
anything for SEO and does the length of a random string of numbers
affect it)
b)Whether there is anything else I should be concerned about or check
for with my proposed approach.
c)Is there an easier approach, perhaps a hashing algorithm which
produces much shorter results.
d) Is there already a ci lib out there that does this?
Thank you for your input and advice
This answers a few of your questions:
Replacing spaces with underscores is not enough to have a clean filename as you'd need to check for more weird characters, but you can use sanitize_filename() method in CI's security library: http://ellislab.com/codeigniter/user-guide/libraries/security.html
If you do want to preserve the original filename, your approach sounds good to me. Though, 8-digit integer at the end of filename can be replaced by '-1’, ‘-2’, ‘-3' by simple incremental loop checking if the file with that ending exists or not.
File Upload library is something you can check out - http://ellislab.com/codeigniter/user-guide/libraries/file_uploading.html. It is flexible and can be configured to keep the original filenames. Getting sanitize_filename() from Security lib to work along should do exactly what you need.
In all my CI applications I always use encrypted filename (this optional feature is provided by CI file upload class). At the same time I can configure the library to not overwrite already existing file by adding a number to it (if no encryption is used) or by just giving it another encrypted name (when encryption option is on). I do like it this way as it keeps the filenames consistent clean (although long and not SEO-friendly, however ALT tag gives it more exposure to search engines).

Determine data type from file_get_contents()

I'm writing a command line application in PHP that accepts a path to a local input file as an argument. The input file will contain one of the following things:
JSON encoded associative array
A serialized() version of the associative array
A base 64 encoded version of the serialized() associative array
Base 64 encoded JSON encoded associative array
A plain old PHP associative array
Rubbish
In short, there are several dissimilar programs that I have no control over that will be writing to this file, in a uniform way that I can understand, once I actually figure out the format. Once I figure out how to ingest the data, I can just run with it.
What I'm considering is:
If the first byte of the file is { , try json_decode(), see if it fails.
If the first byte of the file is < or $, try include(), see if it fails.
if the first three bytes of the file match a:[0-9], try unserialize().
If not the first three, try base64_decode(), see if it fails. If not:
Check the first bytes of the decoded data, again.
If all of that fails, it's rubbish.
That just seems quite expensive for quite a simple task. Could I be doing it in a better way? If so, how?
There isn't much to optimize here. The magic bytes approach is already the way to go. But of course the actual deserialization functions can be avoided. It's feasible to use a verification regex for each instead (which despite the meme are often faster than having PHP actually unpack a nested array).
base64 is easy enough to probe for.
json can be checked with a regex. Fastest way to check if a string is JSON in PHP? is the RFC version for securing it in JS. But it would be feasible to write a complete json (?R) match rule.
serialize is a bit more difficult without a proper unpack function. But with some heuristics you can already assert that it's a serialize blob.
php array scripts can be probed a bit faster with token_get_all. Or if the format and data is constrained enough, again with a regex.
The more important question here is, do you need reliability - or simplicity and speed?
For speed, you could use the file(1) utility and add "magic numbers" in /usr/share/file/magic. It should be faster than a pure PHP alternative.
You can try json_decode() and unserialize() which will return NULL if they fail, then base64_decode() and run that again. It's not fast, but it's infinitely less error prone than hand parsing them...
The issue here is that if you have no idea which it can be, you will need to develop a detection algorithm. Conventions should be set with an extension (check the extension, if it fails, tell whoever put the file there to place the correct extension on), otherwise you will need to check yourself. Most algorithms that detect what type a file actually is do use hereustics to determine it's contents (exe, jpg etc) because generally they have some sort of signature that identifies them. So if you have no idea what the content will be for definate, it's best to look for features that are specific to those contents. This does sometimes mean reading more than a couple of bytes.

How would i encode certain $_GET params?

Im currently using base64_encode for some $_GET params that i don't want regular user to mess with.
I was wondering that base64 is not looking too strong or is it ?
I also don't want to make some sort of mega encoding it's not so much of important information, but i would not like that user with average knowledge would mess with params in get.
Should i keep using base64 ? Currently it produces MQ== if value is 1 so it's quite easy to take it out from URL and decode and then insert your own.
Base-64 encoding doesn’t protect the data in any way. It’s a simply base conversion like using hexadecimal instead of decimal for integers.
If you just want to verify data integrity, you can use a salted hash (with a secret salt) that you store along with the data. See for example the hashed message authentication code (HMAC).
base64_encode() is not a security measure! It was designed to make sending of binary blobs possible through mediums that typically transfer ASCII only.
Use a session, or properly encrypt your variables.
I would recommend just using a session, and storing it out of the default /tmp for good measure with...
ini_set('session.save_path', '/sessions');
If you want some real encryption/decryption take a look at the Mcrypt features of PHP. http://www.php.net/manual/en/mcrypt.examples.php
But then you may want to use POST instead of GET because of the URL specifications which are limited in character usage and URL length.
Depends on what you want do do with it.
If you just want to obfuscate it (especially when you're generating those URLs in Javascript or so), you could apply ROT13 to the URL and swap a few additional characters to make decoding it a little bit more difficult.
However, if the security of your application depends on it, you could apply a static-key symmetric encrytion on the data server-side and decode it when you receive a request or so. I think that there are frameworks or so for that.

How to encrypt fields in XML document with PHP and RSA / Triple DES

I am developing an application for schools in South Africa which is required to submit data in XML format to the State IT Agency for statistical processing. I am currently generating the XML files using PHP's DOMDocument class.
My files have gone through a first stage verification process. The next stage is to implement encryption and compression of the XML files. The compression is a simple GZip so no worries there.
The specification document indicates that both RSA Encryption is used (I will be issued RSA keys to implement into the software) as well as some form of symmetrical encryption such as Triple DES (although this is an "example" and any of the algorithms at http://www.w3.org/TR/xmldsig-core can be implemented). If I understand this correctly, the RSA encryption is to encode a symmetrical key which is used for the actual encryption of the fields.
The specification document also says "Encryption of an XML file can be performed either on the whole file or on certain elements." I'm not quite sure which is easier, at this stage and so answers to either will suffice!
The requirement is, I assume, to encrypt the contents of the XML tags and not the names (as in http://www.w3.org/TR/xmlenc-core/#sec-eg-Element-Content-Character).
I apologise if this seems vague. It is currently all the information I have and the contacts at the Agency are happy to say that the (VisualBasic .NET) code samples should explain everything... If you want to examine this code sample, you are welcome to have a look at the Word document in the following ZIP file, from about page 213 onwards. http://www.sita.co.za/doe_lurits/DEVS-00118%20Rev%201.2%2012%20Jan%202009.zip
If anyone can help or point me in the right direction, I'd appreciate it.
You should just encrypt the XML file using XMLSec Encryption. The following library should handle all the details for you,
http://code.google.com/p/xmlseclibs/
See openssl_encrypt for symmetric encryption and openssl_public_encrypt/openssl_private_decrypt for asymmetric encryption.
Sounds like you can either encrypt the entire document or just the contents of certain "sensitive" tags. Encrypting the entire document would probably be the easiest way to go.
As for the RSA/3DES thing - you are almost certainly right. You would encrypt the document with 3DES, then encrypt your 3DES key with their RSA public key.
So, seems like what you need to do is just generate the document, zip it, then encrypt the zipped results with 3DES.
The Symmetric-encrypted-document-plus-PK-encrypted-key architecture is essentially PGP. Would OpenPGP be acceptable to your customer?

Categories