Криптографический АРМ на базе стандартов с открытым ключом для платформы Android

от автора

imageПришло время продемонстрировать как криптографический АРМ на базе стандартов с открытым ключом cryptoarmpkcs работает на одной из мобильных платформ, а именно Android.
Концепция, которая закладывалась при разработке утилиты cryptoarmpkcs, состоит в том, чтобы пользователь просто должен минимум неудобств при создании и проверке электронной подписи. Именно поэтому мы предлагаем в качестве ключевого носителя для личного сертификата использовать криптографические токены PKCS#11 и/или защищенные контейнеры PKCS#12. Надо сказать, что использование PKCS#12 во многих случаях оказывается чуть ли не единственно возможным, например, когда у тех же токенов PKCS#11 не оказывается поддержки для тех или иных платформах. Вот и мы решили начать портирование утилиты cryptoarmpkcs на платформу Android с поддержки защищенных контейнеров PKCS#12.
Сразу отметим, что поскольку проект делался на платформе C и Tcl/Tk, то портирование не вызвало каких-либо принципиальных трудностей. Это стало возможным еще благодаря технологии Androwish. С разворачиванием и настройкой среды никаких проблем не возникло (моя рабочая среда это Linux — Mageia-7.0). Приведу только один скрипт, для разворачивания Android Command Line Tools (sdk-tools-linux-xxxx.zip):

#!/bin/sh if [ $# -ne 1   ]     then  	echo "./InstallAndroidSDK.sh <sdk-tools-linux-xxxxxxxx.zip>" 	echo "Не указан архив или число параметров больше 1" 	exit 1 fi if [ ! -f $1 ]     then  	echo "./InstallAndroidSDK.sh <sdk-tools-linux-xxxxxxxx.zip>" 	echo "архив $1 отсутствует" 	exit 1 fi #Распаковываем SDK-TOOLS в папку tools #unzip sdk-tools-linux-4333796.zip unzip $1 #Создаем папку android-sdk-linux mkdir android-sdk-linux #Перемещвем папку tools в android-sdk-linux mv tools android-sdk-linux cd android-sdk-linux/tools/bin ./sdkmanager "platform-tools" "platforms;android-29"  

Самое замечательное то, что в среду Androwish входит два интерпретатора undrowish-xxx и vanillawish-xxx полностью идентичных по составу «балалаек» (пакетов), входящих собственно в состав Androwish. Различие между undrowish и vanillawish состоит в том, что в vanillawish бэкэнд на основе SDL / AGG / freetype:

Наличие этих двух утилит позволяет разрабатывать приложение без использования самого Android-а и его эмулятора с максимальным приближением к реальному устройству. В первую очередь это, конечно, undroidwish-xxx.
Собственно пользовательский пакет для Android собирается в среде AWSDK. Дерево вашего проекта должно перенесено а папку ~/AWSDK/assets/app. При этом главный модуль вашего проекта должен быть переименован в main.tcl. Если вы используете дополнительные балалайки с динамическими библиотеками, то библиотеки необходимо положить в папки ~/AWSDK/libs/x86 для эмулятора и ~/AWSDK/libs/armeabi для реального устройства.
После этого достаточно выполнить команду:

$wish ~/AWSDK/tools/bones

и следовать ее указаниям:

Собранный apk-пакет будет лежать в папке ~/AWSDK/build/outputs/apk.
Если у вас подключено реальное устройство или эмулятор, то пакет можно сразу установить.
При этом реальное устройство должно находиться в режиме отладки.
Но вернемся собственно к приложению. Что же пришлось в нем изменить.
Естественно, в первую очередь изменения связаны с размерами экрана. Пришлось перепроектировать главное (стартовое окно). В итоге, вместо одного окна на обычном компьютере:

появилось три окна на Android:

Первое окно является информационным. Условно оно разбивается на несколько частей. Первая часть, находящаяся вверху, содержит название утилиты и ее логотип.
Далее идет логотип производителя, информационная справка и завершают страницу три кнопки.
Страница написана с использованием компонента canvas (холста). На странице используются кнопки двух видов: одна в виде полупрозрачного прямоугольника (средняя), а две другие в виде прямоугольника с закругленными углами. Для создания кнопок с закругленными углами была задействована «балалайка» tkpath. Лично на меня эта балалайка произвела очень хорошее впечатление. Естественно при работе с холстом (canvas) львиную долю кода занимает геометрия. Ниже приводится скрипт create_titul_page.tcl для создания первой страницы приложения. Каждый желающий может его подредактировать под свое видение.

