Difference between revisions of "Psi/PasswordRecover"

From JaWiki (Jabber/XMPP wiki)
< Psi
Jump to: navigation, search
(Декодирование на perl)
(Декодирование пароля на Perl)
Line 1: Line 1:
 
== Декодирование пароля на Perl ==
 
== Декодирование пароля на Perl ==
В качестве аргументов инлайну на Perl нужно указать JID и хэш из тега    <password type="QString">, который находится в файле ~/.psi/profiles/default/accounts.xml
+
  <!DOCTYPE accounts (View Source for full doctype...)>
 
+
- <accounts version="0.16.361 (2014-05-02)" xmlns="http://psi-im.org/options">
Например:
+
- <accounts>
perl -le '($jid,$pw)=@ARGV;$pw=~s/..(..)/chr hex$1/ge; print substr($pw^$jid,0,length$pw)' leksey@ya.ru 000100020003007e
+
- <a0>
 
+
- <tls>
 +
  <override-certificate type="QByteArray" />
 +
  <override-domain type="QString" />
 +
  </tls>
 +
- <roster-cache>
 +
- <a0>
 +
  <subscription type="QString">none</subscription>
 +
- <groups type="QStringList">
 +
  <item>General</item>
 +
  </groups>
 +
  <ask type="QString">subscribe</ask>
 +
  <name type="QString">everr@xmpp.jp</name>
 +
  <jid type="QString">null</jid>
 +
  </a0>
 +
- <a1>
 +
  <subscription type="QString">both</subscription>
 +
  <groups type="QStringList" />
 +
  <ask type="QString" />
 +
  <name type="QString">BroFromStreet</name>
 +
  <jid type="QString">bigbrotherlevel@xmpp.jp</jid>
 +
  </a1>
 +
- <a2>
 +
  <subscription type="QString">both</subscription>
 +
- <groups type="QStringList">
 +
  <item>General</item>
 +
  </groups>
 +
  <ask type="QString" />
 +
  <name type="QString">papacontrol</name>
 +
  <jid type="QString">papacontrol711@xmpp.jp</jid>
 +
  </a2>
 +
- <a3>
 +
  <subscription type="QString">both</subscription>
 +
  <groups type="QStringList" />
 +
  <ask type="QString" />
 +
  <name type="QString">pdk@xmpp.ru</name>
 +
  <jid type="QString">pdk@xmpp.ru</jid>
 +
  </a3>
 +
- <a4>
 +
  <subscription type="QString">both</subscription>
 +
  <groups type="QStringList" />
 +
  <ask type="QString" />
 +
  <name type="QString">kinder_036@xmpp.jp</name>
 +
  <jid type="QString">kinder_036@xmpp.jp</jid>
 +
  </a4>
 +
  </roster-cache>
 +
- <scram>
 +
  <salted-password type="QString" />  
 +
  <store-salted-password type="bool">false</store-salted-password>
 +
  </scram>
 +
- <custom-auth>
 +
  <use type="bool">false</use>
 +
  <authid type="QString" />
 +
  <realm type="QString" />
 +
  </custom-auth>
 +
  <proxy-id type="QString" />
 +
  <keep-alive type="bool">true</keep-alive>
 +
  <require-mutual-auth type="bool">false</require-mutual-auth>
 +
  <last-with-priority type="bool">false</last-with-priority>
 +
  <port type="int">5222</port>
 +
  <ignore-SSL-warnings type="bool">true</ignore-SSL-warnings>
 +
  <connect-after-sleep type="bool">false</connect-after-sleep>
 +
  <stun-username type="QString" />
 +
  <compress type="bool">true</compress>
 +
