Howto:Encrypt or Decrypt PBX user passwords

From innovaphone wiki
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

Applies To

This information applies to

  • all innovaphone PBX platforms, V6 and later


Abstract

Passwords of user objects in the PBX are saved in encrypted form in order to ensure confidentiality.
Sometimes it could be necessary to create user objects automatically without using the PBX's web gui.

This article describes some ways of doing it.

Creation of PBX User Config File Entries with Password

The password attribute of an user object must be written encrypted, while all other attributes are plain text.

Example user record from PBX config:

mod cmd FLASHDIR0 add-item 101
  (cn=Venus)
  (pbx=<user filter="normal" cd-filter="normal" busy-in="65535" pwd="a50c0b9263f673a778f671fbf9e4358c"/>)
  (node=root)
  (loc=.)
  (e164=224)
  (h323=venus)

The encrypted user password is in the pwd attribute.

  • The user password needs to be encrypted using the PBX key
  • The PBX key is automatically generated during activation of the PBX (random)
  • The PBX key can be found inside the _ADMIN_ object in encrypted form
  • The PBX key is encrypted using the PBX password
  • The PBX password has been configured by the administrator during activation of the PBX

In order to manually generate PBX user objects with passwords, you need

  • to know the PBX password
  • to determine the PBX key
  • to know the desired user password
  • a way to apply RC4 en/decryption

The encryption can be done with any standard RC4 implementation. For convenience, annotated PHP code is given below.

Getting the encrypted PBX Key

First Step is getting the PBX key from the key attribute of the _ADMIN_ object:

mod cmd FLASHDIR0 add-item 101
  (cn=_ADMIN_)
  (h323=pbx-admin)
  (pbx=<user pwd="a61e0ce0068273a778f671fbf9e4358c" key="566e2a2f1d259e4136046d5cbacaea9f"/>)

Encrypting the new User Password

The PBX password needs to be 16 byte zero-padded for encryption. PBX firmware prior to V9 hotfix7 has used 16 byte zero-padded user passwords for encryption. Later firmware uses 24 byte zero-padded user passwords for encryption. Please note that the encrypted (and stored) password ist he full buffer. However, the part following the terminating \0 byte in the clear password may be random. So if you create the crypted password as shown below, it may differ from the one found in the PBX configuration. It will work nevertheless.

To encrypt the user password, you can use the following PHP code. If you not want to use PHP, you can read the code annotation for details of the algorithm. You would then replace the user's pwd attribute with the new value computed.

http://localhost:8080/web/tools/config/config-local/config/init/encrypt-pbx-user-pw.php?pbxpw=pwd&pbxkey=566e2a2f1d259e4136046d5cbacaea9f&userpw=secret

encrypt-pbx-user-pw.php:

<?php

/*
 * encrypt PBX user passwords
 * call e.g. encrypt-pbx-user-pw.php?pbxpw=pwd&pbxkey=566e2a2f1d259e4136046d5cbacaea9f&userpw=secret
 */

require_once "classes/class.rc4crypt.php";

// utilities
function hexprint($bin, $nbytes = 0) {
    if ($nbytes == 0)
        $nbytes = strlen($bin);
    $r = "";
    for ($i = $nbytes; $i > 0; $i--)
        $r .= sprintf("%02x", ord($bin[$nbytes - $i]));
    return $r;
}

function tablerow(array $data, $type = "td") {
    print "<tr>";
    foreach ($data as $item)
        print "<$type>" . htmlspecialchars($item) . "</$type>";
    print "</tr>";
}

function table(array $data) {
    print "<table><thead>";
    tablerow(array_shift($data), "th");
    print "</thead>";
    print "<tbody>";
    foreach ($data as $row)
        tablerow($row);
    print "</tbody></table>";
}

$pbxKey = $_REQUEST['pbxkey'];  // pbx key as taken vom _ADMIN_'s key= attribute (hex-string)
$pbxPW = $_REQUEST['pbxpw'];    // clear text pbx password
$userpw = $_REQUEST['userpw'];  // user password in clear to encrypt 
$userpwlen = empty($_REQUEST['userpwlen']) ? 24 : 16;
// get crypt class
$crypt = new rc4crypt();
// convert admin key hex string to binary
$binkey = pack('H*', $pbxKey);
// convert pbx pw to rc4 seed (this is a 16byte input key)
$pbxPWKey = rc4crypt::make_pbx_key($pbxPW);
// convert user password to rc4 data buffer (length varies by firmware)
$pbxUserpwKey = rc4crypt::make_pbx_key($userpw, $userpwlen);

// decrypt the pbx key
$pbxKeyDecrypted = $crypt->decrypt($pbxPWKey, $binkey, false);

// encrypt the user password
$cryptedUserPW = $crypt->encrypt($pbxKeyDecrypted, $pbxUserpwKey, false);

// output
print "<body style='font-family: courier'>";
table(
        array(
            array("Item", "Value"),
            array("_ADMIN_'s key attribute (given)", $pbxKey),
            array("PBX Password in clear (given)", $pbxPW),
            array("PBX Password in hex", hexprint($pbxPW)),
            array("PBX Password hex zero filled", hexprint($pbxPWKey)),
            array("User Password (given)", $userpw),
            array("User Password hex zero filled", hexprint($pbxUserpwKey)),
            array("PBX key (decrypted)", hexprint($pbxKeyDecrypted)),
            array("User PW (encrypted)", hexprint($cryptedUserPW)),
        )
);
print "</body>";
?>