Скрипт create_titul_page.tcl

package require Tk package require tkpath 0.3.0  global mydir set mydir [file dirname [info script]] #Грузим картинки #Логотип продукта image create photo logo_product -file [file join $mydir "imageme" "validcertkey_51x24.png"]  #Логотип производителя image create photo logo_orel -file [file join $mydir "imageme" "я_орел_425x200.png"] -format "png -alpha 1.0" #Андроида с tcl/tk image create photo logo_and -file [file join $mydir "imageme" "AndTk_inv_147x173.png"] -format "png -alpha 1.0" #Свиток опечатанный image create photo svitok -file [file join $mydir "imageme" "blue_svitok.png"] -format "png -alpha 1.0" #Плитка image create photo tileand -file [file join $mydir "imageme" "tile_green_and_32x32.png"] -format "png -alpha 1.0" #Увеличить/уменьшить (отрицательное значение - уменьшение) proc scaleImage {im xfactor {yfactor 0}} {    set mode -subsample    if {$xfactor>=0 && $yfactor>=0} {        set mode -zoom    } else { 	set xfactor [expr $xfactor * -1]    }    if {$yfactor == 0} {set yfactor $xfactor}    set t [image create photo]    $t copy $im    $im blank    $im copy $t -shrink $mode $xfactor $yfactor    image delete $t }  proc createtile {w  backg} {     image create photo tiled     tiled copy $backg -to 0 0 $::scrwidth $::scrheight -shrink     $backg copy tiled     image delete tiled # Мостим холст     $w create image 0 0  \       -image $backg  \       -anchor nw }  proc create_rectangle  {canv img x1 y1 x2 y2 color alfa {wbd 0} {colorline black} } {     image create photo $img -format "default -colorformat  rgb"     set rgb1 [winfo rgb $canv $color]     set cr  [lindex $rgb1 0]     set cg  [lindex $rgb1 1]     set cb  [lindex $rgb1 2]     set fill [format "#%04x%04x%04x" $cr $cg $cb ] #Создаем цветной праямоугольник     $img put $fill -to 0 0 [expr {$x2 - $x1}] [expr {$y2 -$y1}] #Сохраняем картинку     set dimg [$img data -format png] #Создаем image с учетом alpha канала     image create photo $img -data $dimg -format "png -alpha $alfa" #    $img put [list $rgb1] -to 0 0 [expr {$x2 - $x1}] [expr {$y2 -$y1}] #Отображаем цветной прямоугольник     set imgr [$canv create image $x1 $y1 -image $img -anchor nw]      set cc [subst {butImg $img}]     $canv bind $imgr <ButtonPress-1> $cc #Оконтовка вокруг цветного прямоугольника     if {$wbd > 0 } { 	set item [$canv create rect $x1 $y1 $x2 $y2 -outline $colorline -width $wbd ] 	$canv bind $item <ButtonPress-1> $cc     }    return $imgr }  proc butImg {img} {     tk_messageBox -title "Кнопка" -icon info -message "Нажали кнопку=$img" -detail "::screenwidth=$::scrwidth\n::screenheight=$::scrheight" -parent .     if {$img == "exit"} { 	set answer [tk_dialog .dialog2 "Конец работы" "Вы действительно\nхотите выйти?" question 0 "Да" "Нет" ] 	if {$answer == 0} {     	    exit 	}	     } }  proc page_titul {fr  logo_manufacturer} {     global mydir #Создаем холст на весь экран     tkp::canvas $fr.can -borderwidth 0 -height [winfo screenheight .] -width [winfo screenwidth .] -relief flat #Мостим холст плиткой      createtile "$fr.can"  "tileand"     pack $fr.can  -anchor center -expand 1 -fill both -side top  -padx 0 -pady 0 #Вычисляем координаты для логотипа производителя #update чтобы обновилась информация в БД об окнах     update #    set aa [winfo height $fr.labtitul]     set aa $::padly #Центрируем логотип разработчика     set ha [image width $logo_manufacturer]     set xman [expr {($::scrwidth - $ha) / 2 }]     $fr.can create image $xman $aa -image $logo_manufacturer -anchor nw -tag tag_logo      set blogo [$fr.can bbox tag_logo]     set wexit [lindex $blogo 3]     if {$::typetlf } { 	set dlx [expr {$::padlx / 1}] 	$fr.can create text [expr $dlx + 6] [expr {$wexit + $::padly + 6}] -anchor nw -text "Электронная подпись" -fill black -font {{Roboto Condensed Medium} 15 } 	$fr.can create text $dlx [expr {$wexit + $::padly}] -anchor nw -text "Электронная подпись" -fill white -font {{Roboto Condensed Medium} 15 } -tag id_text0 	update 	set blogo [$fr.can bbox id_text0] 	set wexit [lindex $blogo 3] 	$fr.can create text [expr $dlx + 4] [expr {$wexit + $::padly + 4 - 80}] -anchor nw -text "для платформы Android" -fill black -font {{Roboto Condensed Medium} 13} 	$fr.can create text $dlx [expr {$wexit + $::padly - 80}] -anchor nw -text "для платформы Android" -fill white -font {{Roboto Condensed Medium} 13} -tag id_text1 	set blogo [$fr.can bbox id_text1] 	set wexit [lindex $blogo 3] 	$fr.can create text [expr $dlx + 3] [expr {$wexit + $::padly + 3 - 50}] -anchor nw -text "№ 63 ФЗ \"Об электронной\nподписи от 6 апреля 2011 года\"" -fill black -font {{Roboto} 10} 	$fr.can create text $dlx [expr {$wexit + $::padly - 50}] -anchor nw -text "№ 63 ФЗ \"Об электронной\nподписи от 6 апреля 2011 года\"" -fill white -font {{Roboto} 10} -tag id_text2 	set blogo [$fr.can bbox id_text2] 	set wexit [lindex $blogo 3] 	$fr.can create text [expr $dlx + 2] [expr {$wexit + $::padly + 2 - 40}] -text "Авторы: В.Н. Орлов\nhttp://soft.lissi.ru, http://www.lissi.ru\n+7(495)589-99-53\ne-mail: support@lissi.ru\n\n" \ 	-anchor nw -fill black  -font {{Roboto} 9} 	$fr.can create text $dlx [expr {$wexit + $::padly - 40}] -text "Авторы: В.Н. Орлов\nhttp://soft.lissi.ru, http://www.lissi.ru\n+7(495)589-99-53\ne-mail: support@lissi.ru\n\n" \ 	-anchor nw -fill white -tag id_text3  -font {{Roboto} 9}     } else { 	$fr.can create text [expr $::padlx + 2] [expr {$wexit + $::padly + 2}] -anchor nw -text "Электронная подпись" -fill black -font {{Nimbus Sans Narrow} 20} 	$fr.can create text $::padlx [expr {$wexit + $::padly}] -anchor nw -text "Электронная подпись" -fill white -font {{Nimbus Sans Narrow} 20} -tag id_text0 	set blogo [$fr.can bbox id_text0] 	set wexit [lindex $blogo 3] 	$fr.can create text [expr $::padlx + 2] [expr {$wexit + $::padly + 2 - 20}] -anchor nw -text "для платформы Android" -fill black -font {{Nimbus Sans Narrow} 18} 	$fr.can create text $::padlx [expr {$wexit + $::padly - 20}] -anchor nw -text "для платформы Android" -fill white -font {{Nimbus Sans Narrow} 18} -tag id_text1 	set blogo [$fr.can bbox id_text1] 	set wexit [lindex $blogo 3] 	$fr.can create text [expr $::padlx + 2] [expr {$wexit + $::padly + 2}] -anchor nw -text "№ 63 ФЗ \"Об электронной\nподписи от 6 апреля 2011 года\"" -fill black -font {{Nimbus Sans Narrow} 14} 	$fr.can create text $::padlx [expr {$wexit + $::padly}] -anchor nw -text "№ 63 ФЗ \"Об электронной\nподписи от 6 апреля 2011 года\"" -fill white -font {{Nimbus Sans Narrow} 14} -tag id_text2 	set blogo [$fr.can bbox id_text2] 	set wexit [lindex $blogo 3] 	$fr.can create text [expr $::padlx + 1] [expr {$wexit + $::padly + 1}] -text "Авторы: В.Н. Орлов\nhttp://soft.lissi.ru, http://www.lissi.ru\n+7(495)589-99-53\ne-mail: support@lissi.ru\n\n" \ 	-anchor nw -fill black  -font {{Nimbus Sans Narrow} 12} 	$fr.can create text $::padlx [expr {$wexit + $::padly}] -text "Авторы: В.Н. Орлов\nhttp://soft.lissi.ru, http://www.lissi.ru\n+7(495)589-99-53\ne-mail: support@lissi.ru\n\n" \ 	-anchor nw -fill white -tag id_text3  -font {{Nimbus Sans Narrow} 12} -tag id_text3 	set blogo [$fr.can bbox id_text2]     }     set blogo [$fr.can bbox id_text3]     set wland [lindex $blogo 3]     $fr.can create image $::padlx $wland -image logo_and -anchor nw -tag tag_land     set ha [image height logo_and]     set wa [image width logo_and]     set ha1 [expr {$ha - ($ha / 2 ) }]     $fr.can create image [expr {$wa - 80 }] [expr {$wland + $ha1}] -image svitok -anchor nw -tag tag_land     if {$::typetlf} { 	set x1 [expr {$::padlx / 2}] 	set y1 [expr {$wland + 120}] 	set x2 [expr {$::::scrwidth - $x1}] 	set y2 [expr {$y1 + 120}] 	set wd 8 	set rr 18     } else { 	set x1 [expr {$::padlx / 2}] 	set y1 [expr {$wland + 40}] 	set x2 [expr {$::::scrwidth - $x1}] 	set y2 [expr {$y1 + 40}] 	set wd 4 	set rr 6     }      set g5 [$fr.can gradient create linear -stops {{0 lightgreen} {1 green}}]      set S3 [$fr.can style create -stroke "skyblue" -fill  $g5 -strokewidth $wd  -fillopacity 0.6]     set im1 [$fr.can create prect $x1 $y1 $x2 $y2 -rx $rr -style $S3]     $fr.can bind $im1 <ButtonPress-1> {butImg "img1"} #Печатаем техт     set blogo [$fr.can bbox $im1]     set by2 [lindex $blogo 3]     set by1 [lindex $blogo 1]     set bb [expr {($by2 - $by1) / 2}]     set bx2 [lindex $blogo 2]     set bx1 [lindex $blogo 0]     set bbx [expr {($bx2 - $bx1) / 2}]     set txt1 [$fr.can create text [expr {$x1 + $::padlx * 2}] [expr {$y1 + 1 }] -anchor nw -text "Сайт разработчика" -fill black -font {{Arial} 10 normal}]  #Центрируем техт     set btxt1 [$fr.can bbox $txt1] #Смещение по оси Y     set ty2 [lindex $btxt1 3]     set ty1 [lindex $btxt1 1]     set tt [expr {$ty2 - $ty1}]     set tt [expr {$tt / 2}]     set offsy [expr {($by1 + $bb) - ($ty1 + $tt)}] #Смещение по оси X     set tx2 [lindex $btxt1 2]     set tx1 [lindex $btxt1 0]     set ttx [expr {$tx2 - $tx1}]     set ttx [expr {$ttx / 2}]     set offsx [expr {($bx1 + $bbx) - ($tx1 + $ttx)}]     $fr.can move $txt1 $offsx $offsy     $fr.can bind $txt1 <ButtonPress-1> {butImg "img1"}      if {$::typetlf} { 	set y1 [expr $y2 + 40] 	set x2 [expr {$::::scrwidth - $x1}] 	set y2 [expr {$y1 + 120}]     } else { 	set y1 [expr {$y1 + 60}] 	set x2 [expr {$::::scrwidth - $x1}] 	set y2 [expr {$y1 + 40}]     }     set im1 [create_rectangle $fr.can "but2" $x1 $y1 $x2 $y2 "#2b972d" 0.6 $wd "skyblue"] #Печатаем техт     set blogo [$fr.can bbox $im1]     set by2 [lindex $blogo 3]     set by1 [lindex $blogo 1]     set bb [expr {($by2 - $by1) / 2}]     set bx2 [lindex $blogo 2]     set bx1 [lindex $blogo 0]     set bbx [expr {($bx2 - $bx1) / 2}]     set txt1 [$fr.can create text [expr {$x1 + $::padlx * 2}] [expr {$y1 + 1 }] -anchor nw -text "Переход в основное меню" -fill black -font {{Roboto Condensed Medium} 12}]  #Центрируем текст     set btxt1 [$fr.can bbox $txt1] #Смещение по оси Y     set ty2 [lindex $btxt1 3]     set ty1 [lindex $btxt1 1]     set tt [expr {$ty2 - $ty1}]     set tt [expr {$tt / 2}]     set offsy [expr {($by1 + $bb) - ($ty1 + $tt)}] #Смещение по оси X     set tx2 [lindex $btxt1 2]     set tx1 [lindex $btxt1 0]     set ttx [expr {$tx2 - $tx1}]     set ttx [expr {$ttx / 2}]     set offsx [expr {($bx1 + $bbx) - ($tx1 + $ttx)}]     $fr.can move $txt1 $offsx $offsy     $fr.can bind $txt1 <ButtonPress-1> {butImg "but2"}     if {$::typetlf} { 	set x1 [expr {$::padlx / 2}] 	set y1 [expr $y2 + 40] 	set x2 [expr {$::::scrwidth - $x1}] 	set y2 [expr {$y1 + 120}]     } else { 	set x1 [expr {$::padlx / 2}] 	set y1 [expr {$y1 + 60}] 	set x2 [expr {$::::scrwidth - $x1}] 	set y2 [expr {$y1 + 40}]     }     set S3 [$fr.can style create -stroke skyblue -fill  $g5 -strokewidth $wd  -fillopacity 0.6]     set im1 [$fr.can create prect $x1 $y1 $x2 $y2 -rx $rr -style $S3]     set blogo [$fr.can bbox $im1]     $fr.can bind $im1 <ButtonPress-1> {butImg "exit"}     set by2 [lindex $blogo 3]     set by1 [lindex $blogo 1]     set bb [expr {($by2 - $by1) / 2}]     set bx2 [lindex $blogo 2]     set bx1 [lindex $blogo 0]     set bbx [expr {($bx2 - $bx1) / 2}]     set txt1 [$fr.can create text [expr {$x1 + $::padlx * 2}] [expr {$y1 + 1 }] -anchor nw -text "Конец работы" -fill black  -font {Arial 10 normal}]     $fr.can bind $txt1 <ButtonPress-1> {butImg "exit"}     set btxt1 [$fr.can bbox $txt1] #Смещение по оси Y     set ty2 [lindex $btxt1 3]     set ty1 [lindex $btxt1 1]     set tt [expr {$ty2 - $ty1}]     set tt [expr {$tt / 2}]     set offsy [expr {($by1 + $bb) - ($ty1 + $tt)}] #Смещение по оси X     set tx2 [lindex $btxt1 2]     set tx1 [lindex $btxt1 0]     set ttx [expr {$tx2 - $tx1}]     set ttx [expr {$ttx / 2}]     set offsx [expr {($bx1 + $bbx) - ($tx1 + $ttx)}]     $fr.can move $txt1 $offsx $offsy } #Собственно скрипт #Считываем размеры экрана set ::scrwidth [winfo screenwidth .] set ::scrheight [winfo screenheight .] set ::typetlf 0 #Проверяем, что это телефон if {$::scrwidth < $::scrheight} {     set ::typetlf 1 } set ::padls 20 set ::padlx 15 set ::padly 15 if {$::typetlf} { 	wm attributes . -fullscreen 1 	scaleImage icon_openfile_18x16 3 	scaleImage ::img::view_18x16 3 #Логотип производителя 	scaleImage logo_orel 2 #Логотип продуктв 	scaleImage logo_product 2 #Андроида tcl/tk 	scaleImage logo_and 3 #Свиток опечатанный 	scaleImage svitok 4 	set ::padls 50 	set ::padlx 75 	set ::padly 50 } else { #Конфигурирование виджета под смартфон     scaleImage logo_orel -2     set ::scrwidth 370     set ::scrheight 700     wm minsize . $::scrwidth $::scrheight     set geometr $::scrwidth     append geometr "x"     append geometr $::scrheight     append geometr "+0+0"     wm geometry . $geometr } #Создаем название продукта set name_product "CryptoArmPKCS-A"  label .labtitul -image logo_product -compound left -fg snow -text $name_product -font {Arial 10 bold} -anchor w  -width [winfo screenwidth .] -pady $::padls -padx 10 -bg #222222  pack .labtitul -anchor nw -expand 0 -fill x -side top  -padx 1 -pady 0 #Создаем стартовую страницу set i 0 ttk::frame .fr$i -pad 0 -padding 0 page_titul ".fr$i"  "logo_orel" pack .fr$i -side top -anchor center -expand 1 -fill both -side top  -padx 0 -pady 0  update

