Felipe Weckx

Using the new PHP 5.5 “password API”

Introduction

Storing user passwords in any system or website is a subject that often does not receive the deserved atention. Many systems store the password as plain text or using weak cryptography algorithms, which causes several cases of password de leaks.

To ensure that in case of breach the attacker doesn’t find out the user password we can use a hash function to store it. A hash function creates an output from any input and that output cannot be used to restore the original input.

That’s why hash functions are so good to store passwords. In theory. There are many hashing algorithms such as: MD5 e SHA1. The problem of using these algorithms directly is that there are many pre-compiled hash tables which contain millions of these values. Some techniques, such as Rainbow Tables allow for easy cracking of weaker ciphers. For example, lets make a MD5 hash of the value felipe0111:

Which gives us this:

simple Google search for the hash value gives us the original value, so we obviously cannot use MD5 to store passwords. The SHA1 stronger, but also easily crackable.

The PHP password API

To make things easier for developers and encourage the safe storage and handling of passwords the PHP 5.5  version added a few new functions for this.  One of the big advantages of using this API is that, if used correctly, it ensures that your passwords are always stored with the strongest hashing algorithm available. That is achieved using the PASSWORD_DEFAULT constant.

Using the API

Generating the hash

The simplest use of the API is hashing a password using the password_hash function:

Notice the use of the PASSWORD_DEFAULT constant, using it will make sure that our hash is generated using the strongest hashing algorithm available, so it is important that the place where this hash is stored (ex: database field) is large enough to hold the generated string and also have some growth room (when the algorithm is updated).

Comparing hash

Now that our password is safely stored we can compare the value the user passed with it. That’s achieved using the password_verify function, which simply receives the raw input and the hash to compare. It is imporÉ importante utilizar esta função para comparar pois, se o hash tiver sido gerado com um algoritmo diferente do atualmente configurado em PASSWORD_DEFAULT o hash não irá bater. A função password_verify automaticamente identifica o algoritmo utilizado e usa o mesmo para conferir.

Atualizando o hash com novo algoritmo

Outra vantagem da API de senhas do PHP é que podemos verificar se há um algoritmo mais forte para gerar o hash da senha. Ou seja, se numa versão nova do PHP for incluído um algoritmo de hash mais forte, a constante PASSWORD_DEFAULT terá seu valor alterado, mas nossas senhas permanecerão armazenadas com o algoritmo antigo. Isto não gera problemas na comparação com password_verify, mas pode tornar mais fácil a descoberta das senhas. Para isto há a função password_needs_rehash que indica se a senha precisa ser criptografada novamente:

Conclusão

A API de hash de senhas do PHP é uma ótima adição à linguagem, dando organização e um método de trabalho claro para lidar com o armazenamento e verificação de senhas. Com poucas funções ela organiza bem todo o fluxo de autenticação com senhas e ao utiliza-la podemos minimizar os dados causados por uma invasão ou vazamento de dados.

Streaming videos with PHP

Videos for the Web

With the recent support for HTML5 in most modern browsers, nearly all of them can understand the <video> tag which allows to place a video in a webpage. However, not any video format can be used for there are limitations between browsers and their versions, so before serving a video on the web it has to be converted to a supported format.

Supported Formats

MP4 is the most widely supported video format on the web today, however it is possible to specify several sources in the <video> tag which allows the browser to choose format it supports best. According to W3Schools the supported formats  in each of the most common browsers are:

 

Browser MP4 WebM Ogg
Internet Explorer SIM NÃO NÃO
Chrome SIM SIM SIM
Firefox NÃO SIM SIM
Safari SIM NÃO NÃO
Opera NÃO SIM SIM

For this example this video in the Quicktime (.mov) format will be used. The FFmpeg, available for Linux, Windows and MAC will be used.

Converting to MP4

To convert the video into the MP4 format use the following command line:

ffmpeg -i Rain_Fire.mov -c:v libx264 -pix_fmt yuv420p -profile:v baseline -preset slower -crf 23 -vf "scale=trunc(in_w/2)*2:trunc(in_h/2)*2" -movflags +faststart rain.mp4