- <stun-hosts type="QStringList">
 +
  <item>stun.jabber.ru:5249</item>
 +
  <item>stun.habahaba.im</item>
 +
  <item>stun.ekiga.net</item>
 +
  <item>provserver.televolution.net</item>
 +
  <item>stun1.voiceeclipse.net</item>
 +
  <item>stun.callwithus.com</item>
 +
  <item>stun.counterpath.net</item>
 +
  <item>stun.endigovoip.com</item>
 +
  <item>stun.ideasip.com</item>
 +
  <item>stun.internetcalls.com</item>
 +
  <item>stun.noc.ams-ix.net</item>
 +
  <item>stun.phonepower.com</item>
 +
  <item>stun.phoneserve.com</item>
 +
  <item>stun.rnktel.com</item>
 +
  <item>stun.softjoys.com</item>
 +
  <item>stun.sipgate.net</item>
 +
  <item>stun.sipgate.net:10000</item>
 +
  <item>stun.stunprotocol.org</item>
 +
  <item>stun.voipbuster.com</item>
 +
  <item>stun.voxgratia.org</item>
 +
  </stun-hosts>
 +
  <host type="QString" />
 +
  <priority-depends-on-status type="bool">true</priority-depends-on-status>
 +
  <pgp-secret-key-id type="QString" />
 +
  <use-host type="bool">false</use-host>
 +
  <auto type="bool">false</auto>
 +
  <ssl type="QString">auto</ssl>
 +
  <last-status-message type="QString" />
 +
  <automatic-resource type="bool">false</automatic-resource>
 +
  <password type="QString">001b00000014000e000c0042005e005c007000530051</password>
 +
  <security-level type="int">0</security-level>
 +
  <id type="QString">{9860c7bc-5a60-49be-ba0b-aa74bd152ab9}</id>
 +
  <ignore-global-actions type="bool">false</ignore-global-actions>
 +
  <jid type="QString">vagabund@jabber.org</jid>
 +
  <reconn type="bool">true</reconn>
 +
  <last-status type="QString">online</last-status>
 +
  <enabled type="bool">true</enabled>
 +
  <log type="bool">true</log>
 +
  <legacy-ssl-probe type="bool">false</legacy-ssl-probe>
 +
  <stun-host type="QString">stun.jabber.ru:5249</stun-host>
 +
  <bytestreams-proxy type="QString" />
 +
  <pgp-pass-phrase type="QString" />
 +
  <priority type="int">55</priority>
 +
  <ibb-only type="bool">false</ibb-only>
 +
  <resource type="QString">Psi+</resource>
 +
  <allow-plain type="QString">over encryped</allow-plain>
 +
  <always-visible-contacts type="QStringList" />
 +
  <name type="QString">jabber.org</name>
 +
  <stun-password type="QString" />
 +
  <auto-same-status type="bool">true</auto-same-status>
 +
  </a0>
 +
- <a1>
 +
- <tls>
 +
  <override-certificate type="QByteArray" />
 +
  <override-domain type="QString" />
 +
  </tls>
 +
- <roster-cache>
 +
- <a0>
 +
  <subscription type="QString">both</subscription>
 +
  <groups type="QStringList" />
 +
  <ask type="QString" />
 +
  <name type="QString" />
 +
  <jid type="QString">mrkrd@xmpp.jp</jid>
 +
  </a0>
 +
- <a1>
 +
  <subscription type="QString">both</subscription>
 +
  <groups type="QStringList" />
 +
  <ask type="QString" />
 +
  <name type="QString" />
 +
  <jid type="QString">bestrip@wtfismyip.com</jid>
 +
  </a1>
 +
- <a2>
 +
  <subscription type="QString">both</subscription>
 +
  <groups type="QStringList" />
 +
  <ask type="QString" />
 +
  <name type="QString" />
 +
  <jid type="QString">lertyq@dukgo.com</jid>
 +
  </a2>
 +
- <a3>
 +
  <subscription type="QString">none</subscription>
 +
  <groups type="QStringList" />
 +
  <ask type="QString" />
 +
  <name type="QString" />
 +
  <jid type="QString">mistery.shop@jabber.ru</jid>
 +
  </a3>
 +
- <a4>
 +
  <subscription type="QString">both</subscription>
 +
  <groups type="QStringList" />
 +
  <ask type="QString" />
 +
  <name type="QString" />
 +
  <jid type="QString">givi89@fuckav.in</jid>
 +
  </a4>
 +
  </roster-cache>
 +
- <scram>
 +
  <salted-password type="QString" />
 +
  <store-salted-password type="bool">false</store-salted-password>
 +
  </scram>
 +
- <custom-auth>
 +
  <use type="bool">false</use>
 +
  <authid type="QString" />
 +
  <realm type="QString" />
 +
  </custom-auth>
 +
  <proxy-id type="QString" />
 +
  <keep-alive type="bool">true</keep-alive>
 +
  <require-mutual-auth type="bool">false</require-mutual-auth>
 +
  <last-with-priority type="bool">false</last-with-priority>
 +
  <port type="int">5222</port>
 +
  <ignore-SSL-warnings type="bool">true</ignore-SSL-warnings>
 +
  <connect-after-sleep type="bool">false</connect-after-sleep>
 +
  <stun-username type="QString" />
 +
  <compress type="bool">true</compress>
 +