Для выполнения данного скрипта используем одну из утилит undroidwish или vanillawish:

$ /usr/local/bin64/undroidwish-e5dc71ed9d-linux64   create_titul_page.tcl 

или

$/usr/local/bin64/vanillawish-e5dc71ed9d-linux64  create_titul_page.tcl 

Результат представлен на первом скриншоте.

На второй странице перечисляется поддерживаемый утилитой cryptoarmpkcs-A функционал. Каждая строчка является кнопкой, при нажатии на которую будет отображена функциональная страница. Геометрия размещение кнопок на этой странице определяется шрифтом, который используется. Ниже приводится скрипт create_page_functions.tcl для создания второй/функциональной страницы приложения. Каждый желающий также может его подредактировать под свои функции.

Скрипт create_page_functions.tcl

package require Tk package require tkpath 0.3.0 global mydir set mydir [file dirname [info script]] #Увеличить/уменьшить (отрицательное значение - уменьшение) proc scaleImage {im xfactor {yfactor 0}} {    set mode -subsample    if {$xfactor>=0 && $yfactor>=0} {        set mode -zoom    } else { 	set xfactor [expr $xfactor * -1]    }     if {$yfactor == 0} {set yfactor $xfactor}    set t [image create photo]    $t copy $im    $im blank    $im copy $t -shrink $mode $xfactor $yfactor    image delete $t }  proc createtile {w  backg} {     image create photo tiled     tiled copy $backg -to 0 0 $::scrwidth $::scrheight -shrink     $backg copy tiled     image delete tiled # Мостим холст     $w create image 0 0  \       -image $backg  \       -anchor nw }  proc butCliked {num fr} {     pack forget  .fr1     set ::tekFrfunc $fr     pack $fr -side top -anchor center -expand 1 -fill both -side top  -padx 0 -pady 0      tk_dialog .dialog1 "Dear user:" "Button $num was clicked\nFr=$fr" info 0 OK  }  proc butImg {img} {     tk_messageBox -title "Кнопка" -icon info -message "Нажали кнопку=$img" -detail "::screenwidth=$::scrwidth\n::screenheight=$::scrheight" -parent .     if {$img == "exit"} { 	set answer [tk_dialog .dialog2 "Конец работы" "Вы действительно\nхотите выйти?" question 0 "Да" "Нет" ] 	if {$answer == 0} {     	    exit 	}	     } }  proc butReturn {} {     pack forget  $::tekFrfunc     pack .fr1 -side top -anchor center -expand 1 -fill both -side top  -padx 0 -pady 0  #    tk_dialog .dialog1 "Dear user:" "Button $num was clicked\nFr=$fr" info 0 OK  }  proc page_func {fr tile titul functions} { #Кнопки  меню     upvar $functions but #Создаем шрифт для кнопок     if {$::typetlf} { 	set feFONT_button "-family {Roboto} -size 9 -weight bold -slant roman" 	set widl 10     } else { 	set feFONT_button "-family {Arial} -size 12 -weight bold -slant roman" 	set widl 5     }     catch {font delete fontTEMP_drawer}     eval font create fontTEMP_drawer  $feFONT_button #Вычисляем максимальныю длину текста     set drawerCNT 0     set strMaxWidthPx 15     set Ndrawers [expr {[array size but] - 1}]     while { $drawerCNT <= $Ndrawers } { 	set strWidthPx [font measure fontTEMP_drawer "$but($drawerCNT)"] 	if { $strWidthPx > $strMaxWidthPx } {     	    set strMaxWidthPx $strWidthPx 	} 	incr drawerCNT     }     set drawerWidthPx [expr $strMaxWidthPx + 10]     set xxx [expr {($::::scrwidth - $drawerWidthPx) / 2}]      if {$fr != ".fr1"} { 	set hret [expr $::scrheight / 4]     } else { 	set hret $::scrheight     } 	set hret [expr $::scrheight / 4]     tkp::canvas $fr.can -borderwidth 0 -height $hret -width $::scrwidth -relief flat #Мостим холст плиткой      createtile "$fr.can"  $tile     pack $fr.can  -anchor center -expand 1 -fill both -side top  -padx 0 -pady 0     if {$titul != "" } { 	set allfunc $titul 	catch {font delete fontTEMP_titul} 	set font_titul "-family {Roboto Condensed Medium} -size 15"         eval font create fontTEMP_titul  $font_titul 	set funcWidthPx [font measure fontTEMP_titul "$allfunc"] 	set dlx [expr {($::::scrwidth - $funcWidthPx) / 2}]  	$fr.can create text [expr $dlx + 6] [expr {6 + 6}] -anchor nw -text "$allfunc" -fill black -font fontTEMP_titul 	$fr.can create text $dlx 6 -anchor nw -text "$allfunc" -fill white -font fontTEMP_titul -tag id_text0 	set blogo [$fr.can bbox id_text0] 	set boxbut [expr ([lindex $blogo 3] + 6 + 6)]     } else { 	set boxbut [expr 6 + 6]     } #Вычисляем самый широкий текст у кнопок #См. выше #Размещаем кнопки     set BDwidth_canvas 0      set maxTextHeightPx [font metrics fontTEMP_drawer -linespace]       set maxTextHeightPx [expr {$maxTextHeightPx + ( $maxTextHeightPx / 2)}]      set drawerHeightPx $maxTextHeightPx      set xLocTextPx [expr {($::::scrwidth - $drawerWidthPx) / 2}]      set yLocTextPx [expr $BDwidth_canvas + ($drawerHeightPx / 2) + $boxbut]     set canvasHeightPx [expr $Ndrawers * $drawerHeightPx]      set drawerCNT 0     set Ndrawers [expr {[array size but] - 1}]     while { $drawerCNT <= $Ndrawers } {       set yLineLocPx [ expr (( $drawerCNT ) * $drawerHeightPx + $boxbut)] #Линия перед текстом       $fr.can create line \          $xLocTextPx $yLineLocPx \          [expr $drawerWidthPx + $xLocTextPx] $yLineLocPx \          -fill "#a0a0a0" -width $widl        $fr.can create text [expr $xLocTextPx + 5] $yLocTextPx \ 	-anchor w \         -font fontTEMP_drawer \         -text "$but($drawerCNT)" \         -tag textlineTag($drawerCNT)        if {$drawerCNT == 0} { 	    if {$fr == ".fr1"} { 		$fr.can bind textlineTag($drawerCNT)  <ButtonRelease-1>   {butImg "but1"} 	    } else { 		$fr.can bind textlineTag($drawerCNT)  <ButtonRelease-1>   {butReturn} 	    } 	} else { 	    frame .fn$drawerCNT -background white -relief flat -pady 0 -padx 0 	    set titul $but($drawerCNT) 	    set cmd "$fr.can bind textlineTag($drawerCNT)  <ButtonRelease-1>   {butCliked $drawerCNT .fn$drawerCNT}" 	    set cmd [subst "$cmd"] 	    eval $cmd  	    set but1(0) "Возврат в основное меню" 	    page_func ".fn$drawerCNT" voda "$titul" "but1" 	}  	incr drawerCNT  	set yLocTextPx [ expr $yLocTextPx + $drawerHeightPx] #Завершаюшая линия 	if { $drawerCNT > $Ndrawers } {     	    set yLineLocPx [ expr (( $drawerCNT ) * $drawerHeightPx + $boxbut)]     	    $fr.can create line $xLocTextPx $yLineLocPx \             [expr $drawerWidthPx + $xLocTextPx] $yLineLocPx \             -fill "#a0a0a0" -width $widl 	}     } } #Собственно скрипт #Считываем размеры экрана set ::scrwidth [winfo screenwidth .] set ::scrheight [winfo screenheight .] set ::typetlf 0 #Проверяем, что это телефон if {$::scrwidth < $::scrheight} {     set ::typetlf 1 } set ::padls 20 set ::padlx 15 set ::padly 15 if {$::typetlf} { 	wm attributes . -fullscreen 1 #Логотип продуктв 	scaleImage logo_product 2 	set ::padls 50 	set ::padlx 75 	set ::padly 50 } else { #Конфигурирование виджета под смартфон     set ::scrwidth 370     set ::scrheight 700     wm minsize . $::scrwidth $::scrheight     set geometr $::scrwidth     append geometr "x"     append geometr $::scrheight     append geometr "+0+0"     wm geometry . $geometr }  #Грузим картинки image create photo voda -file [file join $mydir "imageme" "voda_400x800.png"] #Логотип продукта image create photo logo_product -file [file join $mydir "imageme" "validcertkey_51x24.png"]  #Создаем название продукта set name_product "CryptoArmPKCS-A"  label .labtitul -image logo_product -compound left -fg snow -text $name_product -font {Arial 10 bold} -anchor w  -width [winfo screenwidth .] -pady $::padls -padx 10 -bg #222222  pack .labtitul -anchor nw -expand 0 -fill x -side top  -padx 1 -pady 0 #Создаем страницы с функционалом set i 1 ttk::frame .fr$i -pad 0 -padding 0 #Кнопки основного меню set but(0) "Стартовая страница"  set but(1) "Подписать документ" set but(2) "Работаем с ЭП (PKCS7)"  set but(3) "Запрос на сертификат"  set but(4) "Просмотр запроса/сертификата"  set but(5) "Список криптомеханизмов" set but(6) "Просмотр ASN1-структуры"  set but(7) "Объекты токена"  set but(8) "Работаем с PKCS12/PFX"  set but(9) "Самоподписанный сертификат" set but(10) "Об Утилите/Дистрибутивы"  set but(11) "Создать Токены" set but(12) "Конфигурировние токена" if {$::typetlf} {     scaleImage voda 3 2 } #Создаем страницу с функционалом page_func ".fr$i" voda "Функционал" "but" #Отображаем страницу с функционалом pack .fr$i -side top -anchor center -expand 1 -fill both -side top  -padx 0 -pady 0 