Some important parameters of the command above:

  • -c:v libx264 – Use the x264 codec, very importante since its the most widely supported
  • -pix_fmt yuv420p – Pixel format to use
  • -profile:v baseline – Video profile. The baseline profile makes it easy for Androi devices to support
  • – preset slower – Determines the size/encoding time ratio.  Can be (faster, fast, medium, slow
  • -crf 23 – Quality encoding level. 0 means lossless and 51 the worst quality possible. The default is 23 which is a good value.
  • -vf “scale=trunc(in_w/2)*2:trunc(in_h/2)*2” – For some reasons MP4 movies using this encoding need even width and height. This parameter adjusts these values.
  • -movflags +faststart – Places the video information headers on the beggining of the file, this allows the browser to download the video information first.  This parameter is essential to allow the streaming of the video.

For more information see FFmpeg documentation on H.264 video encoding.

Converting to WebM

Another possibile video format is WebM which uses the VP8 codec , a royalty free video codec purchased by Google. To convert to this format use the following command:

ffmpeg -i Rain_Fire.mov -c:v libvpx -c:a libvorbis -pix_fmt yuv420p -b:v 2M -crf 5 rain.webm

The parameters are

  • -c:v libvpx – The video codec to use (VP8)
  • -c:a libvorbis – The audio codec
  • -pix_fmt yuv420p – pixel format
  • -b:v 2M – desired bitrate. It is important to set this parameter as the default creates poor quality videos
  • -crf 5 – Video quality. Ranges from 4 – 63. The smaller the better.

More info on the FFmpeg VP8 documentation.

Serving the file

With the correct format files let’s create a simple site to serve it. The following directory structure will be used:

Estrutura de diretórios

Estrutura de diretórios

In the public directory are the files that are visible by the webserver and in the resource directory the video files which we will serve. The index.php file has the HTML and stream.php is where we will read the video files using PHP to serve them.

Streaming

Streaming is a data distribution method in which the content is served to the client as needed, in a way that it is not necessary to have the full content before acessing it. That is the best way to serve video files because it allows quick visualization by the user and also lowers bandwidth usage. The web browsers use the HTTP Range header to indicate which bytes of the video it wants.

Handling the Range header

According to the RFC2616 which specifies the  HTTP protocol version 1.1 the Range header specifies the portion of the content to be served on the request and format of the header is one of the following:

  • The first 500 bytes: bytes=0-499
  • The second 500 bytes: bytes=500-999
  • The last 500 bytes: bytes=-500
  • All bytes since 9500: bytes=9500-

The header value is available on the $_SERVER[‘HTTP_RANGE’] variable, the code below for the file stream.php uses the PHP filesystem functions  to read a video file and serve it.

It is essential to handle the Range header when streaming video files otherwise the forward, reverse and seek player options will not work. Also, without that the video would have to be completely downloaded before watching, which gives a bad user experience.

The web page

Moving on to the web page the file index.php  will have the HTML with the <video> tag and will be the one acessed by the user:

The file can be tested using a webserver o the PHP built-in webserver executing:

php -S localhost:8000 index.php

And on the browser access http://localhost:8000

The <video> tag

The <video> tag is used to add the video element to the page. Inside the tag there may be any number of <source> elements, each one with a video or audio URL. So it is possible, for example, to specify a video and an audio file that will be combined by the browser on playback. In our case we specify two video sources, on for the MP4 file and the other for the WebM file and the browser will decide which one to use. The attributes for the tag are:

  • controls – Wheter the video controls should be displayed
  • preload – If the video will be loaded with the webpage or not. The value can be auto to load, , metadata to load only the metadata or none to not load the video util it is clicked (played) by the user. Internet Explorer does not respect this parameter.
  • width height – The video width and height if it is not the same as the file the video will be resized by the browser
  • poster – URL for an image that will be displayed in the video container util the video is loaded or played. It is possible to create it using FFmpeg as we will see below.
  • autoplay – if specified the video will start playing as soon as possible

There are several other parameters available.

Creating the poster

The poster image can be created using FFmpeg with the following command:

ffmpeg -i Rain_Fire.mov -r 1 -vframes 1 -ss 0:05 poster.png

The most important parameter is -ss 0:05 which specifies the time where the image will be extracted.

Using video.js

The page works on any modern browser that supports HTML5. But what about older, but still used, browsers such as Internet Explorer 7 or 8? For those we can use the video.js javascript library. It automatically detects if the <video> tag is supported and if it isn’t it is replaced with a flash video player automatically. The update index.php is shown below:

Conclusion

HTML5’s <video> tag allows for easy video embedding in web pages, but it is necessary to take care with the video format and make the necessary convertions. It is essential that the files be served via streaming to reduce network usage and enhance user experience. PHP allows easy handling of streaming by the use of its file system functions and the Range HTTP header. The code developed here is very basic and can be improved in many ways.

The example code is available at Github: https://github.com/weckx/wcx-video-stream

Translating ZF2 validation messages

Often we use the InputFilter to validate the elements of a form create with Zend Framework 2. However, when creating a system/website which has to support multiple languages we also need to translate the validation messages. Fortunately ZF2 comes with a series of translations for the default validation classes and we can set up the translation using the \Zend\Validator\AbstractValidator::setDefaultTranslator method:

The code above has to placed inside the Module class in the modules you need to translate the messages, or in your application module to enable in all of them. Note that we added it to the onBootstrap method, which means it will be executed in all actions. That can cause a performance issue, so it is best to separate it and call only on the controllers that actually use validations.

Zend Certified Engineer Certification

Recently I upgraded my “Zend Certified Engineer PHP 5.3” to the new “Zend Certified PHP Engineer” that covers the 5.5 version of PHP. I found the exam quite similar to the previous one (I believe some questions were actually the same). But there were some new topics:

The exam level is very similiar to the previous one, but it’s nevertheless good to keep the exam up to date with the language features. The new topics are great to provoke studying and getting to know new features. The complete list of topics is available at: http://www.zend.com/en/services/certification/php-certification/.

The exam voucher can be bought at the Zend website or at Pearson Vue for $ 195. Those who already have the PHP 5.3 certification get a $ 70 discount on the exam (you have to send them an e-mail). If you pass the exam you also get a perpetual Zend Studio license.

According to the Zend website the Zend Framwork 2 certification will come out this year (at last).

PHP: in_array and arrays with a true item

A very important parameter of the in_array PHP function is the $strict parameter. It has the default value of FALSE. But what exactly does it do? Let’s look at the following code:

The output will be as expected:

However, if we add to the array $array a new item with the value true:

Then the output will be:

Which means that the in_array returned true even though there’s no salmon item in $array! That is because by default the in_array functio uses PHP’s “loose comparison”, that is, it uses the  “==” operator to check if the value is in the array (more information on http://php.net/manual/en/types.comparisons.php) so any non-empty value that is compared to true returns true. That can cause a nasty bug that is very hard to find and understand. To solve it we can pass the $strict parameter as true:

Now the comparison will behave as expected. That kind of mistake can be easily prevented if the software is developed using TDD with a good test coverage and test cases, but otherwise it can be very tricky to be found.