Главная » Хабрахабр » Инфраструктура открытых ключей: GnuPG/SMIME и токены PKCS#11 с поддержкой российской криптографии

Инфраструктура открытых ключей: GnuPG/SMIME и токены PKCS#11 с поддержкой российской криптографии

diff -u KSBA_ORIG/cms.c KSBA/cms.c
--- KSBA_ORIG/cms.c 2013-03-15 23:26:38.000000000 +0400
+++ KSBA/cms.c 2018-07-19 08:24:48.774106713 +0300
@@ -1581,6 +1581,15 @@ Note that IDX is only used for consistency checks. */
+/* For GOST
+ r_sig = (sig-val
+ (gost
+ (r <mpi>)
+ (s <mpi>)
+ )
+ (hash <name_hash>))
+*/
+ gpg_error_t ksba_cms_set_sig_val (ksba_cms_t cms, int idx, ksba_const_sexp_t sigval) {
@@ -1588,6 +1597,7 @@ unsigned long n; struct sig_val_s *sv, **sv_tail; int i;
+ int gost; if (!cms) return gpg_error (GPG_ERR_INV_VALUE);
@@ -1615,6 +1625,11 @@ /* Break out the algorithm ID. */ if (!(n = snext (&s))) return gpg_error (GPG_ERR_INV_SEXP);
+ gost = 0;
+ if (n==4 && s[0] == 'g' && s[1] == 'o' && s[2] == 's' && s[3] == 't') {
+ /* kludge to allow "gost" to be passed as algorithm name */
+ gost = 1;
+ } sv = xtrycalloc (1, sizeof *sv); if (!sv)
@@ -1680,6 +1695,11 @@ s++; n--; }
+if(gost){
+ sv->value = xtrymalloc (n * 2);
+}
+else
+ sv->value = xtrymalloc (n); if (!sv->value) {
@@ -1687,6 +1707,11 @@ xfree (sv); return gpg_error (GPG_ERR_ENOMEM); }
+/*r и s в подписи меняем местами - ТК-26*/
+if(gost == 1)
+ memcpy (sv->value + n, s, n);
+else
+ memcpy (sv->value, s, n); sv->valuelen = n; s += n;
@@ -1698,6 +1723,84 @@ return gpg_error (GPG_ERR_UNKNOWN_SEXP); /* but may also be an invalid one */ } s++;
+if(gost == 1){
+ unsigned char sh[30];
+
+ if (*s != '(')
+ {
+ xfree (sv->algo);
+ xfree (sv);
+ return gpg_error (digitp (s)? GPG_ERR_UNKNOWN_SEXP : GPG_ERR_INV_SEXP);
+ }
+ s++;
+ if (!(n = snext (&s)))
+ {
+ xfree (sv->algo);
+ xfree (sv);
+ return gpg_error (GPG_ERR_INV_SEXP);
+ }
+
+ s += n; /* ignore the name of the parameter */
+
+ if (!digitp(s))
+ {
+ xfree (sv->algo);
+ xfree (sv);
+ /* May also be an invalid S-EXP. */
+ return gpg_error (GPG_ERR_UNKNOWN_SEXP);
+ }
+ if (!(n = snext (&s)))
+ {
+ xfree (sv->algo);
+ xfree (sv);
+ return gpg_error (GPG_ERR_INV_SEXP);
+ }
+
+ if (n > 1 && !*s)
+ { /* We might have a leading zero due to the way we encode
+ MPIs - this zero should not go into the OCTECT STRING. */
+ s++;
+ n--;
+ }
+/*r и s в подписи меняем местами - ТК-26*/
+ memcpy (sv->value, s, n);
+ sv->valuelen += n;
+ s += n;
+
+ if ( *s != ')' && s[1] != ')' && s[2] != '(' )
+ {
+ xfree (sv->value);
+ xfree (sv->algo);
+ xfree (sv);
+ return gpg_error (GPG_ERR_UNKNOWN_SEXP); /* but may also be an invalid one */
+ }
+ s++;s++;s++;
+ if (!(n = snext (&s)))
+ {
+ xfree (sv->algo);
+ xfree (sv);
+ return gpg_error (GPG_ERR_INV_SEXP);
+ }
+ s += n;
+ if (!(n = snext (&s)))
+ {
+ xfree (sv->algo);
+ xfree (sv);
+ return gpg_error (GPG_ERR_INV_SEXP);
+ }
+ strncpy(sh, s, n);
+ if(!strcmp(sh, "1.2.643.7.1.1.2.2") || !strcasecmp(sh, "stribog256"))
+ sv->algo = xtrystrdup ("1.2.643.7.1.1.1.1");
+ else if(!strcmp(sh, "1.2.643.7.1.1.2.3") || !strcasecmp(sh, "stribog512"))
+ sv->algo = xtrystrdup ("1.2.643.7.1.1.1.2");
+ else if(!strcmp(sh, "1.2.643.2.2.9") || !strcasecmp(sh, "gostr3411_CP"))
+ sv->algo = xtrystrdup ("1.2.643.2.2.19");
+ else {
+ return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
+ }
+ s += n;
+
+} /* fixme: end loop over parameters */ /* we need 2 closing parenthesis */
diff -u KSBA_ORIG/dn.c KSBA/dn.c
--- KSBA_ORIG/dn.c 2016-08-22 11:40:58.000000000 +0300
+++ KSBA/dn.c 2018-06-26 19:24:32.000000000 +0300
@@ -48,6 +48,7 @@ 2 = David Chadwick, July 2003 <draft-ietf-pkix-dnstrings-02.txt> 3 = Peter Gutmann
+ 4 = tk26 */ const char *description; size_t oidlen;
@@ -74,12 +75,17 @@ "\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x19", "0.9.2342.19200300.100.1.25" }, ,
-{"EMAIL", 3, "emailAddress", 9,
+{"E", 1, "emailAddress", 9, "\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01", "1.2.840.113549.1.9.1" },
+/*oid-ы квалифицированного сертификата от TK-26*/
+{"OGRN", 4, "OGRN", 5, "\x2a\x85\x03\x64\x01", "1.2.643.100.1" },
+{"INN", 4, "INN", 8, "\x2a\x85\x03\x03\x81\x03\x01\x01", "1.2.643.3.131.1.1" },
+{"SNILS", 4, "SNILS", 5, "\x2a\x85\x03\x64\x03", "1.2.643.100.3" },
+{"OGRNIP", 4, "OGRNIP", 5, "\x2a\x85\x03\x64\x05", "1.2.643.100.5" },
+ { NULL } }; - #define N 0x00 #define P 0x01 static unsigned char charclasses[128] = {
@@ -555,8 +561,8 @@ name = NULL; for (i=0; oid_name_tbl[i].name; i++) {
- if (oid_name_tbl[i].source == 1
- && node->len == oid_name_tbl[i].oidlen
+/*Все oid-ы из DN переводим в текстовую форму*/
+ if (node->len == oid_name_tbl[i].oidlen && !memcmp (image+node->off+node->nhdr, oid_name_tbl[i].oid, node->len)) {
@@ -604,6 +610,9 @@ case TYPE_UTF8_STRING: append_utf8_value (image+node->off+node->nhdr, node->len, sb); break;
+/*Добавляем обработку NUMERIC_STRING*/
+ case TYPE_NUMERIC_STRING:
+ case TYPE_PRINTABLE_STRING: case TYPE_IA5_STRING: /* we assume that wrong encodings are latin-1 */
diff -u KSBA_ORIG/keyinfo.c KSBA/keyinfo.c
--- KSBA_ORIG/keyinfo.c 2015-10-28 13:41:48.000000000 +0300
+++ KSBA/keyinfo.c 2018-07-19 09:03:27.936234230 +0300
@@ -45,7 +45,6 @@ #include "convert.h" #include "ber-help.h" - /* Constants used for the public key algorithms. */ typedef enum {
@@ -98,6 +97,19 @@ "1.2.840.10045.2.1", /* ecPublicKey */ "\x2a\x86\x48\xce\x3d\x02\x01", 7, 1, PKALGO_ECC, "ecc", "q", "\x80" },
+/*oid-ы ГОСТ-овых ключей*/
+ { /* GOST3410-2001 */
+ "1.2.643.2.2.19", /* gostPublicKey-2001 */
+ "\x2a\x85\x03\x02\x02\x13", 6,
+ 1, PKALGO_ECC, "ecc", "q", "\x80" },
+ { /* GOST3410-2012-256 */
+ "1.2.643.7.1.1.1.1", /* gostPublicKey-2012-256 */
+ "\x2a\x85\x03\x07\x01\x01\x01\x01", 8,
+ 1, PKALGO_ECC, "ecc", "q", "\x80" },
+ { /* GOST3410-2012-512 */
+ "1.2.643.7.1.1.1.2", /* gostPublicKey-2012-512 */
+ "\x2a\x85\x03\x07\x01\x01\x01\x02", 8,
+ 1, PKALGO_ECC, "ecc", "q", "\x80" }, {NULL} };
@@ -209,6 +221,31 @@ "1.3.36.3.4.3.2.2", /* sigS_ISO9796-2rndWithrsa_ripemd160 */ "\x2B\x24\x03\x04\x03\x02\x02", 7, 0, PKALGO_RSA, "rsa", "s", "\x82", NULL, NULL, "rmd160" },
+ { /* GOST3410-2001 */
+ "1.2.643.2.2.19", /* gostPublicKey-2001 */
+ "\x2a\x85\x03\x02\x02\x13", 6,
+ 1, PKALGO_ECC, "gost", "s", "\x80", NULL, NULL, "gostr3411_CP" },
+ { /* GOST3410-2012-256 */
+ "1.2.643.7.1.1.1.1", /* gostPublicKey-2012-256 */
+ "\x2a\x85\x03\x07\x01\x01\x01\x01", 8,
+ 1, PKALGO_ECC, "gost", "s", "\x80", NULL, NULL, "stribog256"},
+ { /* GOST3410-2012-512 */
+ "1.2.643.7.1.1.1.2", /* gostPublicKey-2012-512 */
+ "\x2a\x85\x03\x07\x01\x01\x01\x02", 8,
+ 1, PKALGO_ECC, "gost", "s", "\x80", NULL, NULL, "stribog512"},
+
+ { /* GOST3411-2012-256 */
+ "1.2.643.7.1.1.3.2", /* STRIBOG256 */
+ "\x2a\x85\x03\x07\x01\x01\x03\x02", 8,
+ 1, PKALGO_ECC, "gost", "s", "\x80", NULL, NULL, "stribog256" },
+ { /* GOST3411-2012-512 */
+ "1.2.643.7.1.1.3.3", /* STRIBOG512 */
+ "\x2a\x85\x03\x07\x01\x01\x03\x03", 8,
+ 1, PKALGO_ECC, "gost", "s", "\x80", NULL, NULL, "stribog512" },
+ { /* GOST3410-2001-Signature */
+ "1.2.643.2.2.3", /* gosrPublicKey-2001 avec signature */
+ "\x2a\x85\x03\x02\x02\x03", 6,
+ 1, PKALGO_ECC, "gost", "s", "\x80", NULL, NULL, "gostr3411_CP" }, {NULL} };
@@ -218,6 +255,20 @@ "1.2.840.113549.1.1.1", /* rsaEncryption (RSAES-PKCA1-v1.5) */ "\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01", 9, 1, PKALGO_RSA, "rsa", "a", "\x82" },
+/*oid-ы ГОСТ-ых ключей для ассиметричного шифрования*/
+ {
+ "1.2.643.2.2.19", /*GOST R34.10-2001 */
+ "\x2A\x85\x03\x02\x02\x13", 6,
+ 1, PKALGO_ECC, "ecc", "a", "\x80" },
+ {
+ "1.2.643.7.1.1.1.1", /*GOST R34.10-2012-256 */
+ "\x2A\x85\x03\x07\x01\x01\x01\x01", 8,
+ 1, PKALGO_ECC, "ecc", "a", "\x80" },
+ {
+ "1.2.643.7.1.1.1.2", /*GOST R34.10-2012-512 */
+ "\x2A\x85\x03\x07\x01\x01\x01\x02", 8,
+ 1, PKALGO_ECC, "ecc", "a", "\x80" },
+ {NULL} }; @@ -267,6 +318,13 @@ { "1.2.643.2.2.35.1", "GOST2001-CryptoPro-A" }, { "1.2.643.2.2.35.2", "GOST2001-CryptoPro-B" }, { "1.2.643.2.2.35.3", "GOST2001-CryptoPro-C" },
+/*дополнительные oid-ы точек эллиптической кривой для ГОСТ Р 34.10-2001/2012*/
+// "GOST2001-CryptoPro-XchA" + { "1.2.643.2.2.36.0", "GOST2001-CryptoPro-A" }, +// "GOST2001-CryptoPro-XchB" + { "1.2.643.2.2.36.1", "GOST2001-CryptoPro-C" }, +
+ { "1.2.643.7.1.2.1.2.1", "GOST2012-tc26-A" }, { "1.2.643.7.1.2.1.2.2", "GOST2012-tc26-B" }, @@ -393,7 +451,8 @@ /* get the object identifier */ if (!derlen) return gpg_error (GPG_ERR_INV_KEYINFO);
- c = *der++; derlen--;
+ c = *der++;
+ derlen--; if ( c != 0x06 ) return gpg_error (GPG_ERR_UNEXPECTED_TAG); /* not an OBJECT IDENTIFIER */ TLV_LENGTH(der);
@@ -418,6 +477,7 @@ if (!derlen) return gpg_error (GPG_ERR_INV_KEYINFO); c = *der++; derlen--;
+ if ( c == 0x05 ) { /*printf ("parameter: NULL \n"); the usual case */
@@ -471,6 +531,7 @@ else { /* printf ("parameter: with tag %02x - ignored\n", c); */
+ TLV_LENGTH(der); seqlen -= der - startparm; /* skip the value */
@@ -692,6 +753,8 @@ const unsigned char *ctrl; const char *elem; struct stringbuf sb;
+ int gost_key;
+ char *parm_oid_hash = NULL; *r_string = NULL; @@ -701,6 +764,7 @@ c = *der++; derlen--; if ( c != 0x30 ) return gpg_error (GPG_ERR_UNEXPECTED_TAG); /* not a SEQUENCE */
+ TLV_LENGTH(der); /* and now the inner part */ err = get_algorithm (1, der, derlen, &nread, &off, &len, &is_bitstr,
@@ -715,13 +779,36 @@ && !memcmp (der+off, pk_algo_table[algoidx].oid, len)) break; }
+ if (!pk_algo_table[algoidx].oid) return gpg_error (GPG_ERR_UNKNOWN_ALGORITHM); if (!pk_algo_table[algoidx].supported) return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
+/*Определяем тип ключа 1 - ГОСТ-овый ключ*/
+ gost_key = !memcmp(pk_algo_table[algoidx].oidstring, "1.2.643", 7); if (parm_off && parm_len && parm_type == TYPE_OBJECT_ID) parm_oid = ksba_oid_to_str (der+parm_off, parm_len);
+ else +/*Извлекаем параметры ГОСТ-ового ключа*/
+ if (parm_off && parm_len && parm_type == TYPE_SEQUENCE && gost_key && (*(der+parm_off + off - 2) == TYPE_OBJECT_ID)){
+/*Вытаскиваем oid curve для ГОСТ-ключа*/
+ int len_hash;
+ int len_curve;
+ unsigned char* addr_hash;
+ unsigned char* addr_curve;
+ len_curve = (int) *(der+parm_off + off -1);
+ addr_curve = der+parm_off + off;
+ parm_oid = ksba_oid_to_str (addr_curve, len_curve);
+/*Вытаскиваем oid хэша для ГОСТ-ключа*/
+ if( *(addr_curve + len_curve)== TYPE_OBJECT_ID) {
+ len_hash = (unsigned int) *(der+parm_off + off + len_curve + 1);
+ addr_hash = addr_curve + len_curve + 2;
+ parm_oid_hash = ksba_oid_to_str (addr_hash, len_hash);
+ }
+/*Вытаскиваем oid алгоритма шифрования для ГОСТ-ключа*/
+ }
+ else if (parm_off && parm_len) { parmder = der + parm_off;
@@ -762,6 +849,13 @@ put_stringbuf_sexp (&sb, "curve"); put_stringbuf_sexp (&sb, parm_oid); put_stringbuf (&sb, ")");
+/*Устанавливаем oid-хэша для ГОСТ-ового ключа*/
+ if(gost_key && parm_oid_hash) {
+ put_stringbuf (&sb, "(");
+ put_stringbuf_sexp (&sb, "hash");
+ put_stringbuf_sexp (&sb, parm_oid_hash);
+ put_stringbuf (&sb, ")");
+ } } /* If parameters are given and we have a description for them, parse
@@ -851,6 +945,43 @@ put_stringbuf (&sb, "("); tmp[0] = *elem; tmp[1] = 0; put_stringbuf_sexp (&sb, tmp);
+/*Извлечение значения открытого ключа в соответствии с рекомендациями TK-26*/
+ if(gost_key){
+ unsigned char pk[129];
+ unsigned char *x;
+ unsigned char *y;
+ int len_pk;
+ int len_xy;
+ int i;
+ unsigned char c_inv;
+ int offset;
+ pk[0] = 0x04;
+ if(len == 131 || len == 66){
+ offset = 0;
+ if(der[0] == 0x04 && der[1] & 0x80)
+ offset = 3;
+ else if(der[0] == 0x04 && der[1] & 0x40)
+ offset = 2;
+ len_pk = len - offset;
+ memcpy(&pk[1], der + offset, len_pk);
+ x = &pk[1];
+ len_xy = len_pk / 2;
+ y = x + len_xy;
+/*REVERT-INVERTIROVANIE*/
+ for (i = 0; i < (len_xy/2); i++) {
+ c_inv = *(x + i);
+ *(x + i) = *(x + len_xy - i - 1);
+ *(x + len_xy - i - 1) = c_inv;
+ }
+ for (i = 0; i < (len_xy/2); i++) {
+ c_inv = y[i];
+ y[i] = y[len_xy - i -1];
+ y[len_xy - i - 1] = c_inv;
+ }
+ put_stringbuf_mem_sexp (&sb, pk , len_pk + 1);
+ }
+ } else
+ put_stringbuf_mem_sexp (&sb, der, len); der += len; derlen -= len;
@@ -1606,6 +1737,7 @@ const unsigned char *ctrl; const char *elem; struct stringbuf sb;
+ int gost_sign; /* FIXME: The entire function is very similar to keyinfo_to_sexp */ *r_string = NULL;
@@ -1615,7 +1747,6 @@ else algo_table = enc_algo_table; - err = get_algorithm (1, der, derlen, &nread, &off, &len, &is_bitstr, NULL, NULL, NULL); if (err)
@@ -1628,11 +1759,16 @@ && !memcmp (der+off, algo_table[algoidx].oid, len)) break; }
+ if (!algo_table[algoidx].oid) return gpg_error (GPG_ERR_UNKNOWN_ALGORITHM);
+ if (!algo_table[algoidx].supported) return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM); +/*Определяем тип подписи по oid-у*/
+ gost_sign = !memcmp(algo_table[algoidx].oidstring, "1.2.643", 7);
+ der += nread; derlen -= nread; @@ -1682,8 +1818,21 @@ put_stringbuf (&sb, "("); tmp[0] = *elem; tmp[1] = 0;
+/*Если ЭП по ГОСТ, то r находится справа, а s находится слева */
+ if(gost_sign == 1 && algo_table == sig_algo_table){
+ put_stringbuf_sexp (&sb, "r");
+ put_stringbuf_mem_sexp (&sb, der+(len/2), len/2);
+ put_stringbuf (&sb, ")");
+ put_stringbuf (&sb, "(");
+ put_stringbuf_sexp (&sb, "s");
+ put_stringbuf_mem_sexp (&sb, der, len/2);
+ }
+ else{
+ put_stringbuf_sexp (&sb, tmp); put_stringbuf_mem_sexp (&sb, der, len);
+ }
+ der += len; derlen -= len; put_stringbuf (&sb, ")");


Оставить комментарий

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

*

x

Ещё Hi-Tech Интересное!

[Перевод] Учёные вырастили универсальные стволовые клетки при помощи CRISPR инженерии

Клетки сердечной мышцы человека, полученные из новых универсальных стволовых клеток Учёные из University of California San Francisco впервые вырастили универсальные стволовые клетки, используя технологию редактирования генов CRISPR в целях получения плюрипотентных стволовых клеток, которые могут быть трансплантированы любому пациенту, не ...

[Перевод] Шесть историй, как код переписали с нуля

Новый взгляд на извечный вопрос: следует ли переписывать приложение с нуля или это «самая худшая стратегическая ошибка, которую может сделать разработчик программного обеспечения»? Оказывается, при работе со зрелой кодовой базой есть более двух вариантов ответа. «Исходный код словно заржавел!» — Джоэл ...