Этот скрипт также готовит болванки для каждой функциональной кнопки:

Наполнение болванок ведется классическими и тематическими виджетами (labelframe, button и т.д.). Одну из таких заполненных балванок можно видеть на первом скриншоте справа. Посколько на первом этапе мы сосредоточились на работе с контейнером PKCS#12, то код практически без изменений был использован и для cryptoarmpkcs-A. На данном этапе реализованы следующие функции:
— подписать документ (Cades-BES, CAdes-T, CAdes-XLT1);
— работаем с ЭП (PKCS7), включая добавление подписанта;
— просмотр сертификатов/запросов на сертификаты:

— работаем с PKCS12/PFX;
— об утилите/Дистрибутивы:

Остальные функции больше связаны с токенами PKCS#11. Их портирование отложено на Новый Год. Планируется подключение программного токена и подключение к облаку токенов.
С точки зрения функционала практически все аналочично утилите cryptoarmpkcs. Но есть отдельные отличия. Например, после подписания документа, утилита спрашивает будет ли подпись проверяться на сайте Госуслуг:

При нажатии кнопки «Да» будет загружен браузер со страницей проверки подписи документов и сертификатов. Сразу оговоримся, что эта страница не очень рассчитана на экран смартфона. Это будет заметно при выборе подписи и, если подпись отсоединенная, файла с документом. Но если все хорошо, то мы получим положительный результат:

Следует иметь ввиду, что проверка как подписи, так и сертификата на сайте Госуслуг имеет смыл только если сертификат был получен в аккредитованном удостоверяющем центре (УЦ). В противном случае подпись всегда будет недействительной.
Для вызова браузера пришлось добавить пару строк в процедуру openUrl:

proc openURL {url} {   global typesys   global macos   #  global windowsOS #проверка, что утилита выполняется на смартфоне Android   if {$::typetlf} { #Запуск браузера  	borg activity android.intent.action.VIEW $url text/html  	return   } . . . }

Браузер на Android вызывается следующим образом:

borg activity android.intent.action.VIEW <URL> text/html 

Небольшая особенность есть при добавлении нового подписанта к ранее подписанному документу. Сертификат нового подписанта (вернее даже контейнер PKCS#12 с сертификатом и закрытым ключом) должен быть заранее выбран на странице «Подписать документ» или «Работаем с PKCS12/PFX», о чем утилита напомнит:

При длительных операциях как и прежде будут идти часы:

Осталось сказать откуда скачать дистрибутивы и Поздравить с наступающим Новым Годом и пожелать всем всего наилучшего в 2020 Году!
imageИтак, дистрибутивы для Linux, OS X, Windows и Android:


ссылка на оригинал статьи https://habr.com/ru/post/482574/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *