Separate Delivery Encoding Class

// will encode mp3 / wav / jpeg / any media files into Separate Delivery DRM encoding
// http://www.openmobilealliance.org/Technical/release_program/drm_v1_0.aspx
// require mcrypt module

<?php
class SeparateDelivery
{
    var $version = 1;
    var $content_type = '';
    var $content_id = '';
    var $headers = 'Encryption-Method: AES128CBC;padding=RFC2630';

    function encode($content_id, $content_type, $data, $key='', $headers='')
    {
        $this->content_id = $content_id;
        $this->content_type = $content_type;
        if ($headers)
        {
            $this->headers .= "\r\n" . $headers;
        }
        $this->initkey($key);
        $data = $this->encrypt($data);
        
        $output = pack('CCC', $this->version, strlen($this->content_type), strlen($this->content_id));
        $output .= $this->content_type;
        $output .= $this->content_id;
        $output .= $this->pack_uintvar(strlen($this->headers));
        $output .= $this->pack_uintvar(strlen($data));
        $output .= $this->headers;
        $output .= $data;
        
        return $output;
    }

    function pack_uintvar($bval)
    {
        $pck = '';
        do
        {
            $sept = $bval & 0x7F;
            $bval = $bval >> 7;
            $pck = pack('C', $sept | ((strlen($pck) > 0) ? 0x80 : 0) ) . $pck;
        } 
        while ($bval > 0);
        return $pck;
    }

    function initkey($key='') 
    {
        if (!isset($this->key))
        {
            $this->key = '';
            $keysize = mcrypt_module_get_algo_key_size(MCRYPT_RIJNDAEL_128);
            if (($keysize > 0) && ($td = mcrypt_module_open(MCRYPT_RIJNDAEL_256, '', MCRYPT_MODE_CBC, ''))) 
            {
                $keysize = 16;
                while (strlen($key) < $keysize) 
                {
                    $key .= mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
                }
                mcrypt_module_close($td);
                $key = substr($key, 0, $keysize);
                $this->key = $key;
            }
        }
        return $this->key;
    }
    
    function encrypt($data) 
    {
        $td = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');
        $this->iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
        mcrypt_generic_init($td, $this->key, $this->iv);

        // padding
        $bs = mcrypt_enc_get_block_size($td);
        $plen = $bs - (strlen($data) % $bs);
        for($i = 0; $i < $plen; $i++)
            $data .= pack('C', $plen);

        $encrypted_data = $this->iv.mcrypt_generic($td, $data);
        mcrypt_generic_deinit($td);
        mcrypt_module_close($td);
        return $encrypted_data;
    }

    function decrypt($data) 
    {
        $td = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');
        $iv_length = mcrypt_enc_get_iv_size($td);

        $this->iv = substr($data, 0, $iv_length);
        $data = substr($data, $iv_length);

        mcrypt_generic_init($td, $this->key, $this->iv);
        $decrypted_data = mdecrypt_generic($td, $data);
        mcrypt_generic_deinit($td);
        mcrypt_module_close($td);

        // remove padding
        $dataLen = strlen($decrypted_data);
        $paddingLength = substr($decrypted_data, $dataLen - 1, 1);
        $decrypted_data = substr($decrypted_data, 0, $dataLen - ord($paddingLength));

        return $decrypted_data;
    }
    
    function hex_dump($data)
    {
        $hexi = '';
        $i = 0;
        while ($i < strlen($data))
        {
            $hexi .= sprintf("%02X", ord($data{$i}));
            $i++;
        }
        
        return $hexi;
    }
}
?>

// example

<?php

$sd = new SeparateDelivery;
$result = $sd->encode('cid:ferdhie@id-snippet.com', 'image/jpeg', 
    file_get_contents('test.jpg'), 
    base64_decode('Lsaip8QiFAdSfevcR8GzIA=='));

$fp = fopen('test2.dcf', 'wb');
fputs($fp, $result);
fclose($fp);

?>

0 Comments

Post A Comment