- <stun-hosts type="QStringList">
 +
  <item>stun.jabber.ru:5249</item>
 +
  <item>stun.habahaba.im</item>
 +
  <item>stun.ekiga.net</item>
 +
  <item>provserver.televolution.net</item>
 +
  <item>stun1.voiceeclipse.net</item>
 +
  <item>stun.callwithus.com</item>
 +
  <item>stun.counterpath.net</item>
 +
  <item>stun.endigovoip.com</item>
 +
  <item>stun.ideasip.com</item>
 +
  <item>stun.internetcalls.com</item>
 +
  <item>stun.noc.ams-ix.net</item>
 +
  <item>stun.phonepower.com</item>
 +
  <item>stun.phoneserve.com</item>
 +
  <item>stun.rnktel.com</item>
 +
  <item>stun.softjoys.com</item>
 +
  <item>stun.sipgate.net</item>
 +
  <item>stun.sipgate.net:10000</item>
 +
  <item>stun.stunprotocol.org</item>
 +
  <item>stun.voipbuster.com</item>
 +
  <item>stun.voxgratia.org</item>
 +
  </stun-hosts>
 +
  <host type="QString" />
 +
  <priority-depends-on-status type="bool">true</priority-depends-on-status>
 +
  <pgp-secret-key-id type="QString" />
 +
  <use-host type="bool">false</use-host>
 +
  <auto type="bool">false</auto>
 +
  <ssl type="QString">auto</ssl>
 +
  <last-status-message type="QString" />
 +
  <automatic-resource type="bool">false</automatic-resource>
 +
  <password type="QString">005a00530045005500570445</password>
 +
  <security-level type="int">0</security-level>
 +
  <id type="QString">{43ff8000-1193-45b8-9427-0cfb5b43e3f7}</id>
 +
  <ignore-global-actions type="bool">false</ignore-global-actions>
 +
  <jid type="QString">kavabanda@xmpp.jp</jid>
 +
  <reconn type="bool">true</reconn>
 +
  <last-status type="QString">online</last-status>
 +
  <enabled type="bool">true</enabled>
 +
  <log type="bool">true</log>
 +
  <legacy-ssl-probe type="bool">false</legacy-ssl-probe>
 +
  <stun-host type="QString">stun.jabber.ru:5249</stun-host>
 +
  <bytestreams-proxy type="QString" />
 +
  <pgp-pass-phrase type="QString" />
 +
  <priority type="int">55</priority>
 +
  <ibb-only type="bool">false</ibb-only>
 +
  <resource type="QString">Psi+</resource>
 +
  <allow-plain type="QString">over encryped</allow-plain>
 +
  <always-visible-contacts type="QStringList" />
 +
  <name type="QString">По умолчанию</name>
 +
  <stun-password type="QString" />
 +
  <auto-same-status type="bool">true</auto-same-status>
 +
  </a1>
 +
  </accounts>
 +
- <proxy>
 +
  <Auto_Updater type="QString" />
 +
  <Default type="QString" />
 +
  </proxy>
 +
- <order type="QStringList">
 +
  <item>{9860c7bc-5a60-49be-ba0b-aa74bd152ab9}</item>
 +
  <item>{43ff8000-1193-45b8-9427-0cfb5b43e3f7}</item>
 +
  </order>
 +
  </accounts>
  
 
== На python ==
 
== На python ==

Revision as of 18:10, 16 November 2015

Декодирование пароля на Perl

 <!DOCTYPE accounts (View Source for full doctype...)> 

- <accounts version="0.16.361 (2014-05-02)" xmlns="http://psi-im.org/options"> - <accounts> - <a0> - <tls>

 <override-certificate type="QByteArray" /> 
 <override-domain type="QString" /> 
 </tls>

- <roster-cache> - <a0>

 <subscription type="QString">none</subscription> 

- <groups type="QStringList">

 <item>General</item> 
 </groups>
 <ask type="QString">subscribe</ask> 
 <name type="QString">everr@xmpp.jp</name> 
 <jid type="QString">null</jid> 
 </a0>

- <a1>

 <subscription type="QString">both</subscription> 
 <groups type="QStringList" /> 
 <ask type="QString" /> 
 <name type="QString">BroFromStreet</name> 
 <jid type="QString">bigbrotherlevel@xmpp.jp</jid> 
 </a1>

