Всем доброго времени суток.

Так уж сложилось исторически, что электронные ключи организаций нашего небольшого холдинга для программы электронного документооборота SBIS были импортированы в реестр windows каждой рабочей станции, каждого пользователя.
При создании нового рабочего места выгружался куст с ключами из ветки Crypto-Pro и импортировался новому пользователю.
На терминальном сервере, понял, что такое недопустимо и решил выгрузить все ключи на флешку и разрешить в Crypto-Pro внешние накопители.

Теперь при создании новых пользователей на терминальном сервере никаких телодвижений с электронными ключами делать не нужно.

Проблема была в том, что нужно конвертировать ASCII ключи из реестра в 16 ричные файлы.
Возможно я плохо умею «гуглить», но готовых решений по теме не нашел, по этому сделал собственный скриптик на bash.
Может, кому то пригодится.

Небольшое описание.
Ключи находятся в ветке реестра — [HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Crypto Pro\Settings\Users\SID-пользователя\Keys\Название-ключа]

Структура ключа в выгруженной ветке реестра:
«name.key»=hex:10,d5…
«header.key»=hex:20,42,19,…
«primary.key»=hex:30,12
«masks.key»=hex:30,23
«primary2.key»=hex:30,12…
«masks2.key»=hex:30,56,10…

В качестве параметра скрипту необходимо указать файл с выгруженными ключами из реестра (например keys.reg).
В результате работы скрипта создастся папка keys в корневой директории из которой запускали скрипт и внутри нее папки с названием ключей. Папки с названием ключей будут содержать по 6 файлов — name.key, header.key, primary.key, primary2.key, masks.key, masks2.key.

#!/bin/bash

path=./
temp=$path/temp

file[1]="name.key"
file[2]="masks.key"
file[3]="masks2.key"
file[4]="primary.key"
file[5]="primary2.key"
file[6]="header.key"

if [ ! -d "$temp" ]; then 
    mkdir "$temp"
fi

if [ ! -d "$path/keys" ]; then 
    mkdir "$path/keys"
fi

# CR to LF. Конвертируем файл в формат UNIX (Окончания строк LF, вместо CR)
dos2unix -n -q $1 $temp/$1

# Записываем имена всех ключей во временный файл
cat $temp/$1 | grep -E -o 'Keys\\\w+]' | sed -E 's/Keys\\//; s/]//' > $temp/keysname

while read key
   do
     # Записываем полное содержимое ключа в отдельный файл с его именем
     cat $temp/$1 | sed -e '/./{H;$!d;}' -e "x;/$key]/!d" | sed -n "/$key]/!p" > $temp/$key
	
	# Разделяем ключи (name, primary, masks, header...) и записываем в отдельные файлы в папку с именем ключа 
	if ! [ -d "$path/keys/$key" ]; then
              mkdir "$path/keys/$key"
	fi

	for i in {1..6}; 
   	 do 
   	 hex=$(cat $temp/$key | tr -d '\n' | sed -E 's/\\//g; s/ //g; s/\$//g' | grep -E -o "${file[$i]}\"=hex:(\w{2},?)+?" | sed -E "s/${file[$i]}\"=hex://; s/,//g" | sed -E 's/\w{2}/\\x&/g')
   	 echo -e -n "$hex" > "$path/keys/$key/${file[$i]}"

	 # LF to CR ??? 
	 # sed 's/$'"/`echo \\\r`/" "$path/keys/${file[$i]}" > "$path/keys/${file[$i]}"
	done
done < $temp/keysname

# Очистка временных файлов
if [ -d "$temp" ]; then 
   rm -rf "$temp"
fi

exit 0

