Psi/PasswordRecover
Декодирование пароля на 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.