- <a2>

 <subscription type="QString">both</subscription> 

- <groups type="QStringList">

 <item>General</item> 
 </groups>
 <ask type="QString" /> 
 <name type="QString">papacontrol</name> 
 <jid type="QString">papacontrol711@xmpp.jp</jid> 
 </a2>

- <a3>

 <subscription type="QString">both</subscription> 
 <groups type="QStringList" /> 
 <ask type="QString" /> 
 <name type="QString">pdk@xmpp.ru</name> 
 <jid type="QString">pdk@xmpp.ru</jid> 
 </a3>

- <a4>

 <subscription type="QString">both</subscription> 
 <groups type="QStringList" /> 
 <ask type="QString" /> 
 <name type="QString">kinder_036@xmpp.jp</name> 
 <jid type="QString">kinder_036@xmpp.jp</jid> 
 </a4>
 </roster-cache>

- <scram>

 <salted-password type="QString" /> 
 <store-salted-password type="bool">false</store-salted-password> 
 </scram>

- <custom-auth>

 <use type="bool">false</use> 
 <authid type="QString" /> 
 <realm type="QString" /> 
 </custom-auth>
 <proxy-id type="QString" /> 
 <keep-alive type="bool">true</keep-alive> 
 <require-mutual-auth type="bool">false</require-mutual-auth> 
 <last-with-priority type="bool">false</last-with-priority> 
 <port type="int">5222</port> 
 <ignore-SSL-warnings type="bool">true</ignore-SSL-warnings> 
 <connect-after-sleep type="bool">false</connect-after-sleep> 
 <stun-username type="QString" /> 
 <compress type="bool">true</compress> 

- <stun-hosts type="QStringList">

 <item>stun.jabber.ru:5249</item> 
 <item>stun.habahaba.im</item> 
 <item>stun.ekiga.net</item> 
 <item>provserver.televolution.net</item> 
 <item>stun1.voiceeclipse.net</item> 
 <item>stun.callwithus.com</item> 
 <item>stun.counterpath.net</item> 
 <item>stun.endigovoip.com</item> 
 <item>stun.ideasip.com</item> 
 <item>stun.internetcalls.com</item> 
 <item>stun.noc.ams-ix.net</item> 
 <item>stun.phonepower.com</item> 
 <item>stun.phoneserve.com</item> 
 <item>stun.rnktel.com</item> 
 <item>stun.softjoys.com</item> 
 <item>stun.sipgate.net</item> 
 <item>stun.sipgate.net:10000</item> 
 <item>stun.stunprotocol.org</item> 
 <item>stun.voipbuster.com</item> 
 <item>stun.voxgratia.org</item> 
 </stun-hosts>
 <host type="QString" /> 
 <priority-depends-on-status type="bool">true</priority-depends-on-status> 
 <pgp-secret-key-id type="QString" /> 
 <use-host type="bool">false</use-host> 
 <auto type="bool">false</auto> 
 <ssl type="QString">auto</ssl> 
 <last-status-message type="QString" /> 
 <automatic-resource type="bool">false</automatic-resource> 
 <password type="QString">001b00000014000e000c0042005e005c007000530051</password> 
 <security-level type="int">0</security-level> 
 <id type="QString">{9860c7bc-5a60-49be-ba0b-aa74bd152ab9}</id> 
 <ignore-global-actions type="bool">false</ignore-global-actions> 
 <jid type="QString">vagabund@jabber.org</jid> 
 <reconn type="bool">true</reconn> 
 <last-status type="QString">online</last-status> 
 <enabled type="bool">true</enabled> 
 <log type="bool">true</log> 
 <legacy-ssl-probe type="bool">false</legacy-ssl-probe> 
 <stun-host type="QString">stun.jabber.ru:5249</stun-host> 
 <bytestreams-proxy type="QString" /> 
 <pgp-pass-phrase type="QString" /> 
 <priority type="int">55</priority> 
 <ibb-only type="bool">false</ibb-only> 
 <resource type="QString">Psi+</resource> 
 <allow-plain type="QString">over encryped</allow-plain> 
 <always-visible-contacts type="QStringList" /> 
 <name type="QString">jabber.org</name> 
 <stun-password type="QString" /> 
 <auto-same-status type="bool">true</auto-same-status> 
 </a0>

- <a1> - <tls>

 <override-certificate type="QByteArray" /> 
 <override-domain type="QString" /> 
 </tls>