Комментарии (9)


  1. JIghtuse
    30.07.2015 17:06
    +1

    Недопонял, зачем это здесь, и кому это можно понадобиться, ну да ладно.
    Зачем-то ваш скрипт поправил. Мне кажется, стало немного читабельнее.

    Скрытый текст
    #!/bin/bash
    
    path=./
    temp=$path/temp
    key_files="name.key masks.key masks2.key primary.key primary2.key header.key"
    original_file="$temp/$1"
    
    mkdir -p "$temp"
    mkdir -p "$path/keys"
    
    # CR to LF. Конвертируем файл в формат UNIX (Окончания строк LF, вместо CR)
    dos2unix -n -q "$1" "$original_file"
    
    # Записываем имена всех ключей во временный файл
    grep  -E -o 'Keys\\\w+]' "$original_file" | sed -E 's/Keys\\//; s/]//' > $temp/keysname
    
    while read key
       do
         # Записываем полное содержимое ключа в отдельный файл с его именем
         cat $original_file | sed -e '/./{H;$!d;}' -e "x;/$key]/!d" | sed -n "/$key]/!p" > $temp/$key
        
        # Разделяем ключи (name, primary, masks, header...) и записываем в отдельные файлы в папку с именем ключа 
        mkdir -p "$path/keys/$key"
    
        for file in $key_files;
         do 
         hex=$(cat $temp/$key | tr -d '\n' | sed -E 's/\\//g; s/ //g; s/\$//g' | grep -E -o "$file\"=hex:(\w{2},?)+?" | sed -E "s/$file\"=hex://; s/,//g" | sed -E 's/\w{2}/\\x&/g')
         echo -e -n "$hex" > "$path/keys/$key/$file"
    
         # LF to CR ??? 
         # sed 's/$'"/`echo \\\r`/" "$path/keys/$file" > "$path/keys/$file"
        done
    done < $temp/keysname
    
    # Очистка временных файлов
    rm -rf "$temp"
    
    exit 0


    1. Bearpuh Автор
      30.07.2015 17:18

      За ликбез и поправки спасибо +1. Скрипты пишу не часто и конструкции получаются не очень красивые порой.
      Глупые и ненужные проверки тянутся еще из далекого прошлого, со времен borland pascal наверное.))


    1. Bearpuh Автор
      30.07.2015 17:23

      sed, кстати тоже может принимать данные из файла, без cat. Забыл про это.
      sed 'бла бла бла' <file


      1. ZyXI
        30.07.2015 18:41
        +1

        Это не имеет никакого отношения к sed. Перенаправление ввода/вывода — возможности оболочки. Sed будет просто использовать stdin, не увидев никакой разницы между < и cat (хотя она, вообще?то, есть: в случае с cat stdin будет подключен к pipe, в который cat закачивает данные, а в случае с < stdin будет связан с файлом: разница не только в наличии лишних действий со стороны cat, но и в том, что файл, к примеру, поддерживает fseek/ftell, а pipe — нет).


        1. Bearpuh Автор
          30.07.2015 18:51

          Полезно, но в вышеуказанном примере абсолютно «монопинисуально» — т.е. без разницы. )))
          Я не старался сделать чистый и оптимальный код с оптимальным быстродействием и «защитой от дурака». Ну да, может и некрасиво и не очень быстро, но работает. Работает, кстати, медленно — на моем i3 где то около секунды парсил 15 ключей.


          1. ZyXI
            30.07.2015 18:57

            Я тоже обычно пишу cat file | sed, потому что так удобнее менять sed на что?то ещё. Но вообще о том, как нужно писать — sed command file (только здесь sed будет открывать файл сам, а не пользоваться stdin), sed command <file, cat file | sed command или даже <file | sed command (zsh) — периодически разгораются жаркие споры. В том числе видел такое и на habrahabr.ru.


            1. Bearpuh Автор
              30.07.2015 19:03

              Честно говоря, никогда не лез в такие тонкости. Возможно впоследствии, когда нужна будет мегасупероптимизация по универсальности и быстродействию — вкурю и это. В любом случае, спасибо за ликбез.


              1. ZyXI
                30.07.2015 21:31

                Если нужна мегасупероптимизация, то проще переписать с использованием чего?то вроде Python+PyPy. А такие споры — погоня, как правило, за долями процентов (если только вы не догадались действительно написать <file | sed command с достаточно большим файлом — zsh почему?то на порядок медленнее cat в данном вопросе).


  1. xyyx
    31.07.2015 17:57

    Если мне память не изменяет, то можно делать все самим КриптоПро. Копируем закрытый ключ с реестра на флеху через панель управления. И получаем эти файлы на флехе.