
Es hora de demostrar cómo la estación de trabajo criptográfica basada en
estándares de clave pública
cryptoarmpkcs funciona en una de las plataformas móviles, a saber, Android.
El concepto que se estableció durante el desarrollo de la utilidad cryptoarmpkcs es que el usuario debe experimentar un mínimo de inconvenientes al crear y verificar una firma electrónica. Es por eso que proponemos utilizar tokens criptográficos
PKCS # 11 y / o contenedores seguros
PKCS # 12 como medio clave para un certificado personal. Debo decir que el uso de PKCS # 12 en muchos casos es casi el único posible, por ejemplo, cuando los mismos tokens PKCS # 11 no brindan soporte para ciertas plataformas.
Así que decidimos comenzar a portar la utilidad cryptoarmpkcs a la plataforma Android con soporte para contenedores seguros PKCS # 12.
Inmediatamente, observamos que, dado que el proyecto se realizó en las plataformas C y Tcl / Tk, la transferencia no causó dificultades fundamentales. Esto fue posible gracias a la tecnología
Androwish . No hubo problemas con la implementación y la
configuración del entorno (mi entorno de trabajo es Linux - Mageia-7.0). Solo le daré un script para implementar las herramientas de línea de comandos de Android (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"
Lo más notable es que el entorno Androwish incluye dos intérpretes, undrowish-xxx y vanillawish-xxx, que son completamente idénticos en composición a los "balalaika" (paquetes) que en realidad son parte de Androwish. La diferencia entre nonrowish y vanillawish es que en vanillawish el backend se basa en SDL / AGG / freetype:

La presencia de estas dos utilidades le permite desarrollar una aplicación sin usar el propio Android y su emulador con la máxima aproximación al dispositivo real. En primer lugar, por supuesto, undroidwish-xxx.
El paquete de Android personalizado en sí está construido en el entorno AWSDK. El árbol de su proyecto debe moverse y la carpeta ~ / AWSDK / assets / app. En este caso, el módulo principal de su proyecto debe renombrarse a main.tcl. Si usa balalaikas adicionales con bibliotecas dinámicas, las bibliotecas deben colocarse en las carpetas ~ / AWSDK / libs / x86 para el emulador y ~ / AWSDK / libs / armeabi para el dispositivo real.
Después de eso, solo ejecuta el comando:
$wish ~/AWSDK/tools/bones
y sigue sus instrucciones:

El paquete apk recopilado estará en la carpeta ~ / AWSDK / build / salidas / apk.
Si tiene un dispositivo o emulador real conectado, el paquete se puede instalar de inmediato.
En este caso, el dispositivo real debe estar en modo de depuración.
Pero volvamos a la aplicación en sí. Lo que tenía que ser cambiado en eso.
Naturalmente, en primer lugar, los cambios están relacionados con el tamaño de la pantalla. Tuve que rediseñar el principal (ventana de inicio). Como resultado, en lugar de una sola ventana en una computadora normal:

Tres ventanas aparecieron en Android:

La primera ventana es informativa. Convencionalmente, se divide en varias partes. La primera parte, ubicada en la parte superior, contiene el nombre de la utilidad y su logotipo.
Luego viene el logotipo del fabricante, la ayuda de información y tres botones que completan la página.
La página se escribe utilizando el componente de lienzo. La página utiliza dos tipos de botones: uno en forma de rectángulo translúcido (en el centro) y los otros dos en forma de rectángulo redondeado. Para crear botones con esquinas redondeadas,
se utilizó el tkpath "balalaika". Personalmente, esta balalaika me causó una muy buena impresión. Naturalmente, cuando se trabaja con lienzo, la mayor parte del código es la geometría. El siguiente es el script create_titul_page.tcl para crear la primera página de la aplicación. Todos pueden editarlo para adaptarse a su visión.
Script create_titul_page.tcl package require Tk package require tkpath 0.3.0 global mydir set mydir [file dirname [info script]]
Para ejecutar este script, use una de las utilidades undroidwish o vanillawish:
$ /usr/local/bin64/undroidwish-e5dc71ed9d-linux64 create_titul_page.tcl
o
$/usr/local/bin64/vanillawish-e5dc71ed9d-linux64 create_titul_page.tcl
El resultado se muestra en la primera captura de pantalla.
La segunda página enumera la funcionalidad admitida por la utilidad cryptoarmpkcs-A. Cada línea es un botón, cuando se hace clic, se mostrará una página funcional. La geometría de los botones en esta página está determinada por la fuente utilizada. El siguiente es el script create_page_functions.tcl para crear la segunda página / funcional de la aplicación. Todos también pueden editarlo para sus funciones.
Script 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
Este script también prepara espacios en blanco para cada botón de función:

Los espacios en blanco están llenos de widgets clásicos y temáticos (marco de trabajo, botón, etc.). Uno de estos lienzos rellenos se puede ver en la primera captura de pantalla a la derecha. Como en la primera etapa nos centramos en trabajar con el contenedor PKCS # 12, el código se usó casi sin cambios para cryptoarmpkcs-A. En esta etapa, se implementan las siguientes funciones:
- Firme el documento (Cades-BES, CAdes-T, CAdes-XLT1);
- Trabajamos con ES (PKCS7), incluida la adición de un firmante;
- Ver certificados / solicitudes de certificados:

- Trabajamos con PKCS12 / PFX;
- Sobre utilidad / distribuciones:

Otras funciones están más relacionadas con los tokens PKCS # 11. Su portabilidad se pospone para el Año Nuevo. Se planea conectar un token de software y conectarse a una
nube de tokens .
Desde el punto de vista de la funcionalidad, casi todo es similar a la utilidad cryptoarmpkcs. Pero hay algunas diferencias. Por ejemplo, después de firmar un documento, la utilidad pregunta si la firma se verificará en el sitio web de los Servicios del Estado:
Cuando haga clic en Sí, se cargará un navegador con una página para verificar la firma de documentos y certificados. Inmediatamente haga una reserva de que esta página no está muy diseñada para la pantalla de un teléfono inteligente. Esto se notará al elegir una firma y, si la firma se desconecta, el archivo con el documento. Pero si todo está bien, obtendremos un resultado positivo:

Debe tenerse en cuenta que la verificación tanto de la firma como del certificado en el sitio web del Servicio Estatal solo se elimina si el certificado se recibió en un centro de certificación acreditado (
CA ). De lo contrario, la firma siempre será inválida.
Para llamar al navegador, tuve que agregar un par de líneas al procedimiento openUrl:
proc openURL {url} { global typesys global macos # global windowsOS #, Android if {$::typetlf} { # borg activity android.intent.action.VIEW $url text/html return } . . . }
El navegador de Android se invoca de la siguiente manera:
borg activity android.intent.action.VIEW <URL> text/html
Una pequeña característica es cuando se agrega un nuevo firmante a un documento firmado previamente. El certificado del nuevo firmante (o más bien, incluso el contenedor PKCS # 12 con el certificado y la clave privada) debe seleccionarse previamente en la página "Firmar el documento" o "Trabajar con PKCS12 / PFX", que la utilidad le recordará:
Con operaciones a largo plazo, el reloj continuará como antes:
¡Queda por decir dónde descargar distribuciones y Feliz Año Nuevo y desearles a todos lo mejor para 2020!

Entonces, distribuciones para Linux, OS X, Windows y Android: