2017-06-23 12:01:16

Добавление SubjectSignTool в КриптоПро ЭЦП Browser plug-in

Про работу JavaScript КриптоПро

КриптоПро


Пишу, как говорится, о наболевшем, я от всей души ненавижу создателей браузерного плагина crypto-pro, но об этом в PS, а теперь к делу. В процессе формирования запроса на сертификат (CSR) силами cadesplugin нам нужно добавить в него расширение SubjectSignTool (OID.1.2.643.100.111) со значением в виде строки (UTF8String).

На первый взгляд все кажется не сложно: создать объект X509Enrollment.CObjectId и инициализировать его значением, создать объект X509Enrollment.CX509Extension и инициализировать его созданным OID и нужной строкой с правильным EncodingType. Сделать это правда придется два раза, для синхронного и асинхронного режима, но об этом тоже в PS. На практике все не так просто, и приходится погружаться в низкоуровневое кодирование ASN.1.


Суровая реальность заставляет нас откусить первые 127 символов от нашей строки (чтоб не попасть на дополнительные заморочки с кодированием), обычно этого вполне достаточно. Далее перевести в массив байт UTF8, добавить служебные байты ASN.1, перевести обратно в строку и сразу закодировать в base64 (без "сразу" все сломается и точно не будет работать в хроме на винде). Ну и наконец можно инициализировать наш CX509Extension полученной строкой с EncodingType.XCN_CRYPT_STRING_BASE64. На практике у меня получился вот такой кусок кода для асинхронного режима:

...
}).then(function(){
return Promise.all([
    cadesplugin.CreateObjectAsync('X509Enrollment.CX509Extension'),
        cadesplugin.CreateObjectAsync('X509Enrollment.CObjectId')
    ]);
}).then(function(objects){
oSubjectSignTool = objects[0];
oOID = objects[1];
    return oOID.InitializeFromValue('1.2.643.100.111');
}).then(function(){           
var shortName = sCSPName.slice(0, 127);
    var utf8arr = shortName.toUtf8ByteArray();
    var UTF8StringTag = 0x0c; // 12, UTF8String
    utf8arr.unshift(UTF8StringTag, utf8arr.length);
    var base64String = btoa(String.fromCharCode.apply(null, new Uint8Array(utf8arr)));
    return oSubjectSignTool.Initialize(oOID, EncodingType.XCN_CRYPT_STRING_BASE64, base64String);
}).then(function(){
...

Чтоб это все работало придется немного подготовиться:

  • Написать String.prototype.toUtf8ByteArray, взять можно отсюда.
  • Убедится что в браузере есть нативная поддержка кодирования в base64, функция btoa.
  • Скопировать себе структуру EncodingType отсюда.
  • Почитать как делают коллеги на профильном форуме.

Угробив кучу времени на получение бесценного опыта, я задаюсь одним вопросом: почему в рамках плагина нельзя было сделать метод, который просто создает/добавляет Extension из двух строк: OID и значение, со всем кодированием внутри, как сделано у других?

Ну и соответственно имея несколько таких методов под типовые задачи, получился бы хороший продукт, а не то, под что приходится писать собственную обертку, чтоб можно было хоть как-то пользоваться.

P.S.

Да, я от всей души ненавижу тех, кто сделал крипто-про плагин таким, какой он есть! Ну вот зачем делать синхронный и асинхронный режим, зависящий от браузера, и заставлять разработчика всегда(!) писать два варианта одного кода?! Ну разве нельзя перенять опыт у коллег/конкурентов из JaCarta или RuToken и сделать хотя бы так же удобно?! Почему нельзя опубликовать на своем громко звучащем CPDN качественную, подробную документацию для плагина, снабдить ее достаточным количеством примеров, а не отсылать в MSDN по 10 раз с каждой страницы?!

Так или иначе, но чтоб разрабатывать что-то для cadesplugin приходится пользоваться не официальной документацией, а добывать информацию при помощи гугла, форума и такой-то матери. И конечно, всегда приходится делать две версии кода, чтоб обеспечить максимальное покрытие браузеров, о том чем это плохо думаю нет смысла описывать.

Мое знакомство с КриптоПро началось достаточно давно, как с "де-факто" стандарта российской криптографии, правда сильно ущербного, привязывающего потребителя к IE под windows. За годы прошедшие с того момента, конечно, появилась поддержка нормальных браузеров и других ОС, но тем не менее, сейчас КриптоПро не является лидером отрасли благодаря качеству продукта, а всего лишь самый "толстый" игрок на рынке :(