«О Царстве Теней я могу сказать только одно: есть реальность и есть её Тень; в этом суть всего. В реальном Мире существует лишь Амбер, реальный город на реальной Земле, в котором собрано всё. А Царство Теней — лишь бесконечность ирреальности. Здесь тоже можно обнаружить всё — но то будут тени, искажённое отражение реальности. Царство Теней окружает Амбер со всех сторон. А за его пределами царит хаос. На пути из Амбера в Царство Хаоса возможно всё.»
Роджер Желязны. «Девять принцев Амбера»
Всё началось с нeoбxодимocти работать с одним и тем же ключом на etoken c разных, значительно удалённых друг от друга рабочих мест (USB Over IP ради пары токенов дороговато будет) и моего большого желания открыть этот закрытый мир. Мне попалась работа habr.com/post/276057 за что её автору большой респект, в моём проекте использована значительная часть отреверсеных им функций (код ведь открытый). Правда как выяснилось всё что работает с etsdk.dll работает только с синими рыбками. Поэтому для JaCarta новые функции пришлось писать заново, а часть отредактировать.
В результате долгих изысканий появился JaCarta Editor — программа показывающая и позволяющая редактировать сущности (именно так в официальной документации называют объекты файловой системы токенов, видимо намекая на их эфемерность и ирреальность) на токенах от Аладдина, в том числе самых современных.
Аналогичное приложение для Rutoken есть в открытом доступе в составе Rutoken SDK (Rutoken Editor), но для Аладдина, по крайней мере в открытом доступе нет, хотя лет 15 назад, судя по документации которую удалось найти в интернете, такое было (ETEditor).
Программа написана на Autoit, тестировалась с EToken PRO Java 72 K, JaCarta LT, JaCarta Pro, JaCarta ГОСТ-2.
Программа не будет работать, если на компьютере установлены драйвера Rutoken (требуется чтобы EToken или Ja Carta имели номер ридера 0).
По этой же причине для корректной работы должен быть подключен только один токен.
Скрипт использует системные вызовы Window$, и тестировался только с этим семейством ОС.
Для работы требуется установка «Единого клиента JaCarta» (бесплатно скачивается с сайта производителя), при установке которого в системную папку windows устанавливается в том числе и значительно более новая версия etsdk.dll а также jcFS.dll содержащая функции JaCarta File System (очень похожие на те что в etsdk.dll, но в jcFS появилось значительно больше функций без которых работа с некоторыми современными джакартами, например ГОСТ-2, будет невозможна). При установленном Едином клиенте искать и ложить в папку с программой эту dll естественно не нужно, в ином случае при установленном драйвере конкретного вида токена эта dll должна быть в папке с программой.
Все функции jcFS подробно описаны на сайте производителя, но тем не менее некоторые параметры этих функций пришлось подбирать экспериментально.
Для того, чтобы получить доступ к корневой директории токена необходимо вызвать функцию ETRootDirOpen или JCRootDirOpen (что одинаково, так как первая в dll вызывает вторую, это справедливо почти для всех функций, но есть несколько исключений) с идентификатором вендора равным 0 (константы типа 0xF007 позволят увидеть только отдельные директории в основном старых eToken на которых хранятся банковские ключи сгенерированные с помощью утилит типа PKIAdmin и MessagePRO).
Следующей важной особенностью современных джакарт является необходимость знать id апплета который установлен на токене, за это отвечает функция JCSelectApplet.
У старых токенов обычно есть апплет по умолчанию и вызов этой функции специально не требуется, но у новых и относительно новых джакарт без знания id апплета дальнейшая работа становится невозможной. Вызов всех функций получающих информацию от токена в этом случае возвращает False. В моём проекте в этом случае реализован двуступенчатый брутфорс (токен отзывается всегда на два id, но работает из них только один) id и дальнейшеая работа с нужным значением.
Вся информация выводится в окно вывода расположенное под деревом директорий.
Реализован ввод пин кода, выводится также информация об оставшихся попытках его ввода.
Выводится содержание директорий и краткие сведения о файлах: имя, является ли файл приватной информацией закрытой пин кодом — буква p: (ноль после неё файл публичный, единица приватный) и размер файла в байтах после «s:». Файл открывается по двойному клику.
Можно просмотреть и при необходимости скопировать в буфер содержимое файлов токена в шестнадцатеричном виде или сохранить в бинарном виде на компьютер.
Можно также изменить содержимое файла и выбрать в меню «Сохранить изменения» (предварительно должен быть введён пин код, если не был введён, то будет выведено соответствующее сообщение, в этом случае отредактированные данные можно выделить и скопировать в буфер обмена).
Для удаления файла необходимо его выделить и нажать «Удалить», после чего появится окно для подтверждения.
У JaCarta File System есть занятная особенность, которая пристутствует на всех токенах которые я тестировал. Если создать на токене директорию или несколько директорий без файлов, при следующей сессии работы с токеном они исчезнут, видимо таким образом файловая система заботится о сохранении объёма памяти токена и чистит от всякого мусора.
Поэтому при нажатии в программе кнопки «Создать» создаётся сразу цепочка из директории или двух директорий и файла. Глубина вложенности директорий в программе — две, не считая корневую. В корневой директории можно создавать только директории, но не файлы.
Перед созданием, редактирование или удалением сущностей необходимо ввести пин код.
Очень важное замечание об именах директорий!
На токенах, где содержимое создано средствами производителя вы никогда не встретите директорий с одинаковыми именами, где бы они не были. Это связано с особенностями файловой системы.
Предположим, у нас на токене есть следующая сущность: //0001/A001/0008 (то есть в корневой директории находится папка 0001, в ней папка А001, а в ней файл 0008) и мы создаём на токене новую сущность: //СС00/0001/1010. При обращении к файлу 1010 начнётся поиск директории 0001, которая находится в корне и будет найдена первой, но такого файла в ней нет. В результате функция возвращает False и cущность становится потерянной, как либо обратиться к ней и удалить тоже нельзя. Поможет только инициализация токена.
Особое замечаеме про EToken PRO и JA Carta Pro, отличие у которых только во внешнем виде, у них в корневой директории находятся системные файлы (именно они показаны на скрине), в одном из которых хранится судя по всему хэш пин кода, изменение этих файлов приводит к тому что авторизация становится невозможной (пин код становится неверным) и после этого поможет только инициализация.
Относительно закрытых ключей удалось установить следующее: если на токене хранится контейнер, созданный сторонним криптопровайдером, например CryptoPro, то всё его содержимое, включая закрытые ключи будет доступно, это просто флэшка с пин кодом (что и показано на картинке). Если же ключевая пара была сгенерирована на борту токена средствами PKCS11, то будут доступны только сертификат и открытый ключ.
Поскольку это экспериментальная программа я не рекомендую использовать её с токенами содержащими действующие ключи ЭЦП, все операции выполняются на страх и риск экспериментирующего. Особенно это касается создания новых сущностей, в ряде случаев результат труднопредсказуем.
Вся информация для создания программы получена из открытых источников, цель её создания чисто исследовательская.
Собственно скрипт
Источники информации
eToken Developer’s Guide Version 3.50 (декабрь 2003)
Роджер Желязны. «Девять принцев Амбера»
Всё началось с нeoбxодимocти работать с одним и тем же ключом на etoken c разных, значительно удалённых друг от друга рабочих мест (USB Over IP ради пары токенов дороговато будет) и моего большого желания открыть этот закрытый мир. Мне попалась работа habr.com/post/276057 за что её автору большой респект, в моём проекте использована значительная часть отреверсеных им функций (код ведь открытый). Правда как выяснилось всё что работает с etsdk.dll работает только с синими рыбками. Поэтому для JaCarta новые функции пришлось писать заново, а часть отредактировать.
В результате долгих изысканий появился JaCarta Editor — программа показывающая и позволяющая редактировать сущности (именно так в официальной документации называют объекты файловой системы токенов, видимо намекая на их эфемерность и ирреальность) на токенах от Аладдина, в том числе самых современных.
Аналогичное приложение для Rutoken есть в открытом доступе в составе Rutoken SDK (Rutoken Editor), но для Аладдина, по крайней мере в открытом доступе нет, хотя лет 15 назад, судя по документации которую удалось найти в интернете, такое было (ETEditor).
Программа написана на Autoit, тестировалась с EToken PRO Java 72 K, JaCarta LT, JaCarta Pro, JaCarta ГОСТ-2.
Программа не будет работать, если на компьютере установлены драйвера Rutoken (требуется чтобы EToken или Ja Carta имели номер ридера 0).
По этой же причине для корректной работы должен быть подключен только один токен.
Скрипт использует системные вызовы Window$, и тестировался только с этим семейством ОС.
Для работы требуется установка «Единого клиента JaCarta» (бесплатно скачивается с сайта производителя), при установке которого в системную папку windows устанавливается в том числе и значительно более новая версия etsdk.dll а также jcFS.dll содержащая функции JaCarta File System (очень похожие на те что в etsdk.dll, но в jcFS появилось значительно больше функций без которых работа с некоторыми современными джакартами, например ГОСТ-2, будет невозможна). При установленном Едином клиенте искать и ложить в папку с программой эту dll естественно не нужно, в ином случае при установленном драйвере конкретного вида токена эта dll должна быть в папке с программой.
Все функции jcFS подробно описаны на сайте производителя, но тем не менее некоторые параметры этих функций пришлось подбирать экспериментально.
Для того, чтобы получить доступ к корневой директории токена необходимо вызвать функцию ETRootDirOpen или JCRootDirOpen (что одинаково, так как первая в dll вызывает вторую, это справедливо почти для всех функций, но есть несколько исключений) с идентификатором вендора равным 0 (константы типа 0xF007 позволят увидеть только отдельные директории в основном старых eToken на которых хранятся банковские ключи сгенерированные с помощью утилит типа PKIAdmin и MessagePRO).
Следующей важной особенностью современных джакарт является необходимость знать id апплета который установлен на токене, за это отвечает функция JCSelectApplet.
У старых токенов обычно есть апплет по умолчанию и вызов этой функции специально не требуется, но у новых и относительно новых джакарт без знания id апплета дальнейшая работа становится невозможной. Вызов всех функций получающих информацию от токена в этом случае возвращает False. В моём проекте в этом случае реализован двуступенчатый брутфорс (токен отзывается всегда на два id, но работает из них только один) id и дальнейшеая работа с нужным значением.
Вся информация выводится в окно вывода расположенное под деревом директорий.
Реализован ввод пин кода, выводится также информация об оставшихся попытках его ввода.
Выводится содержание директорий и краткие сведения о файлах: имя, является ли файл приватной информацией закрытой пин кодом — буква p: (ноль после неё файл публичный, единица приватный) и размер файла в байтах после «s:». Файл открывается по двойному клику.
Можно просмотреть и при необходимости скопировать в буфер содержимое файлов токена в шестнадцатеричном виде или сохранить в бинарном виде на компьютер.
Можно также изменить содержимое файла и выбрать в меню «Сохранить изменения» (предварительно должен быть введён пин код, если не был введён, то будет выведено соответствующее сообщение, в этом случае отредактированные данные можно выделить и скопировать в буфер обмена).
Для удаления файла необходимо его выделить и нажать «Удалить», после чего появится окно для подтверждения.
У JaCarta File System есть занятная особенность, которая пристутствует на всех токенах которые я тестировал. Если создать на токене директорию или несколько директорий без файлов, при следующей сессии работы с токеном они исчезнут, видимо таким образом файловая система заботится о сохранении объёма памяти токена и чистит от всякого мусора.
Поэтому при нажатии в программе кнопки «Создать» создаётся сразу цепочка из директории или двух директорий и файла. Глубина вложенности директорий в программе — две, не считая корневую. В корневой директории можно создавать только директории, но не файлы.
Перед созданием, редактирование или удалением сущностей необходимо ввести пин код.
Очень важное замечание об именах директорий!
На токенах, где содержимое создано средствами производителя вы никогда не встретите директорий с одинаковыми именами, где бы они не были. Это связано с особенностями файловой системы.
Предположим, у нас на токене есть следующая сущность: //0001/A001/0008 (то есть в корневой директории находится папка 0001, в ней папка А001, а в ней файл 0008) и мы создаём на токене новую сущность: //СС00/0001/1010. При обращении к файлу 1010 начнётся поиск директории 0001, которая находится в корне и будет найдена первой, но такого файла в ней нет. В результате функция возвращает False и cущность становится потерянной, как либо обратиться к ней и удалить тоже нельзя. Поможет только инициализация токена.
Особое замечаеме про EToken PRO и JA Carta Pro, отличие у которых только во внешнем виде, у них в корневой директории находятся системные файлы (именно они показаны на скрине), в одном из которых хранится судя по всему хэш пин кода, изменение этих файлов приводит к тому что авторизация становится невозможной (пин код становится неверным) и после этого поможет только инициализация.
Относительно закрытых ключей удалось установить следующее: если на токене хранится контейнер, созданный сторонним криптопровайдером, например CryptoPro, то всё его содержимое, включая закрытые ключи будет доступно, это просто флэшка с пин кодом (что и показано на картинке). Если же ключевая пара была сгенерирована на борту токена средствами PKCS11, то будут доступны только сертификат и открытый ключ.
Поскольку это экспериментальная программа я не рекомендую использовать её с токенами содержащими действующие ключи ЭЦП, все операции выполняются на страх и риск экспериментирующего. Особенно это касается создания новых сущностей, в ряде случаев результат труднопредсказуем.
Вся информация для создания программы получена из открытых источников, цель её создания чисто исследовательская.
Собственно скрипт
JACartaEditor.au3
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <EditConstants.au3>
#include <TreeViewConstants.au3>
#include <GuiTreeView.au3>
#include <GuiMenu.au3>
#include <MsgBoxConstants.au3>
#include <StaticConstants.au3>
#include <GuiButton.au3>
#NoTrayIcon
;функции из jcFS.dll
Dim $ETSdkDll=DllOpen('jcFS.dll')
Func ETTokenLock($BindId)
Local $CallRes=DllCall($ETSdkDll,'WORD','ETTokenLock', _
'DWORD',$BindId _
)
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:True
EndFunc
Func ETTokenUnLock($BindId)
Local $CallRes=DllCall($ETSdkDll,'WORD','ETTokenUnLock', _
'DWORD',$BindId _
)
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:True
EndFunc
Func ETReadersEnumOpen()
Local $Out=DllStructCreate('DWORD')
Local $CallRes=DllCall($ETSdkDll,'WORD','ETReadersEnumOpen', _
'PTR',DllStructGetPtr($Out) _
)
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:DllStructGetData($Out,1)
EndFunc
Func ETReadersEnumNext($EnumId)
Local $Reader=DllStructCreate('CHAR name[260]; BYTE etoken;')
Local $CallRes=DllCall($ETSdkDll,'WORD','ETReadersEnumNext', _
'DWORD',$EnumId, _
'PTR',DllStructGetPtr($Reader) _
)
Local $Result[2]=[ DllStructGetData($reader,'name'), _
DllStructGetData($reader,'etoken')]
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:$Result
EndFunc
Func ETReadersEnumClose($EnumId)
Local $CallRes=DllCall($ETSdkDll,'WORD','ETReadersEnumClose', _
'DWORD',$EnumId _
)
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:True
EndFunc
Func ETTokenBind($ReaderName)
Local $In=DllStructCreate('BYTE['&(StringLen($ReaderName)+1)&']')
Local $Out=DllStructCreate('DWORD')
DllStructSetData($In,1,$ReaderName)
Local $CallRes=DllCall($ETSdkDll,'WORD','ETTokenBind', _
'PTR',DllStructGetPtr($Out), _
'PTR',DllStructGetPtr($In) _
)
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:DllStructGetData($Out,1)
EndFunc
Func ETTokenRebind($BindId)
Local $CallRes=DllCall($ETSdkDll,'WORD','ETTokenRebind', _
'DWORD',$BindId _
)
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:True
EndFunc
Func ETTokenUnbind($BindId)
Local $CallRes=DllCall($ETSdkDll,'WORD','ETTokenUnbind', _
'DWORD',$BindId _
)
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:True
EndFunc
Func ETTokenLogin($BindId,$Pin='')
Local $In=DllStructCreate('BYTE['&(StringLen($Pin)+1)&']')
DllStructSetData($In,1,$Pin)
Local $CallRes=DllCall($ETSdkDll,'WORD','ETTokenLogin', _
'DWORD',$BindId, _
'PTR',DllStructGetPtr($In) _
)
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:True
EndFunc
Func ETTokenPinChange($BindId,$Pin)
Local $In=DllStructCreate('CHAR['&(StringLen($Pin)+1)&']')
DllStructSetData($In,1,$Pin)
Local $CallRes=DllCall($ETSdkDll,'WORD','ETTokenPinChange', _
'DWORD',$BindId, _
'PTR',DllStructGetPtr($In) _
)
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:True
EndFunc
Func ETTokenLogout($BindId)
Local $CallRes=DllCall($ETSdkDll,'WORD','ETTokenLogout', _
'DWORD',$BindId _
)
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:True
EndFunc
Func ETRootDirOpen($BindId,$Dir=0xF007)
Local $Out=DllStructCreate('DWORD')
Local $CallRes=DllCall($ETSdkDll,'WORD','ETRootDirOpen', _
'PTR',DllStructGetPtr($Out), _
'DWORD',$BindId, _
'DWORD',$Dir _
)
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:DllStructGetData($Out,1)
EndFunc
Func ETDirOpen($Dir,$DirId)
Local $Out=DllStructCreate('DWORD')
Local $CallRes=DllCall($ETSdkDll,'WORD','ETDirOpen', _
'PTR',DllStructGetPtr($Out), _
'DWORD',$Dir, _
'DWORD',$DirId _
)
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:DllStructGetData($Out,1)
EndFunc
Func ETDirCreate($Dir,$DirId)
Local $Out=DllStructCreate('DWORD')
Local $CallRes=DllCall($ETSdkDll,'WORD','ETDirCreate', _
'PTR',DllStructGetPtr($Out), _
'DWORD',$Dir, _
'DWORD',$DirId, _
'DWORD',0 _
)
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:DllStructGetData($Out,1)
EndFunc
Func ETDirGetInfo($DirId)
Local $Out=DllStructCreate('WORD wDirName; WORD wSize')
Local $CallRes=DllCall($ETSdkDll,'WORD','ETDirGetInfo', _
'DWORD',$DirId, _
'PTR',DllStructGetPtr($Out) _
)
Local $Result[2]=[ DllStructGetData($Out,'wDirName'), _
DllStructGetData($Out,'wSize')]
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:$Result
EndFunc
Func ETDirClose($DirId)
Local $CallRes=DllCall($ETSdkDll,'WORD','ETDirClose', _
'DWORD',$DirId _
)
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:True
EndFunc
Func ETDirDelete($DirId)
Local $CallRes=DllCall($ETSdkDll,'WORD','ETDirDelete', _
'DWORD',$DirId _
)
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:True
EndFunc
Func ETDirEnumOpen($DirId)
Local $Out=DllStructCreate('DWORD')
Local $CallRes=DllCall($ETSdkDll,'WORD','ETDirEnumOpen', _
'PTR',DllStructGetPtr($Out), _
'DWORD',$DirId _
)
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:DllStructGetData($Out,1)
EndFunc
Func ETDirEnumNext($EnumId)
Local $Out=DllStructCreate('DWORD')
Local $CallRes=DllCall($ETSdkDll,'WORD','ETDirEnumNext', _
'DWORD',$EnumId, _
'PTR',DllStructGetPtr($Out) _
)
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:DllStructGetData($Out,1)
EndFunc
Func ETDirEnumClose($EnumId)
Local $CallRes=DllCall($ETSdkDll,'WORD','ETDirEnumClose', _
'DWORD',$EnumId _
)
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:True
EndFunc
Func ETFileOpen($File,$DirId)
Local $Out=DllStructCreate('DWORD')
Local $CallRes=DllCall($ETSdkDll,'WORD','ETFileOpen', _
'PTR',DllStructGetPtr($Out), _
'DWORD',$DirId, _
'DWORD',$File _
)
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:DllStructGetData($Out,1)
EndFunc
Func ETFileCreate($File,$DirId,$Size,$Private=0)
Local $Out=DllStructCreate('DWORD')
Local $CallRes=DllCall($ETSdkDll,'WORD','ETFileCreate', _
'PTR',DllStructGetPtr($Out), _
'DWORD',$DirId, _
'DWORD',$File, _
'DWORD',$Size, _
'DWORD',$Private _
)
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:DllStructGetData($Out,1)
EndFunc
Func ETFileGetInfo($FileId)
Local $Out=DllStructCreate('WORD name;WORD private;WORD;WORD size')
Local $CallRes=DllCall($ETSdkDll,'WORD','ETFileGetInfo', _
'DWORD',$FileId, _
'PTR',DllStructGetPtr($Out) _
)
Local $Result[3]=[ DllStructGetData($Out,'name'), _
DllStructGetData($Out,'private'), _
DllStructGetData($Out,'size')]
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:$Result
EndFunc
Func ETFileRead($FileId)
Local $FileInfo=ETFileGetInfo($FileId)
If @error Then Return SetError(@error,0,False)
Local $Out=DllStructCreate('BYTE ['&$FileInfo[2]&']')
Local $CallRes=DllCall($ETSdkDll,'WORD','ETFileRead', _
'DWORD',$FileId, _
'DWORD',0, _
'DWORD',0xFFFF, _
'PTR',DllStructGetPtr($Out), _
'DWORD',$FileInfo[2] _
)
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:DllStructGetData($Out,1)
EndFunc
Func ETFileWrite($FileId,$Data,$Pos=0)
$Data=Binary($Data)
Local $DataSize=BinaryLen($Data)
Local $In=DllStructCreate('BYTE['&$DataSize&']')
DllStructSetData($In,1,$Data)
Local $CallRes=DllCall($ETSdkDll,'WORD','ETFileWrite', _
'DWORD',$FileId, _
'DWORD',$Pos, _
'PTR',DllStructGetPtr($In), _
'DWORD',$DataSize _
)
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:True
EndFunc
Func ETFileClose($FileId)
Local $CallRes=DllCall($ETSdkDll,'WORD','ETFileClose', _
'DWORD',$FileId _
)
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:True
EndFunc
Func ETFileDelete($FileId)
Local $CallRes=DllCall($ETSdkDll,'WORD','ETFileDelete', _
'DWORD',$FileId _
)
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:True
EndFunc
Func ETFilesEnumOpen($DirId)
Local $Out=DllStructCreate('DWORD')
Local $CallRes=DllCall($ETSdkDll,'WORD','ETFilesEnumOpen', _
'PTR',DllStructGetPtr($Out), _
'DWORD',$DirId _
)
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:DllStructGetData($Out,1)
EndFunc
Func ETFilesEnumNext($EnumId)
Local $Out=DllStructCreate('DWORD')
Local $CallRes=DllCall($ETSdkDll,'WORD','ETFilesEnumNext', _
'DWORD',$EnumId, _
'PTR',DllStructGetPtr($Out) _
)
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:DllStructGetData($Out,1)
EndFunc
Func ETFilesEnumClose($EnumId)
Local $CallRes=DllCall($ETSdkDll,'WORD','ETFilesEnumClose', _
'DWORD',$EnumId _
)
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:True
EndFunc
Func ETTokenLabelGet($BindId)
Local $Out1=DllStructCreate('DWORD')
Local $CallRes=DllCall($ETSdkDll,'WORD','ETTokenLabelGet', _
'DWORD',$BindId, _
'PTR',0, _
'PTR',DllStructGetPtr($Out1) _
)
If $CallRes[0] Then Return SetError($CallRes[0],0,False)
Local $Out2=DllStructCreate('CHAR['&DllStructGetData($Out1,1)&']')
$CallRes=DllCall($ETSdkDll,'WORD','ETTokenLabelGet', _
'DWORD',$BindId, _
'PTR',DllStructGetPtr($Out2), _
'PTR',DllStructGetPtr($Out1) _
)
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:DllStructGetData($Out2,1)
EndFunc
Func ETTokenIDGet($BindId)
Local $Out1=DllStructCreate('DWORD')
Local $CallRes=DllCall($ETSdkDll,'WORD','ETTokenIDGet', _
'DWORD',$BindId, _
'PTR',0, _
'PTR',DllStructGetPtr($Out1) _
)
If $CallRes[0] Then Return SetError($CallRes[0],0,False)
Local $Out2=DllStructCreate('CHAR['&DllStructGetData($Out1,1)&']')
$CallRes=DllCall($ETSdkDll,'WORD','ETTokenIDGet', _
'DWORD',$BindId, _
'PTR',DllStructGetPtr($Out2), _
'PTR',DllStructGetPtr($Out1) _
)
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:DllStructGetData($Out2,1)
EndFunc
Func ETTokenMaxPinGet($BindId)
Local $Out=DllStructCreate('DWORD')
Local $CallRes=DllCall($ETSdkDll,'WORD','ETTokenMaxPinGet', _
'DWORD',$BindId, _
'PTR',DllStructGetPtr($Out) _
)
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:DllStructGetData($Out,1)
EndFunc
Func ETTokenMinPinGet($BindId)
Local $Out=DllStructCreate('DWORD')
Local $CallRes=DllCall($ETSdkDll,'WORD','ETTokenMinPinGet', _
'DWORD',$BindId, _
'PTR',DllStructGetPtr($Out) _
)
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:DllStructGetData($Out,1)
EndFunc
Func ETSelectApplet($BindId, $Applet)
Local $In=DllStructCreate('DWORD')
DllStructSetData($In,1,$Applet)
Local $CallRes=DllCall($ETSdkDll,'WORD','ETSelectApplet', _
'DWORD',$BindId, _
'PTR',DllStructGetPtr($Applet) _
)
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:True
EndFunc
Func JCSelectApplet($BindId, $Applet)
Local $In=DllStructCreate('WORD')
DllStructSetData($In,1,$Applet)
Local $CallRes=DllCall($ETSdkDll,'WORD','JCSelectApplet', _
'DWORD',$BindId, _
'WORD',$Applet _
)
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:True
EndFunc
Func JCReadersEnumOpen()
Local $Out=DllStructCreate('DWORD')
Local $CallRes=DllCall($ETSdkDll,'WORD','JCReadersEnumOpen', _
'PTR',DllStructGetPtr($Out) _
)
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:DllStructGetData($Out,1)
EndFunc
Func JCReadersEnumNext($EnumId)
Local $Reader=DllStructCreate('CHAR name[260]; BYTE etoken;')
Local $CallRes=DllCall($ETSdkDll,'WORD','JCReadersEnumNext', _
'DWORD',$EnumId, _
'PTR',DllStructGetPtr($Reader) _
)
Local $Result[2]=[ DllStructGetData($reader,'name'), _
DllStructGetData($reader,'etoken')]
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:$Result
EndFunc
Func JCReadersEnumClose($EnumId)
Local $CallRes=DllCall($ETSdkDll,'WORD','JCReadersEnumClose', _
'DWORD',$EnumId _
)
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:True
EndFunc
Func JCTokenBind($ReaderName)
Local $In=DllStructCreate('CHAR['&(StringLen($ReaderName)+1)&']')
Local $Out=DllStructCreate('DWORD')
DllStructSetData($In,1,$ReaderName)
Local $CallRes=DllCall($ETSdkDll,'WORD','JCTokenBind', _
'PTR',DllStructGetPtr($Out), _
'PTR',DllStructGetPtr($In) _
)
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:DllStructGetData($Out,1)
EndFunc
Func JCTokenRebind($BindId)
Local $CallRes=DllCall($ETSdkDll,'WORD','JCTokenRebind', _
'DWORD',$BindId _
)
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:True
EndFunc
Func JCTokenUnbind($BindId)
Local $CallRes=DllCall($ETSdkDll,'WORD','JCTokenUnbind', _
'DWORD',$BindId _
)
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:True
EndFunc
Func JCTokenLogin($BindId,$Pin)
Local $In=DllStructCreate('CHAR['&(StringLen($Pin)+1)&']')
DllStructSetData($In,1,$Pin)
Local $CallRes=DllCall($ETSdkDll,'WORD','JCTokenLogin', _
'DWORD',$BindId, _
'PTR',DllStructGetPtr($In) _
)
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:True
EndFunc
Func JCTokenPinChange($BindId,$Pin)
Local $In=DllStructCreate('CHAR['&(StringLen($Pin)+1)&']')
DllStructSetData($In,1,$Pin)
Local $CallRes=DllCall($ETSdkDll,'WORD','JCTokenPinChange', _
'DWORD',$BindId, _
'PTR',DllStructGetPtr($In) _
)
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:True
EndFunc
Func JCTokenLogout($BindId)
Local $CallRes=DllCall($ETSdkDll,'WORD','JCTokenLogout', _
'DWORD',$BindId _
)
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:True
EndFunc
Func JCRootDirOpen($BindId,$Dir=0)
Local $Out=DllStructCreate('DWORD')
Local $CallRes=DllCall($ETSdkDll,'WORD','JCRootDirOpen', _
'PTR',DllStructGetPtr($Out), _
'DWORD',$BindId, _
'WORD',$Dir _
)
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:DllStructGetData($Out,1)
EndFunc
Func JCDirOpen($Dir,$DirId)
Local $Out=DllStructCreate('DWORD')
Local $CallRes=DllCall($ETSdkDll,'WORD','JCDirOpen', _
'PTR',DllStructGetPtr($Out), _
'DWORD',$Dir, _
'DWORD',$DirId _
)
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:DllStructGetData($Out,1)
EndFunc
Func JCDirCreate($Dir,$DirId)
Local $Out=DllStructCreate('DWORD')
Local $CallRes=DllCall($ETSdkDll,'WORD','JCDirCreate', _
'PTR',DllStructGetPtr($Out), _
'DWORD',$Dir, _
'DWORD',$DirId, _
'DWORD',0 _
)
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:DllStructGetData($Out,1)
EndFunc
Func JCDirGetInfo($DirId)
Local $Out=DllStructCreate('BYTE[8]')
Local $CallRes=DllCall($ETSdkDll,'WORD','JCDirGetInfo', _
'DWORD',$DirId, _
'PTR',DllStructGetPtr($Out) _
)
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:DllStructGetData($Out,1)
EndFunc
Func JCDirClose($DirId)
Local $CallRes=DllCall($ETSdkDll,'WORD','JCDirClose', _
'DWORD',$DirId _
)
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:True
EndFunc
Func JCDirDelete($DirId)
Local $CallRes=DllCall($ETSdkDll,'WORD','JCDirDelete', _
'DWORD',$DirId _
)
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:True
EndFunc
Func JCDirEnumOpen($DirId)
Local $Out=DllStructCreate('DWORD')
Local $CallRes=DllCall($ETSdkDll,'WORD','JCDirEnumOpen', _
'PTR',DllStructGetPtr($Out), _
'DWORD',$DirId _
)
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:DllStructGetData($Out,1)
EndFunc
Func JCDirEnumNext($EnumId)
Local $Out=DllStructCreate('DWORD')
Local $CallRes=DllCall($ETSdkDll,'WORD','JCDirEnumNext', _
'DWORD',$EnumId, _
'PTR',DllStructGetPtr($Out) _
)
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:DllStructGetData($Out,1)
EndFunc
Func JCDirEnumClose($EnumId)
Local $CallRes=DllCall($ETSdkDll,'WORD','JCDirEnumClose', _
'DWORD',$EnumId _
)
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:True
EndFunc
Func JCFileOpen($File,$DirId)
Local $Out=DllStructCreate('DWORD')
Local $CallRes=DllCall($ETSdkDll,'WORD','JCFileOpen', _
'PTR',DllStructGetPtr($Out), _
'DWORD',$DirId, _
'DWORD',$File _
)
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:DllStructGetData($Out,1)
EndFunc
Func JCFileCreate($File,$DirId,$Size,$Private=0)
Local $Out=DllStructCreate('DWORD')
Local $CallRes=DllCall($ETSdkDll,'WORD','JCFileCreate', _
'PTR',DllStructGetPtr($Out), _
'DWORD',$DirId, _
'DWORD',$File, _
'DWORD',$Size, _
'DWORD',$Private _
)
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:DllStructGetData($Out,1)
EndFunc
Func JCFileGetInfo($FileId)
Local $Out=DllStructCreate('WORD name;WORD private;WORD;WORD size')
Local $CallRes=DllCall($ETSdkDll,'WORD','JCFileGetInfo', _
'DWORD',$FileId, _
'PTR',DllStructGetPtr($Out) _
)
Local $Result[3]=[ DllStructGetData($Out,'name'), _
DllStructGetData($Out,'private'), _
DllStructGetData($Out,'size')]
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:$Result
EndFunc
Func JCFileRead($FileId)
Local $FileInfo=JCFileGetInfo($FileId)
If @error Then Return SetError(@error,0,False)
Local $Out=DllStructCreate('BYTE ['&$FileInfo[2]&']')
Local $CallRes=DllCall($ETSdkDll,'WORD','JCFileRead', _
'DWORD',$FileId, _
'DWORD',0, _
'DWORD',0xFFFF, _
'PTR',DllStructGetPtr($Out), _
'DWORD',$FileInfo[2] _
)
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:DllStructGetData($Out,1)
EndFunc
Func JCFileWrite($FileId,$Data,$Pos=0)
$Data=Binary($Data)
Local $DataSize=BinaryLen($Data)
Local $In=DllStructCreate('BYTE['&$DataSize&']')
DllStructSetData($In,1,$Data)
Local $CallRes=DllCall($ETSdkDll,'WORD','JCFileWrite', _
'DWORD',$FileId, _
'DWORD',$Pos, _
'PTR',DllStructGetPtr($In), _
'DWORD',$DataSize _
)
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:True
EndFunc
Func JCFileClose($FileId)
Local $CallRes=DllCall($ETSdkDll,'WORD','JCFileClose', _
'DWORD',$FileId _
)
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:True
EndFunc
Func JCFileDelete($FileId)
Local $CallRes=DllCall($ETSdkDll,'WORD','JCFileDelete', _
'DWORD',$FileId _
)
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:True
EndFunc
Func JCFilesEnumOpen($DirId)
Local $Out=DllStructCreate('DWORD')
Local $CallRes=DllCall($ETSdkDll,'WORD','JCFilesEnumOpen', _
'PTR',DllStructGetPtr($Out), _
'DWORD',$DirId _
)
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:DllStructGetData($Out,1)
EndFunc
Func JCFilesEnumNext($EnumId)
Local $Out=DllStructCreate('DWORD')
Local $CallRes=DllCall($ETSdkDll,'WORD','JCFilesEnumNext', _
'DWORD',$EnumId, _
'PTR',DllStructGetPtr($Out) _
)
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:DllStructGetData($Out,1)
EndFunc
Func JCFilesEnumClose($EnumId)
Local $CallRes=DllCall($ETSdkDll,'WORD','JCFilesEnumClose', _
'DWORD',$EnumId _
)
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:True
EndFunc
Func JCTokenLabelGet($BindId)
Local $Out1=DllStructCreate('DWORD')
Local $CallRes=DllCall($ETSdkDll,'WORD','JCTokenLabelGet', _
'DWORD',$BindId, _
'PTR',0, _
'PTR',DllStructGetPtr($Out1) _
)
If $CallRes[0] Then Return SetError($CallRes[0],0,False)
Local $Out2=DllStructCreate('CHAR['&DllStructGetData($Out1,1)&']')
$CallRes=DllCall($ETSdkDll,'WORD','JCTokenLabelGet', _
'DWORD',$BindId, _
'PTR',DllStructGetPtr($Out2), _
'PTR',DllStructGetPtr($Out1) _
)
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:DllStructGetData($Out2,1)
EndFunc
Func JCTokenIDGet($BindId)
Local $Out1=DllStructCreate('DWORD')
Local $CallRes=DllCall($ETSdkDll,'WORD','JCTokenIDGet', _
'DWORD',$BindId, _
'PTR',0, _
'PTR',DllStructGetPtr($Out1) _
)
If $CallRes[0] Then Return SetError($CallRes[0],0,False)
Local $Out2=DllStructCreate('CHAR['&DllStructGetData($Out1,1)&']')
$CallRes=DllCall($ETSdkDll,'WORD','JCTokenIDGet', _
'DWORD',$BindId, _
'PTR',DllStructGetPtr($Out2), _
'PTR',DllStructGetPtr($Out1) _
)
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:DllStructGetData($Out2,1)
EndFunc
Func JCTokenMaxPinGet($BindId)
Local $Out=DllStructCreate('DWORD')
Local $CallRes=DllCall($ETSdkDll,'WORD','JCTokenMaxPinGet', _
'DWORD',$BindId, _
'PTR',DllStructGetPtr($Out) _
)
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:DllStructGetData($Out,1)
EndFunc
Func JCTokenMinPinGet($BindId)
Local $Out=DllStructCreate('DWORD')
Local $CallRes=DllCall($ETSdkDll,'WORD','JCTokenMinPinGet', _
'DWORD',$BindId, _
'PTR',DllStructGetPtr($Out) _
)
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:DllStructGetData($Out,1)
EndFunc
Func JCTokenUnLock($BindId)
Local $CallRes=DllCall($ETSdkDll,'WORD','JCTokenUnLock', _
'DWORD',$BindId _
)
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:True
EndFunc
Func JCTokenLock($BindId)
Local $CallRes=DllCall($ETSdkDll,'WORD','JCTokenLock', _
'DWORD',$BindId _
)
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:True
EndFunc
Func JCTokenPinAttemptsGet($BindId)
Local $Out=DllStructCreate('DWORD')
Local $CallRes=DllCall($ETSdkDll,'WORD','JCTokenPinAttemptsGet', _
'DWORD',$BindId, _
'PTR',DllStructGetPtr($Out) _
)
Return $CallRes[0] _
?SetError($CallRes[0],0,False) _
:DllStructGetData($Out,1)
EndFunc
;Начало приложения
Opt("GUIOnEventMode", 1)
Dim $BindId, $filelog, $Result, $DirIdRoot=False, $Edit, $msg, $Fileinfo, $treeview, $generalitem, $displayitem, $diritem, $Edit, $SrcSubId, $Output, $pinbutton, $hPinWin, $PinEdit, $pinokbutton, $pincancelbutton, $Pin, $Edit1, $Reader, $Applet, $AppletID, $text, $CreateDirWin
Global $Dir1, $Dir2
Dim $hParentWin, $hChildWin, $sItemText, $folderbutton, $filebutton, $deletebutton, $CreateFileWin, $FileEdit, $fileokbutton, $filecancelbutton, $publicbutton, $privatebutton, $sizefile
Dim $hFile, $hMain
Global Enum $idSave= 1000, $Save
Dim $Appname = 'JaCarta Editor'
;Функция получения applet ID брутфорсом
Func Applet()
GUICtrlSetData($Output, 'Попытка получить applet ID... '&@CRLF,1)
Local $Result, $AppletTemp= 0
For $Applet = 0 To 65535 Step 1
$Result = 0
$Result=JCSelectApplet($BindId,$Applet) ; 0x2001 PROJAVA для E-token, 0x1002 PRO, 0x1001 R2, 0x2202 GOST, 0x2205 DATASTORE, 0x2206 ГОСТ-2, 0x2201, 0x2204 (чёрные JaCarta)
If $Result = True Then
$AppletTemp=$Applet
$AppletID=$Applet
ExitLoop
EndIf
Next
Local $Id=ETTokenLabelGet($BindId)
if $Id= False Then
For $Applet=$AppletTemp+1 To 65535 Step 1
$Result=0
$Result=JCSelectApplet($BindId,$Applet)
If $Result = True Then
ExitLoop
EndIf
Next
EndIf
JCSelectApplet($BindId,$Applet)
GUICtrlSetData($Output, 'Select applet 0x'&hex($Applet,4)&@CRLF,1)
$AppletID=$Applet
EndFunc
;Просмотр директорий и файлов в цикле
Func PrintDir($Id,$Prefix)
Local $EnumId=ETDirEnumOpen($Id)
While 1
Local $dir=ETDirEnumNext($EnumId)
If @error Then ExitLoop
Local $DirId=ETDirOpen($dir,$Id)
Local $Dirinfo
$Dirinfo=ETDirGetInfo($DirId)
Local $Dirtext='(dir)'&hex($dir,4)
$diritem = _GUICtrlTreeView_AddChild($treeview,$Prefix, $Dirtext)
PrintDir($DirId,$diritem)
ETDirClose($DirId)
WEnd
ETDirEnumClose($EnumId)
$EnumId=ETFilesEnumOpen($Id)
While 1
Local $file=ETFilesEnumNext($EnumId)
If @error Then ExitLoop
Local $FileId=ETFileOpen($file,$Id)
$Fileinfo=ETFileGetInfo($FileId)
Local $filetext='(file)'&hex($file,5)&' '&'p: '&$Fileinfo[1]&' s: '&$Fileinfo[2]&@CRLF
_GUICtrlTreeView_AddChild($treeview,$Prefix,$filetext)
WEnd
ETFilesEnumClose($EnumId)
EndFunc
;операции подключения к токену и получения от него информации
Func List()
GUICtrlSetData($Output, '')
Local $text
Local $EnumId=ETReadersEnumOpen()
GUICtrlSetData($Output, 'В системе установлены ридеры:'&@CRLF,1)
While 1
$Reader=ETReadersEnumNext($EnumId)
If @error Then ExitLoop
GUICtrlSetData($Output, $Reader[0]&@CRLF,1)
WEnd
ETReadersEnumClose($EnumId)
Local $EnumId=ETReadersEnumOpen()
$Reader=ETReadersEnumNext($EnumId)
$BindId=ETTokenBind($Reader[0])
$Result=JCTokenLock($BindId)
GUICtrlSetData($Output, 'Подключен ридер '&$Reader[0]&@CRLF,1)
;если не получается получить ID токена, значит надо подбирать AppletID
$Result=ETTokenIDGet($BindId)
if $Result= False Then
if $AppletID<>0 Then
JCSelectApplet($BindId,$AppletID)
Else
Applet()
EndIf
EndIf
$Result=ETTokenIDGet($BindId)
$text=$Reader[0]&' ID '&$Result
$generalitem = _GUICtrlTreeView_AddChild($treeview,0,$text)
$Result=ETTokenLabelGet($BindId)
GUICtrlSetData($Output, 'Label: '&$Result&@CRLF,1)
$DirIdRoot=ETRootDirOpen($BindId,0) ;0xF007 для банков 0x0001 для крипто про
$Result=JCTokenPinAttemptsGet($BindId)
;если был введён пин код начинаем авторизацию
If $Pin <> 0 Then
$Result=JCTokenLogin($BindId,$Pin)
If $Result=False Then
$Result=JCTokenPinAttemptsGet($BindId)
MsgBox(0x10,$Appname,'Неверный PIN код'&@CRLF&'Количество попыток ввода PIN кода: '&$Result )
Else
GUICtrlSetData($Output, 'Login OK'&@CRLF,1)
EndIf
EndIf
$Result=JCTokenPinAttemptsGet($BindId)
GUICtrlSetData($Output, 'Количество попыток ввода PIN кода: '&$Result&@CRLF,1)
PrintDir($DirIdRoot,0)
ETTokenUnbind($BindId)
ETReadersEnumClose($EnumId)
EndFunc
;закрытие дочерних окон и программы
Func onClose()
GUISetState(@SW_HIDE, $hPinWin)
GUISetState(@SW_HIDE, $hChildWin)
GUISetState(@SW_HIDE, $CreateFileWin)
if @GUI_WinHandle=$hParentWin Then
Exit
EndIf
EndFunc
;вывод окна ввода пин кода
Func onPin()
GUISetState(@SW_SHOW, $hPinWin )
EndFunc
;подготовка к авторизации после ввода пин кода
Func onPinOK()
$Pin=GUICtrlRead($PinEdit)
GUISetState(@SW_HIDE, $hPinWin)
_GUICtrlTreeView_DeleteAll ($treeview)
List()
EndFunc
;отмена ввода пин кода
Func onPinCancel()
GUISetState(@SW_HIDE, $hPinWin)
EndFunc
;функция удаления
Func Delete()
If $Pin=0 Then
MsgBox(0x10,$Appname,'Для удаления файла сначала введите пин код' )
Else
Local $hItem = _GUICtrlTreeView_GetSelection($treeview)
Local $Del = _GUICtrlTreeView_GetText($treeview, $hItem)
if _GUICtrlTreeView_GetChildren($treeview, $hItem)=False Then
$Del=StringTrimLeft ( $Del, 6 )
Local $p=0
$p=StringInStr ($Del,"p:")
$Del=StringMid ( $Del, 1, $p-2 )
if MsgBox(4 + 32, $Appname, 'Удалить '& $Del &' ?') = 6 Then
Local $DirID=_GUICtrlTreeView_GetParentHandle($treeview, $hItem)
Local $Dir= _GUICtrlTreeView_GetText($treeview, $DirID)
$Dir=StringTrimLeft ( $Dir, 5 )
$BindId=ETTokenBind($Reader[0])
$Result=JCTokenLock($BindId)
if $AppletID<>0 Then
JCSelectApplet($BindId,$AppletID)
EndIf
If $Pin <> 0 Then
$Result=JCTokenLogin($BindId,$Pin)
If $Result=False Then
$Result=JCTokenPinAttemptsGet($BindId)
MsgBox(0x10,$Appname,'Неверный PIN код'&@CRLF&'Количество попыток ввода PIN кода: '&$Result)
EndIf
EndIf
Local $HDir=GetDir(ETRootDirOpen($BindId,0), $Dir)
Local $DELFile =JCFileOpen(Dec ($Del), $HDir)
JCFileDelete($DELFile )
ETDirClose($HDir)
ETTokenUnbind($BindId)
_GUICtrlTreeView_DeleteAll ($treeview)
List()
EndIf
Else
MsgBox(0x10,$Appname,'Сначала удалите все файлы в папке после чего папка будет удалена автоматически' )
EndIf
EndIf
EndFunc
;функция вывода окна создания файла
Func onFileCreate()
If $Pin=0 Then
MsgBox(0x10,$Appname,'Для создания файла сначала введите пин код' )
Else
Local $hItem = _GUICtrlTreeView_GetSelection($treeview)
Local $FileText = 0, $Dir1=0, $Dir2=0
$FileText = _GUICtrlTreeView_GetText($treeview, $hItem)
;Проверка не выбрана ли корневая директория
if StringLen($FileText) >20 Then
GUICtrlSetData($FileEdit, '')
GUICtrlSetData($FileEdit, '//',0)
Else
$Dir1=StringTrimLeft ( $FileText, 5 )
Local $ParentID=_GUICtrlTreeView_GetParentHandle($treeview, $hItem)
Local $ParentDir= _GUICtrlTreeView_GetText($treeview, $ParentID)
if StringInStr ($ParentDir,"Dir")=0 Then
$ParentDir=''
GUICtrlSetData($FileEdit, '')
GUICtrlSetData($FileEdit, '//'&$Dir1&'/',0)
Else
$Dir2=StringTrimLeft ( $ParentDir, 5 )
$Dir2='/'&$Dir2
GUICtrlSetData($FileEdit, '')
GUICtrlSetData($FileEdit, '/'&$Dir2&'/'&$Dir1&'/',0)
EndIf
EndIf
GUISetState(@SW_SHOW, $CreateFileWin)
EndIf
EndFunc
;отмена создания файла
Func onFileCancel()
GUISetState(@SW_HIDE, $CreateFileWin)
EndFunc
;функция создания файла
Func onFileOK()
Local $filename=GUICtrlRead($FileEdit)
Local $isPrivate=_GUICtrlButton_GetCheck($privatebutton)
Local $fileSize=GUICtrlRead($sizefile)
$BindId=ETTokenBind($Reader[0])
$Result=JCTokenLock($BindId)
if $AppletID<>0 Then
JCSelectApplet($BindId,$AppletID)
EndIf
If $Pin <> 0 Then
$Result=JCTokenLogin($BindId,$Pin)
If $Result=False Then
$Result=JCTokenPinAttemptsGet($BindId)
MsgBox(0x10,$Appname,'Неверный PIN код'&@CRLF&'Количество попыток ввода PIN кода: '&$Result )
EndIf
EndIf
Local $rootdir=ETRootDirOpen($BindId,0)
Local $text=StringTrimLeft ( $filename, 2 )
Local $text1=StringLeft($text, 4)
$dir1=JCDirOpen(Dec ($text1), $rootdir)
if $dir1=false Then
$dir1= ETDirCreate(Dec ($text1), $rootdir)
EndIf
if StringLen($text) >12 Then
$text=StringTrimLeft ( $text, 5 )
$text1=StringLeft($text, 4)
$dir2=JCDirOpen(Dec ($text1), $dir1)
if $dir2=false Then
$dir2= ETDirCreate(Dec ($text1), $dir1)
EndIf
$text=StringTrimLeft ( $text, 5 )
Local $DstFile=JCFileCreate(Dec ($text),$Dir2,$fileSize,$isPrivate)
JCFileClose($DstFile)
Else
$text=StringTrimLeft ( $text, 5 )
Local $DstFile=JCFileCreate(Dec ($text),$Dir1,$fileSize,$isPrivate)
JCFileClose($DstFile)
EndIf
ETTokenUnbind($BindId)
GUISetState(@SW_HIDE, $CreateFileWin)
GUISetState(@SW_SHOW, $hParentWin)
_GUICtrlTreeView_DeleteAll ($treeview)
List()
EndFunc
;сохранение изменённого файла на токене
Func SaveFile()
If $Pin=0 Then
MsgBox(0x10,$Appname,'Для сохранения файла сначала введите пин код' )
Else
Local $filebody=GUICtrlRead($Edit1)
Local $hItem = _GUICtrlTreeView_GetSelection($treeview)
Local $FileEd = _GUICtrlTreeView_GetText($treeview, $hItem)
$FileEd=StringTrimLeft ( $FileEd, 6 )
Local $p=0
$p=StringInStr ($FileEd,"p:")
$FileEd=StringMid ( $FileEd, 1, $p-2 )
Local $DirID=_GUICtrlTreeView_GetParentHandle($treeview, $hItem)
Local $Dir= _GUICtrlTreeView_GetText($treeview, $DirID)
$Dir=StringTrimLeft ( $Dir, 5 )
$BindId=ETTokenBind($Reader[0])
$Result=JCTokenLock($BindId)
if $AppletID<>0 Then
JCSelectApplet($BindId,$AppletID)
EndIf
If $Pin <> 0 Then
$Result=JCTokenLogin($BindId,$Pin)
If $Result=False Then
$Result=JCTokenPinAttemptsGet($BindId)
MsgBox(0x10,$Appname,'Неверный PIN код'&@CRLF&'Количество попыток ввода PIN кода: '&$Result)
EndIf
EndIf
Local $HDir=GetDir(ETRootDirOpen($BindId,0), $Dir)
Local $File=JCFileOpen(Dec ($FileEd),$HDir)
Local $Data =Binary('0x' & $filebody)
JCFileWrite($File, $Data)
JCFileClose($File)
ETDirClose($HDir)
ETTokenUnbind($BindId)
GUISetState(@SW_HIDE, $hChildWin)
_GUICtrlTreeView_DeleteAll ($treeview)
List()
EndIf
EndFunc
;сохранение открытого на токене файла на компьютер
Func SaveFileAs()
Local $varFile = 0
$varFile = FileSaveDialog( "Сохранить файл", @MyDocumentsDir & "\", "Бинарные файлы (*.bin)", 16,'',$hParentWin)
If StringLen($varFile) > 3 Then
Local $filedest
$filedest = FileOpen($varFile, 17)
; Check if file open
If $filedest = -1 Then
MsgBox(0, "Error", "Unable to open file.")
Exit
EndIf
FileWrite($filedest, $text)
FileClose($filedest)
EndIf
EndFunc
;Обработка команд меню окна просмотра и редактирования файла
Func WM_COMMAND($hWnd, $iMsg, $wParam, $lParam)
#forceref $hWnd, $iMsg, $lParam
Switch $wParam
Case $Save
SaveFile()
Case $idSave
SaveFileAs()
EndSwitch
EndFunc ;==>WM_COMMAND
;инициализация графического интерфейса
Func GUIInit()
$hParentWin= GUICreate($Appname, 560, 400)
GUISetOnEvent($GUI_EVENT_CLOSE,'onClose')
;Создание главного окна
$treeview = GUICtrlCreateTreeView(6, 6, 400, 300, BitOR($TVS_HASBUTTONS, $TVS_HASLINES, $TVS_LINESATROOT, $TVS_DISABLEDRAGDROP, $TVS_SHOWSELALWAYS), $WS_EX_CLIENTEDGE)
$Output = GUICtrlCreateEdit("" , 6, 320, 400, 70, $ES_AUTOVSCROLL + $WS_VSCROLL + $ES_NOHIDESEL + $ES_WANTRETURN)
$pinbutton = GUICtrlCreateButton("&Ввести PIN код", 430, 20, 100, 50)
$filebutton = GUICtrlCreateButton("&Создать", 430, 80, 100, 50)
$deletebutton = GUICtrlCreateButton("&Удалить", 430, 140, 100, 50)
;Создание окна ввода пин кода
$hPinWin = GUICreate('Введите PIN код', 200, 200, -1, -1, $WS_SYSMENU, -1, $hParentWin)
$PinEdit = GUICtrlCreateInput ("" , 50, 40, 100, 25, $ES_PASSWORD + $ES_NOHIDESEL + $ES_WANTRETURN)
$pinokbutton = GUICtrlCreateButton("&OK", 20, 100, 60, 40)
$pincancelbutton = GUICtrlCreateButton("&Отмена", 110, 100, 60, 40)
;Окно создания файла
$CreateFileWin = GUICreate('Создание папок и файла', 340, 350, -1, -1, $WS_SYSMENU, -1, $hParentWin)
$FileEdit = GUICtrlCreateInput ("" , 50, 70, 230, 25)
$fileokbutton= GUICtrlCreateButton("&OK", 70, 240, 60, 40)
$filecancelbutton = GUICtrlCreateButton("&Отмена", 210, 240, 60, 40)
$publicbutton= _GUICtrlButton_Create($CreateFileWin, "Public", 100, 120, 50, 30, $BS_AUTORADIOBUTTON, 0)
$privatebutton=_GUICtrlButton_Create($CreateFileWin, "Private", 160, 120, 50, 30, $BS_AUTORADIOBUTTON, 0)
_GUICtrlButton_SetCheck($publicbutton, $BST_CHECKED)
Local $label=GUICtrlCreateLabel('Введите имя папок и файла в hex формате 1001 ', 70, 20, 170, 40, $SS_CENTER)
$sizefile = GUICtrlCreateInput ("10" , 220, 175, 50, 20)
Local $label1=GUICtrlCreateLabel('Введите размер файла в байтах', 20, 180, 200, 60, $SS_CENTER)
;Окно редактирования файла
$hChildWin = GUICreate($sItemText, 300, 230, -1, -1, $WS_SYSMENU, -1, $hParentWin)
$Edit1 = GUICtrlCreateEdit("", 10, 10, 240, 160, $ES_AUTOVSCROLL + $WS_VSCROLL + $ES_NOHIDESEL + $ES_WANTRETURN)
; Создаёт меню "Файл" в окне редактирования файла
$hFile = _GUICtrlMenu_CreateMenu ()
_GUICtrlMenu_InsertMenuItem ($hFile, 0, 'Сохранить как...', $idSave)
_GUICtrlMenu_InsertMenuItem ($hFile, 1, 'Сохранить изменения', $Save)
$hMain = _GUICtrlMenu_CreateMenu ()
_GUICtrlMenu_InsertMenuItem ($hMain, 0, 'Файл', 0, $hFile)
_GUICtrlMenu_SetMenu ($hChildWin, $hMain)
;Определение событий
GUICtrlSetOnEvent($filebutton,'onFileCreate')
GUICtrlSetOnEvent($deletebutton,'Delete')
GUICtrlSetOnEvent($pinbutton,'onPin')
GUICtrlSetOnEvent($pinokbutton,'onPinOK')
GUICtrlSetOnEvent($pincancelbutton,'onPinCancel')
GUICtrlSetOnEvent($fileokbutton,'onFileOK')
GUICtrlSetOnEvent($filecancelbutton,'onFileCancel')
GUISetOnEvent($GUI_EVENT_CLOSE,'onClose')
GUISetState(@SW_SHOW, $hParentWin)
GUIRegisterMsg(0x0111, "WM_COMMAND")
EndFunc
;запуск основных функций приложения
GUIInit()
List()
;функция обработки двойного щелчка мышью на дереве файлов и директорий
GUIRegisterMsg($WM_NOTIFY, "MY_WM_NOTIFY")
Global $iDoubleClick = 0
Func MY_WM_NOTIFY($hWnd, $Msg, $wParam, $lParam)
Local $tagNMHDR, $vEvent
Switch $wParam
Case $treeview
$tagNMHDR = DllStructCreate("int;int;int", $lParam)
If @error Then Return
$vEvent = DllStructGetData($tagNMHDR, 3)
If $vEvent = $NM_DBLCLK Then
$iDoubleClick = 1
EndIf
EndSwitch
$tagNMHDR = 0
EndFunc ;==>MY_WM_NOTIFY
;функция поиска директории, в которой кликнули по файлу
Func GetDir( $Id,$Dir_Id)
Local $DirId=0
Local $DirResult=0
Local $EnumId=ETDirEnumOpen($Id)
While 1
Local $dir=ETDirEnumNext($EnumId)
If @error Then ExitLoop
$DirId=ETDirOpen($dir,$Id)
if hex($dir,4)=$Dir_Id Then
$DirResult=$DirId
ExitLoop
EndIf
$DirResult=GetDir( $DirId, $Dir_Id)
ETDirClose($DirId)
WEnd
ETDirEnumClose($EnumId)
Return $DirResult
EndFunc
;функция открытия файла на токене и вывода его содержимого в дочернее окно
Func ListFile($file, $Dir_Id)
$BindId=ETTokenBind($Reader[0])
$Result=JCTokenLock($BindId)
if $AppletID<>0 Then
JCSelectApplet($BindId,$AppletID)
EndIf
If $Pin <> 0 Then
$Result=JCTokenLogin($BindId,$Pin)
If $Result=False Then
$Result=JCTokenPinAttemptsGet($BindId)
MsgBox(0x10,$Appname,'Неверный PIN код'&@CRLF&'Количество попыток ввода PIN кода: '&$Result )
EndIf
EndIf
if StringLen($Dir_Id)>10 Then
$HDir=ETRootDirOpen($BindId,0)
Else
Local $HDir=GetDir(ETRootDirOpen($BindId,0), $Dir_Id)
EndIf
$SrcSubId=JCFileOpen(Dec ($file), $HDir)
$text=JCFileRead($SrcSubId)
GUICtrlSetData($Edit1, hex($text))
JCFileClose($SrcSubId)
ETDirClose($HDir)
ETTokenUnbind($BindId)
EndFunc
;обработка двойного щелчка мышью и получения имени файла на токене
While 1
if $iDoubleClick Then
Local $hItem = _GUICtrlTreeView_GetSelection($treeview)
if _GUICtrlTreeView_GetChildren($treeview, $hItem)=False Then
Local $hItem = _GUICtrlTreeView_GetSelection($treeview)
$sItemText = _GUICtrlTreeView_GetText($treeview, $hItem)
if StringInStr ($sItemText,"Dir")=0 Then
Local $text1=0
$text1=StringTrimLeft ( $sItemText, 6 )
Local $p=0
$p=StringInStr ($text1,"p:")
$sItemText=0
$sItemText=StringMid ( $text1, 1, $p-2 )
GUISetState(@SW_SHOW, $hChildWin)
GUISetOnEvent($GUI_EVENT_CLOSE,'onClose')
Local $DirID=_GUICtrlTreeView_GetParentHandle($treeview, $hItem)
Local $Dir= _GUICtrlTreeView_GetText($treeview, $DirID)
$text1=StringTrimLeft ( $Dir, 5 )
$Dir=$text1
ListFile($sItemText, $Dir)
EndIf
EndIf
$iDoubleClick = 0
EndIf
WEnd
Источники информации
eToken Developer’s Guide Version 3.50 (декабрь 2003)
DuH_Khv
Подскажите пожалуйста, каким конкретно образом данный скрипт помогает вам в решении поставленной задачи?
DWarlock Автор
Создание сущностей это конечно просто для развлечения, скрипт позволяет сделать резервное копирование ключей (когда они там доступны в виде контейнера типа CryptoPro) на компьютер, а затем на другой токен, в том числе необязательно аналогичной модели.
DuH_Khv
Я так и подумал, но решил сначала уточнить.
Поделюсь с вами способом которым пользуюсь самостоятельно — возможно он вам тоже пригодится.
Существует такая утилита ImDisk Virtual Driver (распространяется под GNU GPL, BSD). В функционале этой софтиры есть возможность монтирования любого файла в качестве диска. В том числе представлять его в качестве Сьемного носителя (Removable Media).
2) Форматируем появившуюся в системе «Виртуальную флешку» стандартными средствами Windows в FAT.
3) При помощи оснастки КриптоПро выполняем обычную функцию «Скопировать» (Сервис — Скопировать). В качестве исходного контейнера указываем необходимый на токене — в качестве получателя указываем «Виртуальную флешку». КриптоПро воспринимает такой контейнер вполне адекватно как обычную флешку и создает копию ключа.
4) Извлекаем виртуальный контейнер через оснастку программы ImDisk Virtual Driver.
5) Переносим созданный файлик-виртуальную-флешку на другой компьютер.
6) Монтируем «Виртуальную флешку» через ImDisk Virtual Driver.
7) Производим обратное копирование контейнера закрытого ключа стандартными средствами Крипто-Про.