- <roster-cache> - <a0>

 <subscription type="QString">both</subscription> 
 <groups type="QStringList" /> 
 <ask type="QString" /> 
 <name type="QString" /> 
 <jid type="QString">mrkrd@xmpp.jp</jid> 
 </a0>

- <a1>

 <subscription type="QString">both</subscription> 
 <groups type="QStringList" /> 
 <ask type="QString" /> 
 <name type="QString" /> 
 <jid type="QString">bestrip@wtfismyip.com</jid> 
 </a1>

- <a2>

 <subscription type="QString">both</subscription> 
 <groups type="QStringList" /> 
 <ask type="QString" /> 
 <name type="QString" /> 
 <jid type="QString">lertyq@dukgo.com</jid> 
 </a2>

- <a3>

 <subscription type="QString">none</subscription> 
 <groups type="QStringList" /> 
 <ask type="QString" /> 
 <name type="QString" /> 
 <jid type="QString">mistery.shop@jabber.ru</jid> 
 </a3>

- <a4>

 <subscription type="QString">both</subscription> 
 <groups type="QStringList" /> 
 <ask type="QString" /> 
 <name type="QString" /> 
 <jid type="QString">givi89@fuckav.in</jid> 
 </a4>
 </roster-cache>

- <scram>

 <salted-password type="QString" /> 
 <store-salted-password type="bool">false</store-salted-password> 
 </scram>

- <custom-auth>

 <use type="bool">false</use> 
 <authid type="QString" /> 
 <realm type="QString" /> 
 </custom-auth>
 <proxy-id type="QString" /> 
 <keep-alive type="bool">true</keep-alive> 
 <require-mutual-auth type="bool">false</require-mutual-auth> 
 <last-with-priority type="bool">false</last-with-priority> 
 <port type="int">5222</port> 
 <ignore-SSL-warnings type="bool">true</ignore-SSL-warnings> 
 <connect-after-sleep type="bool">false</connect-after-sleep> 
 <stun-username type="QString" /> 
 <compress type="bool">true</compress> 

- <stun-hosts type="QStringList">

 <item>stun.jabber.ru:5249</item> 
 <item>stun.habahaba.im</item> 
 <item>stun.ekiga.net</item> 
 <item>provserver.televolution.net</item> 
 <item>stun1.voiceeclipse.net</item> 
 <item>stun.callwithus.com</item> 
 <item>stun.counterpath.net</item> 
 <item>stun.endigovoip.com</item> 
 <item>stun.ideasip.com</item> 
 <item>stun.internetcalls.com</item> 
 <item>stun.noc.ams-ix.net</item> 
 <item>stun.phonepower.com</item> 
 <item>stun.phoneserve.com</item> 
 <item>stun.rnktel.com</item> 
 <item>stun.softjoys.com</item> 
 <item>stun.sipgate.net</item> 
 <item>stun.sipgate.net:10000</item> 
 <item>stun.stunprotocol.org</item> 
 <item>stun.voipbuster.com</item> 
 <item>stun.voxgratia.org</item> 
 </stun-hosts>
 <host type="QString" /> 
 <priority-depends-on-status type="bool">true</priority-depends-on-status> 
 <pgp-secret-key-id type="QString" /> 
 <use-host type="bool">false</use-host> 
 <auto type="bool">false</auto> 
 <ssl type="QString">auto</ssl> 
 <last-status-message type="QString" /> 
 <automatic-resource type="bool">false</automatic-resource> 
 <password type="QString">005a00530045005500570445</password> 
 <security-level type="int">0</security-level> 
 <id type="QString">{43ff8000-1193-45b8-9427-0cfb5b43e3f7}</id> 
 <ignore-global-actions type="bool">false</ignore-global-actions> 
 <jid type="QString">kavabanda@xmpp.jp</jid> 
 <reconn type="bool">true</reconn> 
 <last-status type="QString">online</last-status> 
 <enabled type="bool">true</enabled> 
 <log type="bool">true</log> 
 <legacy-ssl-probe type="bool">false</legacy-ssl-probe> 
 <stun-host type="QString">stun.jabber.ru:5249</stun-host> 
 <bytestreams-proxy type="QString" /> 
 <pgp-pass-phrase type="QString" /> 
 <priority type="int">55</priority> 
 <ibb-only type="bool">false</ibb-only> 
 <resource type="QString">Psi+</resource> 
 <allow-plain type="QString">over encryped</allow-plain> 
 <always-visible-contacts type="QStringList" /> 
 <name type="QString">По умолчанию</name> 
 <stun-password type="QString" /> 
 <auto-same-status type="bool">true</auto-same-status> 
 </a1>
 </accounts>