The RC4 encryption class:

<?php

/* vim: set expandtab shiftwidth=4 softtabstop=4 tabstop=4: */

/**
 * RC4Crypt 3.2
 *
 * RC4Crypt is a petite library that allows you to use RC4
 * encryption easily in PHP. It's OO and can produce outputs
 * in binary and hex.
 *
 * (C) Copyright 2006 Mukul Sabharwal [http://mjsabby.com]
 *     All Rights Reserved
 *
 * @link http://rc4crypt.devhome.org
 * @author Mukul Sabharwal <mjsabby@gmail.com>
 * @version $Id: class.rc4crypt.php,v 3.2 2006/03/10 05:47:24 mukul Exp $
 * @copyright Copyright &copy; 2006 Mukul Sabharwal
 * @license http://www.gnu.org/copyleft/gpl.html
 * @package RC4Crypt
 */

/**
 * RC4 Class
 * @package RC4Crypt
 */
class rc4crypt {
    
    /**
     * inno specific key creator for keys derived from user/password
     * @param string $user
     * @param string $password
     * @return string
     */
    static function make_key($user, $password) {
        // create special key format, 16bytes null padded user + 16 byets null padded password
        $key = $user;
        for ($i = strlen($user); $i < 16; $i++) {
            $key .= "\0";
        }
        $key .= $password;
        for ($i = strlen($password); $i < 16; $i++) {
            $key .= "\0";
        }
        return $key;
    }
    
    /**
     * inno specific key creator for keys derived from password only
     * @param string $pwd
     * @return string
     */
    function make_pbx_key($pwd, $size = 16) {
        // create special key format, 16bytes (default) null padded pwd
        $key = $pwd;
        for ($i = strlen($pwd); $i < $size; $i++) {
            $key .= "\0";
        }
        return $key;
    }
    
    /**
     * The symmetric encryption function
     *
     * @param string $pwd Key to encrypt with (can be binary of hex)
     * @param string $data Content to be encrypted
     * @param bool $ispwdHex Key passed is in hexadecimal or not
     * @access public
     * @return string
     */
    function encrypt ($pwd, $data, $ispwdHex = 0)
    {
        if ($ispwdHex)
            $pwd = @pack('H*', $pwd); // valid input, please!

        $key[] = '';
        $box[] = '';
        $cipher = '';

        $pwd_length = strlen($pwd);
        $data_length = strlen($data);

        for ($i = 0; $i < 256; $i++)
        {
            $key[$i] = ord($pwd[$i % $pwd_length]);
            $box[$i] = $i;
        }
        for ($j = $i = 0; $i < 256; $i++)
        {
            $j = ($j + $box[$i] + $key[$i]) % 256;
            $tmp = $box[$i];
            $box[$i] = $box[$j];
            $box[$j] = $tmp;
        }
        for ($a = $j = $i = 0; $i < $data_length; $i++)
        {
            $a = ($a + 1) % 256;
            $j = ($j + $box[$a]) % 256;
            $tmp = $box[$a];
            $box[$a] = $box[$j];
            $box[$j] = $tmp;
            $k = $box[(($box[$a] + $box[$j]) % 256)];
            $cipher .= chr(ord($data[$i]) ^ $k);
        }
        return $cipher;
    }
    /**
     * Decryption, recall encryption
     *
     * @param string $pwd Key to decrypt with (can be binary of hex)
     * @param string $data Content to be decrypted
     * @param bool $ispwdHex Key passed is in hexadecimal or not
     * @access public
     * @return string
     */
    function decrypt ($pwd, $data, $ispwdHex = 0)
    {
        return rc4crypt::encrypt($pwd, $data, $ispwdHex);
    }
}
?>

Notes

Do not mix-up the PBX password with the admin password!
The admin password is used together with the admin username to get access to the config gui of the device.
The admin username and password are set by default to "admin" and "ipxxxx" (depending on your device type).
The PBX password in opposite must always be configured manually during activation of the PBX.
Be sure of really knowing the correct PBX password.

NB: This procedure does not work for other passwords which are stored in VARS, such as e.g. the devices admin password (vars create CMD0/AUTH).

Ths method basically is only good for initial creation of user records, as uploading a modified config requires a re-boot of the PBX!

Encrypt and decrypt VAR values from config file with default admin password

The passwords stored in the config file of an innovaphone device could be also decrypted in similar way as PBX passwords, however this will work only for configs with default admin credentials (admin/ipxxx).

Instead of decrypting a PBX key, you have to create an encryption key from a combination of username and password:

$user = 'admin';
$pass = 'ip411';

// create binary string of encrypted VAR from hex
// vars create LDAPSRV0/AUTH pc 93e6f15d157217f4d0bfe4f0c6a3561b12d2e6
$cryptedPW = pack('H*', "93e6f15d157217f4d0bfe4f0c6a3561b12d2e6");

// get crypt class
$crypt = new rc4crypt();

// create key for decryption in proper format
$key = rc4crypt::make_key($user, $pass);
var_dump($key);

$decryptedPW = $crypt->decrypt($key, $cryptedPW, false);
var_dump($decryptedPW);

Setting the Password with SOAP's Admin() function

You can edit any PBX object with SOAP's Admin function. See Howto:Using the SOAP Admin Function for details.

Setting the Password like the Admin GUI does

Another option is to mimic the admin user GUI to set the password. See Howto:Effect arbitrary Configuration Changes using a HTTP Command Line Client or from an Update for details.

Related Articles