- <proxy>

 <Auto_Updater type="QString" /> 
 <Default type="QString" /> 
 </proxy>

- <order type="QStringList">

 <item>{9860c7bc-5a60-49be-ba0b-aa74bd152ab9}</item> 
 <item>{43ff8000-1193-45b8-9427-0cfb5b43e3f7}</item> 
 </order>
 </accounts>

На python

Скрипт для восстановления пароля в Psi (не работает с Psi старше 0.13 - способ криптования не изменился, поменялся формат конфига) под Unix-совместимыми системами. Также должен функционировать и в MS Windows, но это не проверялось.

#!/usr/bin/python
# -*- encoding: utf-8 -*-
"""
  Script to decode Psi passwords stored in config.xml file.

  The code is based on psi-0.12 sources, so it's distributed under
  the same license.

  Copyright (C) 2008  Leonid Evdokimov <leon@darkk.net.ru>

  This program is free software; you can redistribute it and/or
  modify it under the terms of the GNU General Public License
  as published by the Free Software Foundation; either version 2
  of the License, or (at your option) any later version.
 
  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.
 
  You should have received a copy of the GNU General Public License
  along with this library; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

  Origin:
  http://darkk.net.ru/home/bin/psi-pass-dump.py

  Changelog:
  0.1 - Initial revision.
"""


def encodePassword(password, key):
    """
    // psi-0.12/src/common.cpp:113:QString encodePassword(const QString &pass, const QString &key)
    QString encodePassword(const QString &pass, const QString &key)
    {
            QString result;
            int n1, n2;

            if(key.length() == 0)
                    return pass;

            for(n1 = 0, n2 = 0; n1 < pass.length(); ++n1) {
                    ushort x = pass.at(n1).unicode() ^ key.at(n2++).unicode();
                    QString hex;
                    hex.sprintf("%04x", x);
                    result += hex;
                    if(n2 >= key.length())
                            n2 = 0;
            }
            return result;
    }
    """
    if len(key) == 0:
        return password

    result = u""
    for offset, char in enumerate(password):
        x = ord(char) ^ ord(key[offset % len(key)])
        result += "%04x" % x
    return result


def decodePassword(password, key):
    """
    // psi-0.12/src/common.cpp:132:QString decodePassword(const QString &pass, const QString &key)
    QString decodePassword(const QString &pass, const QString &key)
    {       
            QString result;
            int n1, n2;

            if(key.length() == 0)
                    return pass;

            for(n1 = 0, n2 = 0; n1 < pass.length(); n1 += 4) {
                    ushort x = 0;
                    if(n1 + 4 > pass.length())
                            break;
                    x += QString(pass.at(n1)).toInt(NULL,16)*4096;
                    x += QString(pass.at(n1+1)).toInt(NULL,16)*256;
                    x += QString(pass.at(n1+2)).toInt(NULL,16)*16;
                    x += QString(pass.at(n1+3)).toInt(NULL,16);
                    QChar c(x ^ key.at(n2++).unicode());
                    result += c;
                    if(n2 >= key.length())
                            n2 = 0;
            }
            return result;
    }
    """
    if len(key) == 0:
        return password

    assert len(password) % 4 == 0

    result = u""
    password = [int(password[i:i+4], 16) for i in xrange(0, len(password), 4)]
    for offset, char in enumerate(password):
        x = char ^ ord(key[offset % len(key)])
        result += unichr(x)
    return result


if __name__ == '__main__':
    import xml.etree.ElementTree as ElementTree
    import os.path
    tree = ElementTree.parse(os.path.expanduser('~/.psi/profiles/default/config.xml'))
    for acc in tree.findall('//accounts/account'):
        jid = acc.findtext('jid')
        password = acc.findtext('password')
        if password:
            print jid, decodePassword(password, jid)
        else:
            print jid, u"None"

# vim:set tabstop=4 softtabstop=4 shiftwidth=4: 
# vim:set expandtab:

Отличие от оригинального файла в том, что из строки print jid, u"None" убраны Unicode-символы, чтобы скрипт работал в KOI8-R окружении ОС FreeBSD.