
हम
ओप्सनल के विकल्प के बारे में
बात करना जारी रखते
हैं और हम
लिबक्सबा लाइब्रेरी के बारे में बात करेंगे, जो कि GnuPG का हिस्सा है। लिबक्सबा लाइब्रेरी सार्वजनिक कुंजी अवसंरचना वस्तुओं जैसे प्रमाणपत्र, प्रमाणपत्र अनुरोध, इलेक्ट्रॉनिक हस्ताक्षर (CMS / PKCS # 7) के साथ काम करने के लिए एक उच्च-स्तरीय इंटरफ़ेस प्रदान करता है। हालाँकि, GCrypt पुस्तकालय के विपरीत, जो रूसी क्रिप्टोग्राफिक एल्गोरिदम का समर्थन करता है, libksba में GOST R 34.10-2001 / 2012, GOST R 34.11-94 / 2012 एल्गोरिदम के PKK ऑब्जेक्ट्स जैसे प्रमाणपत्रों के उपयोग पर
TK-26 सिफारिशों के कार्यान्वयन का अभाव है। प्रमाणपत्र, PKCS # 7 / CMS ऑब्जेक्ट (हस्ताक्षरित और / या एन्क्रिप्ट किए गए दस्तावेज़, आदि) के लिए अनुरोध।

आइए उन ओड्स से शुरू करें जो प्रमाणपत्र के जारीकर्ता (प्रकाशक) और विषय (स्वामी) के डीएन (विशिष्ट नाम) की विशिष्ट विशेषताओं का हिस्सा हो सकते हैं (या होना चाहिए)। Libksba लाइब्रेरी में, oid s को oid_name_tbl [] संरचना (dn.c फ़ाइल) में लिखा जाता है। Oid_name_tbl [] संरचना में TIN, BIN, OGRNIP और SNILS का कोई
oid s नहीं है, जो योग्य प्रमाणपत्र के लिए TK-26
द्वारा अनुशंसित है :
18. नाम की अतिरिक्त विशेषताएँ, जिनके उपयोग की आवश्यकता संघीय कानून के अनुसार स्थापित है, में शामिल हैं:
1) OGRN।
ओजीआरएन विशेषता का मूल्य एक योग्य प्रमाण पत्र के धारक के ओजीआरएन का प्रतिनिधित्व करने वाले 13 अंकों की एक स्ट्रिंग है - एक कानूनी इकाई। OGRN विशेषता प्रकार ऑब्जेक्ट पहचानकर्ता का फॉर्म 1.2.643.100.1 है, OGRN विशेषता प्रकार इस प्रकार वर्णित है: OGRN :: = NUMERIC STRING SIZE 13;
2) SNILS (SNILS)।
एसएनआईएलएस विशेषता का मूल्य एक योग्य प्रमाण पत्र के मालिक के एसएनआईएलएस का प्रतिनिधित्व करने वाले 11 अंकों की एक स्ट्रिंग है - एक व्यक्ति। SNILS विशेषता प्रकार का ऑब्जेक्ट पहचानकर्ता 1.2.643.100.3 है, SNILS विशेषता प्रकार इस प्रकार वर्णित है: SNILS :: = NUMERIC STRING SIZE 11;
3) आई.एन.एन.
INN विशेषता का मान एक 12-अंकीय स्ट्रिंग है जो योग्य प्रमाणपत्र धारक के TIN का प्रतिनिधित्व करता है। INN विशेषता प्रकार का ऑब्जेक्ट पहचानकर्ता 1.2.643.3.131.1.1 है, INN विशेषता प्रकार इस प्रकार वर्णित है: INN :: = NUMERIC STRING SIZE 12।
स्वाभाविक रूप से, आपको इन ओड-एस को जोड़ने की आवश्यकता है:
static const struct { const char *name; int source; const char *description; size_t oidlen; const unsigned char *oid; const char *oidstr; } oid_name_tbl[] = { {"CN", 1, "CommonName", 3, "\x55\x04\x03", "2.5.4.3" }, {"SN", 2, "Surname", 3, "\x55\x04\x04", "2.5.4.4" }, {"SERIALNUMBER", 2, "SerialNumber",3, "\x55\x04\x05", "2.5.4.5" }, {"C", 1, "CountryName", 3, "\x55\x04\x06", "2.5.4.6" }, {"L" , 1, "LocalityName", 3, "\x55\x04\x07", "2.5.4.7" }, {"ST", 1, "StateOrProvince", 3, "\x55\x04\x08", "2.5.4.8" }, {"STREET", 1, "StreetAddress", 3, "\x55\x04\x09", "2.5.4.9" }, {"O", 1, "OrganizationName", 3, "\x55\x04\x0a", "2.5.4.10" }, {"OU", 1, "OrganizationalUnit", 3, "\x55\x04\x0b", "2.5.4.11" }, {"T", 2, "Title", 3, "\x55\x04\x0c", "2.5.4.12" }, {"D", 3, "Description", 3, "\x55\x04\x0d", "2.5.4.13" }, {"BC", 3, "BusinessCategory", 3, "\x55\x04\x0f", "2.5.4.15" }, {"ADDR", 2, "PostalAddress", 3, "\x55\x04\x11", "2.5.4.16" }, {"POSTALCODE" , 0, "PostalCode", 3, "\x55\x04\x11", "2.5.4.17" }, {"GN", 2, "GivenName", 3, "\x55\x04\x2a", "2.5.4.42" }, {"PSEUDO", 2, "Pseudonym", 3, "\x55\x04\x41", "2.5.4.65" }, {"DC", 1, "domainComponent", 10, "\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x19", "0.9.2342.19200300.100.1.25" }, {"UID", 1, "userid", 10, "\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x01", "0.9.2342.19200300.100.1.1 " }, {"E", 1, "emailAddress", 9, "\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01", "1.2.840.113549.1.9.1" }, {"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 } };
इस संरचना में जो उल्लेखनीय है वह स्रोत फ़ील्ड की उपस्थिति है, जो इंगित करता है कि किसी विशेष फ़ील्ड में कौन प्रवेश करता है, उदाहरण के लिए, 1 (यूनिट) इंगित करता है कि फ़ील्ड rfc2253 में परिभाषित है, और 4 (चार) यहां जोड़े जाएंगे इंगित करें कि फ़ील्ड TK-26 की तकनीकी समिति द्वारा अनुशंसित है। TK-26 की सिफारिशों के अनुसार, TIN, OGRN, OGRNIP और SNILS विशेषताएँ NUMERIC STRING प्रकार (ऊपर देखें) के हैं। Libksba में DN में शामिल oids का प्रसंस्करण परिशिष्ट_ फ़ंक्शन (dn.c फ़ाइल) में प्रदान किया गया है, हालाँकि, इसमें TYPE_NUMERIC_STRING प्रकार के प्रसंस्करण का अभाव है, और आपको इसे जोड़ना चाहिए:
. . . switch (use_hex? 0 : node->type) { case TYPE_UTF8_STRING: append_utf8_value (image+node->off+node->nhdr, node->len, sb); break; case TYPE_NUMERIC_STRING: case TYPE_PRINTABLE_STRING: ….
Dn.c फ़ाइल के लिए पैच यहाँ है: इसे diff_dn.patch फ़ाइल में सहेजें।
लिबेक्सा लाइब्रेरी को
यहां डाउनलोड किया जा सकता
है । संग्रह को अनज़िप करें, src निर्देशिका दर्ज करें और dn.c फ़ाइल में पैच diff_dn.patch लागू करें:
$patch dn.c < diff_dn.patch $
DN विशेषताओं के oid s के अलावा, संरचना pk_algo_table [] संरचना (keyihfo.c फ़ाइल) में GOST कीज़ के लिए oid s जोड़ना भी आवश्यक है:
static const struct algo_table_s pk_algo_table[] = { { "1.2.840.113549.1.1.1", "\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01", 9, 1, PKALGO_RSA, "rsa", "-ne", "\x30\x02\x02" }, . . . { "1.2.643.2.2.19", "\x2a\x85\x03\x02\x02\x13", 6, 1, PKALGO_ECC, "ecc", "q", "\x80" }, { "1.2.643.7.1.1.1.1", "\x2a\x85\x03\x07\x01\x01\x01\x01", 8, 1, PKALGO_ECC, "ecc", "q", "\x80" }, { "1.2.643.7.1.1.1.2", "\x2a\x85\x03\x07\x01\x01\x01\x02", 8, 1, PKALGO_ECC, "ecc", "q", "\x80" }, {NULL} };
इसी तरह, sig_algo_table [] संरचना (keyihfo.c फ़ाइल) में हम GOST के अनुसार इलेक्ट्रॉनिक हस्ताक्षर से जुड़े ओड-एस जोड़ते हैं:
static const struct algo_table_s sig_algo_table[] = { { "1.2.840.113549.1.1.5", "\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05", 9, 1, PKALGO_RSA, "rsa", "s", "\x82", NULL, NULL, "sha1" }, . . . { "1.2.643.2.2.19", "\x2a\x85\x03\x02\x02\x13", 6, 1, PKALGO_ECC, "gost", "s", "\x80", NULL, NULL, "gostr3411_CP" }, { "1.2.643.7.1.1.1.1", "\x2a\x85\x03\x07\x01\x01\x01\x01", 8, 1, PKALGO_ECC, "gost", "s", "\x80", NULL, NULL, "stribog256"}, { "1.2.643.7.1.1.1.2", "\x2a\x85\x03\x07\x01\x01\x01\x02", 8, 1, PKALGO_ECC, "gost", "s", "\x80", NULL, NULL, "stribog512"}, { "1.2.643.7.1.1.3.2", "\x2a\x85\x03\x07\x01\x01\x03\x02", 8, 1, PKALGO_ECC, "gost", "s", "\x80", NULL, NULL, "stribog256" }, { "1.2.643.7.1.1.3.3", "\x2a\x85\x03\x07\x01\x01\x03\x03", 8, 1, PKALGO_ECC, "gost", "s", "\x80", NULL, NULL, "stribog512" }, { "1.2.643.2.2.3", "\x2a\x85\x03\x02\x02\x03", 6, 1, PKALGO_ECC, "gost", "s", "\x80", NULL, NULL, "gostr3411_CP" }, {NULL} };
और, अंत में, हम GOST कुंजियों की शपथ के साथ enc_algo_table [] की संरचना को पूरक करते हैं जो असममित एन्क्रिप्शन (PKCS # 7) में भाग ले सकते हैं:
static const struct algo_table_s enc_algo_table[] = { { "1.2.840.113549.1.1.1", "\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01", 9, 1, PKALGO_RSA, "rsa", "a", "\x82" }, { "1.2.643.2.2.19", "\x2A\x85\x03\x02\x02\x13", 6, 1, PKALGO_ECC, "ecc", "a", "\x80" }, { "1.2.643.7.1.1.1.1", "\x2A\x85\x03\x07\x01\x01\x01\x01", 8, 1, PKALGO_ECC, "ecc", "a", "\x80" }, { "1.2.643.7.1.1.1.2", "\x2A\x85\x03\x07\x01\x01\x01\x02", 8, 1, PKALGO_ECC, "ecc", "a", "\x80" }, {NULL} };
अब जब हमने oid पर फैसला कर लिया है, तो आइए प्रमाणपत्र में सार्वजनिक कुंजी को संग्रहीत करने की संरचना पर चलते हैं। सामान्य तौर पर, किसी प्रमाण पत्र में SubjectPublicKeyInfo संरचना का निम्न रूप होता है:
SubjectPublicKeyInfo ::= SEQUENCE { algorithm OBJECT IDENTIFIER GostR3410-2001/2012-PublicKeyParameters ::= SEQUENCE { publicKeyParamSet OBJECT IDENTIFIER, digestParamSet OBJECT IDENTIFIER, encryptionParamSet OBJECT IDENTIFIER } subjectKey BIT STRING }
PublicKeyParamSet पैरामीटर अण्डाकार वक्र के बिंदु की ओड निर्दिष्ट करता है। अनुमत बिंदुओं के ओड-पॉइंट libgcrypt लाइब्रेरी की ecc_curves.c फ़ाइल में स्ट्रक्चर कर्व_लीस [] संरचना में पंजीकृत हैं। Libksba लाइब्रेरी में, ये oid-s keyinfo.c फाइल में स्ट्रक्चर कर्व_नाम [] संरचना में पंजीकृत हैं। इस संरचना में, "1.2.643.2.2.36.0" (GOST2001-CryptoPro-XchA) और "1.2.643.2.2.36.1" (GOST2001-CryptoPro-XchB) को छोड़ दिया जाता है। हम इन ओड्स को जोड़ते हैं, लेकिन इस तथ्य को ध्यान में रखते हुए कि ओड "1.2.643.2.2.36.0" वास्तव में ओड के साथ एक बिंदु है "1.2.643.2.2.35.1", और "1.2.643.2.2.36.1" से मेल खाती है ओड "1.2.643.2.2.35.3":
static const struct { const char *oid; const char *name; } curve_names[] = { { "1.3.6.1.4.1.3029.1.5.1", "Curve25519" }, . . . { "1.2.643.2.2.35.3", "GOST2001-CryptoPro-C" },
एन्क्रिप्शनप्रेमसेट पैरामीटर आम तौर पर छोड़ा जाता है। डाइजेस्टपरामसेट पैरामीटर भी छोड़ा जा सकता है: GOST कुंजी प्रकार विशिष्ट रूप से ओड डाइजेस्टरमसेट निर्धारित करता है।
प्रमाणपत्र से GOST सार्वजनिक कुंजी निकालने वाला कोड, इसे पार्स करता है, और इसे S चर में पैक करता है _ksba_keyinfo_to_sexp फ़ंक्शन (keyinfo.c फ़ाइल) में जोड़ा जाता है, और GOST हस्ताक्षर को S चर में पैक करने के लिए जिम्मेदार कोड फ़ंक्शन में जोड़ा जाता है। crypt_val_to_sexp। कोड टिप्पणियों के साथ प्रदान किया गया है और अतिरिक्त स्पष्टीकरण की आवश्यकता नहीं है। हमने
पिछले लेख में प्रमाणपत्र में सार्वजनिक कुंजी और हस्ताक्षर संग्रहीत करने की सुविधाओं के बारे में बात की थी।
Keyinfo.c फ़ाइल के लिए पैच यहाँ है: इसे diff_keyinfo.patch फ़ाइल में सहेजें और keyinfo.c फ़ाइल पर लागू करें:
$patch keyinfo.c < diff_keyinfo.patch $
इन पैच को जोड़ने के बाद, आप लाइब्रेरी का निर्माण कर सकते हैं। यदि आप सिस्टम में असेंबली libksba.so.8.11.6 लाइब्रेरी स्थापित करने नहीं जा रहे हैं, लेकिन इसका उपयोग केवल परीक्षण के लिए करेंगे, तो इसे उस निर्देशिका में कॉपी करना सुविधाजनक है जिसमें परीक्षण के मामले एकत्र किए जाएंगे। ये पैच GOST कुंजी के साथ प्रमाणपत्रों को पार्स करने के लिए पर्याप्त हैं, साथ ही PKCS # 7 प्रारूप में GOST कुंजी के साथ हस्ताक्षरित दस्तावेज, और X509 प्रमाणपत्र या PKCS / 7 / CMS दस्तावेज़ के इलेक्ट्रॉनिक हस्ताक्षर के गणितीय हस्ताक्षर को निकालने और सत्यापित करने के लिए पर्याप्त हैं।
इसका परीक्षण करने के लिए, दो सॉफ्टवेयर मॉड्यूल पर विचार करें। पहला check_cert मॉड्यूल सत्यापित करता है कि प्रमाणपत्र सही तरीके से हस्ताक्षरित है, और दूसरा check_cms_signed मॉड्यूल हस्ताक्षरित दस्तावेज़ (CMS / PKCS # 7) की अखंडता और दस्तावेज़ हस्ताक्षर की शुद्धता की जांच करता है। याद रखें कि प्रमाणपत्र की वैधता न केवल उसके हस्ताक्षर की शुद्धता से निर्धारित होती है, बल्कि जाँच के समय उसकी वैधता (गैर-वापसी) द्वारा भी निर्धारित की जाती है। उसी तरह, किसी दस्तावेज़ के तहत हस्ताक्षर की वैधता न केवल हस्ताक्षर की गणितीय विश्वसनीयता से निर्धारित होती है, बल्कि हस्ताक्षरकर्ता प्रमाण पत्र की वैधता से भी निर्धारित होती है।

PKCS # 7 प्रारूप में एक हस्ताक्षरित दस्तावेज़ बनाने के लिए, आप
टिंकेटर के साथ पायथन में लिखी
गाइनेस ।
Exi उपयोगिता का उपयोग कर सकते हैं, और क्रिप्टोग्राफिक सूचना सुरक्षा उपकरण (CISI) के रूप में रूसी क्रिप्टोग्राफी के लिए समर्थन के साथ PKCS # 11 टोकन का उपयोग कर सकते हैं:

हम यह भी ध्यान देते हैं कि दस्तावेज़ के इलेक्ट्रॉनिक हस्ताक्षर के विचाराधीन PKCS # 7 प्रारूप का तात्पर्य हस्ताक्षर में एक हस्ताक्षरकर्ता प्रमाण पत्र को शामिल करने से है। ऐसा इसलिए किया जाता है ताकि उदाहरण अपार न हो।
सत्यापन उपयोगिता पर हस्ताक्षर करने वाले check_cert.c प्रमाणपत्र का स्रोत कोड यहां दिया गया है: #include <stdio.h> #include <stdlib.h> #include <string.h> #include <assert.h> #include <errno.h> #include <ctype.h> #include <gcrypt.h> #include <ksba.h> /* Hash function used with libksba. */ #define HASH_FNC ((void (*)(void *, const void*,size_t))gcry_md_write) /* S-*/ static void show_sexp (const char *prefix, gcry_sexp_t a) { char *buf; size_t size; if (prefix) fputs (prefix, stderr); size = gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, NULL, 0); buf = gcry_xmalloc (size); gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, buf, size); fprintf (stderr, "%.*s", (int)size, buf); gcry_free (buf); } /* */ static gpg_error_t check_cert_sig (ksba_cert_t issuer_cert, ksba_cert_t cert) { gpg_error_t err; const char *algoid; gcry_md_hd_t md; int i, algo; ksba_sexp_t p; size_t n; /* : S_PKEY - S- . S_SIG - S- S_HASH - S- tbs- */ gcry_sexp_t s_sig, s_hash, s_pkey; const char *s; char algo_name[16+1]; /* hash algorithm name converted to lower case. */ int digestlen; unsigned char *digest; int gost_key; /* Hash the target certificate using the algorithm from that certificate. */ algoid = ksba_cert_get_digest_algo (cert); algo = gcry_md_map_name (algoid); if (!algo) { fprintf(stderr, "unknown hash algorithm `%s'\n", algoid? algoid:"?"); return (-1); } /* */ gost_key = !memcmp(algoid, "1.2.643", 7); s = gcry_md_algo_name (algo); for (i=0; *s && i < sizeof algo_name - 1; s++, i++) algo_name[i] = tolower (*s); algo_name[i] = 0; err = gcry_md_open (&md, algo, 0); if (err) { fprintf(stderr, "md_open failed: %s\n", algoid); return err; } err = ksba_cert_hash (cert, 1, HASH_FNC, md); if (err) { fprintf(stderr, "ksba_cert_hash failed: %s\n", algoid); gcry_md_close (md); return err; } gcry_md_final (md); /* */ p = ksba_cert_get_sig_val (cert); /* */ n = gcry_sexp_canon_len (p, 0, NULL, NULL); if (!n) { gcry_md_close (md); ksba_free (p); return (-1); } /* S- libgcrypt*/ err = gcry_sexp_sscan ( &s_sig, NULL, p, n); ksba_free (p); if (err) { fprintf(stderr, "gcry_sexp_scan failed: %s\n", "Beda"); gcry_md_close (md); return err; } /* S- */ show_sexp ("Sig value:\n", s_sig); /* */ p = ksba_cert_get_public_key (issuer_cert); n = gcry_sexp_canon_len (p, 0, NULL, NULL); if (!n) { fprintf(stderr, "libksba did not return a proper S-Exp\n"); gcry_md_close (md); ksba_free (p); gcry_sexp_release (s_sig); return (-1); } err = gcry_sexp_sscan ( &s_pkey, NULL, p, n); ksba_free (p); if (err) { fprintf(stderr, "gcry_sexp_scan failed: %s\n", "pubkey"); gcry_md_close (md); gcry_sexp_release (s_sig); return err; } /* S- */ show_sexp ("s_pkey:\n", s_pkey); digestlen = gcry_md_get_algo_dlen (algo); digest = gcry_md_read (md, algo); if (gost_key){ unsigned char *h; unsigned char c; int len_xy; /* littlt-endian big-endian*/ unsigned short arch = 1; /* 0x0001 */ h = digest; len_xy = *((unsigned char *) &arch) == 0 ? 0:gcry_md_get_algo_dlen (algo); /* */ for (i = 0; i < (len_xy/2); i++) { c = *(h + i); *(h + i) = *(h + len_xy - i - 1); *(h + len_xy - i - 1) = c; } } switch (gost_key) { case 0: if ( gcry_sexp_build (&s_hash, NULL, "(data(flags pkcs1)(hash %s %b))", algo_name, (int)digestlen, digest) ) { exit (1); } break; case 1: if ( gcry_sexp_build (&s_hash, NULL, "(data(flags gost)(value %b))", (int)digestlen, digest) ) { exit (1); } break; default: exit (1); } /* S- tbs-*/ show_sexp ("s_hash:\n", s_hash); /* */ err = gcry_pk_verify (s_sig, s_hash, s_pkey); /* */ gcry_md_close (md); gcry_sexp_release (s_sig); gcry_sexp_release (s_hash); gcry_sexp_release (s_pkey); return err; } int main (int argc, unsigned char *argv[]) { FILE *fp; ksba_reader_t r; ksba_cert_t cert; FILE *fp_ca; ksba_reader_t r_ca; ksba_cert_t cert_ca; gpg_error_t err; unsigned char *sub_dn; if(argc != 3) { fprintf(stderr, "Usage: check_cert < > < >\n"); exit(1); } fp = fopen (argv[1], "rb"); if (!fp) { fprintf (stderr, "check_cert: can't open `%s'\n", argv[1]); exit (1); } err = ksba_reader_new (&r); if (err) { fprintf(stderr, "ksba_reader_new error\n"); exit(1); } err = ksba_reader_set_file (r, fp); if (err) { fprintf(stderr, "ksba_reader_set error\n"); exit(1); } err = ksba_cert_new (&cert); if (err){ fprintf(stderr, "ksba_cert_new error\n"); exit(1); } err = ksba_cert_read_der (cert, r); if (err){ fprintf(stderr, "ksba_cert_read_der error\n"); exit(1); } fp_ca = fopen (argv[2], "rb"); if (!fp_ca) { fprintf (stderr, "check_cert: can't open `%s'\n", argv[2]); exit (1); } err = ksba_reader_new (&r_ca); if (err) { fprintf(stderr, "ksba_reader_new error\n"); exit(1); } err = ksba_reader_set_file (r_ca, fp_ca); if (err) { fprintf(stderr, "ksba_reader_set error\n"); exit(1); } err = ksba_cert_new (&cert_ca); if (err){ fprintf(stderr, "ksba_cert_new error\n"); exit(1); } err = ksba_cert_read_der (cert_ca, r_ca); if (err){ fprintf(stderr, "ksba_cert_read_der error\n"); exit(1); } sub_dn = ksba_cert_get_subject (cert, 0); fprintf(stderr, "check_cert: Verify %s\n", sub_dn); err = check_cert_sig (cert_ca, cert); if (err) { fprintf(stderr, "check_cert: verify %s error\n", argv[1]); } else { fprintf(stderr, "check_cert: verify %s Ok\n", argv[1]); } }
हम कोड को फ़ाइल check_cert.c में सहेजते हैं, उसका अनुवाद करते हैं और उसे चलाते हैं:
bash-4.3$ln –s libksba.so.8 lgcrypt libksba.so.8.11.6 bash-4.3$ cc -o check_cert check_cert.c -lgcrypt libksba.so.8.11.6 bash-4.3$ ./check_cert Usage: check_cert < > < > bash-4.3$
इसलिए, प्रमाण पत्र को सत्यापित करने के लिए, आपके पास स्वयं प्रमाण पत्र और सीए प्रमाणपत्र होना चाहिए (उदाहरण के लिए, आप इसे पिछले लेख से ले सकते हैं) जिस पर यह जारी किया गया था। प्रमाण पत्र (अभी के लिए) डीईआर-एन्कोडेड होना चाहिए:
bash-4.3$ ./check_cert CERT_CMS_KSBA.der CAcert_NEWCA.der check_cert: Verify SNILS=22222222222,INN=123456789012,O=CMS,STREET=PKCS7,L= ,ST=50 ,C=RU,GN=KSBA,SN=GCrypt,CN= GCrypt and KSBA,E=test@test.ru Sig value: (sig-val (gost (r
स्व-हस्ताक्षरित प्रमाण पत्र को सत्यापित करने के लिए, उत्तरार्द्ध को सत्यापित और मूल प्रमाण पत्र के रूप में दर्शाया गया है:
bash-4.3$ ./check_cert CAcert_NEWCA.der CAcert_NEWCA.der check_cert: Verify E=info@ooo.ru,CN= ,OU= 2,O= ,C=RU,ST= ,L=. . . . check_cert: verify CAcert_NEWCA.der Ok bash-4.3$
इसलिए हमारे पास प्रमाणपत्रों के हस्ताक्षर की पुष्टि के लिए एक सरल उपयोगिता है।
PKCS प्रारूप # 7 में विकसित दस्तावेजों के इलेक्ट्रॉनिक हस्ताक्षर को सत्यापित करने के लिए
परीक्षण उपयोगिता check_cms_signed.c: #include <stdio.h> #include <stdlib.h> #include <string.h> #include <assert.h> #include <time.h> #include <errno.h> #include <ksba.h> //#include "t-common.h" #include <gcrypt.h> #include <sys/stat.h> #include <sys/types.h> #include <fcntl.h> #include <unistd.h> /* Hash function used with libksba. */ #define HASH_FNC ((void (*)(void *, const void*,size_t))gcry_md_write) void dump_isotime (const ksba_isotime_t t) { if (!t || !*t) fprintf (stderr, "[none]"); else fprintf (stderr,"%.4s-%.2s-%.2s %.2s:%.2s:%s", t, t+4, t+6, t+9, t+11, t+13); } static void show_sexp (const char *prefix, gcry_sexp_t a) { char *buf; size_t size; if (prefix) fputs (prefix, stderr); size = gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, NULL, 0); buf = gcry_xmalloc (size); gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, buf, size); fprintf (stderr, "%.*s", (int)size, buf); gcry_free (buf); } void dummy_hash_fnc (void *arg, const void *buffer, size_t length) { (void)arg; (void)buffer; (void)length; } static int dummy_writer_cb (void *cb_value, const void *buffer, size_t count) { (void)cb_value; (void)buffer; (void)count; return 0; } /* */ unsigned char *dgst_file (char *oid, char* fcont, int *len_h) { gcry_md_hd_t hd; gcry_error_t err; int algo; FILE *fp; unsigned char buf[1024]; size_t size; int i; unsigned char *h; unsigned char *ret_h; algo = gcry_md_map_name (oid); if (algo == GCRY_MD_NONE) return NULL; err = gcry_md_open(&hd, algo, 0); if (err) return NULL; fp = fopen (fcont, "r"); if (fp == NULL) return NULL; while (!feof (fp)) { size = fread (buf, 1, sizeof(buf), fp); gcry_md_write (hd, buf, size); } h = gcry_md_read(hd, 0); *len_h = gcry_md_get_algo_dlen (algo); ret_h = malloc(*len_h); memcpy(ret_h, h, *len_h); gcry_md_reset(hd); gcry_md_close(hd); return ret_h; } gcry_error_t one_file (const char *fname, char *fcontent, char *fcert) { gcry_error_t err; FILE *fp; ksba_reader_t r; ksba_writer_t w; ksba_cms_t cms; int i; const char *algoid; ksba_stop_reason_t stopreason; const char *s = NULL; size_t n; ksba_sexp_t p; char *dn; int idx; ksba_cert_t cert; int ii; unsigned char *cert_der; int cert_der_len; int f_der; int rez; ksba_sexp_t p1; size_t n1; gcry_sexp_t s_sig, s_hash, s_pkey, s_num; int gost_key; gcry_md_hd_t md; int rc; int digestlen; unsigned char *digest; gcry_md_hd_t data_md = NULL; ksba_isotime_t sigtime; unsigned char *sub_dn; //dn - char *is_dn; //dn - ksba_sexp_t sub_p; // fprintf (stderr, "\n*** checking `%s' ***\n", fname); fp = fopen (fname, "r"); if (!fp) { fprintf (stderr, "can't open `%s'\n", fname); exit (1); } err = ksba_reader_new (&r); if (err) { fprintf (stderr, "can't reader `%s'\n", fname); exit (1); } err = ksba_reader_set_file (r, fp); if (err) { fprintf (stderr, "can't reader set `%s'\n", fname); exit (1); } /* Also create a writer so that cms.c won't return an error when writing processed content. */ err = ksba_writer_new (&w); if (err) { exit (1); } err = ksba_writer_set_cb (w, dummy_writer_cb, NULL); if (err) { exit (1); } switch (ksba_cms_identify (r)) { case KSBA_CT_SIGNED_DATA: s = "signed data"; break; case KSBA_CT_DATA: s = "data"; case KSBA_CT_ENVELOPED_DATA: if (s == NULL) s = "enveloped data"; case KSBA_CT_DIGESTED_DATA: if (s == NULL) s = "digested data"; case KSBA_CT_ENCRYPTED_DATA: if (s == NULL) s = "encrypted data"; case KSBA_CT_AUTH_DATA: if (s == NULL) s = "auth data"; default: if (s == NULL) s = "unknown"; printf ("identified as: %s\n", s); exit(1); } err = ksba_cms_new (&cms); if (err) { exit(1); } err = ksba_cms_set_reader_writer (cms, r, w); if (err) { exit(1); } rc = gcry_md_open (&data_md, 0, 0); if (rc) { fprintf (stderr, "md_open failed: \n"); exit(1);; } err = ksba_cms_parse (cms, &stopreason); if (err) { fprintf (stderr, "ksba_cms_parse: cannot parse %s\n", fname); exit(1); } ksba_cms_set_hash_function (cms, dummy_hash_fnc, NULL); do { err = ksba_cms_parse (cms, &stopreason); if (err) { fprintf (stderr, "ksba_cms_parse: cannot parse %s\n", fname); exit(1); } } while (stopreason != KSBA_SR_READY); /* PKCS7 */ cert_der_len = 0; for (ii=0; (cert=ksba_cms_get_cert (cms, ii)); ii++) { cert_der = (unsigned char*)ksba_cert_get_image(cert, (size_t *)&cert_der_len); f_der = open(fcert, O_RDWR|O_TRUNC|O_CREAT, 0666); if (f_der == -1) { fprintf(stderr, "Bad open file=%s for cert\n", cert_der_len, fcert); exit(1); } /* */ rez = write(f_der, cert_der, cert_der_len); close(f_der); /* */ p1 = ksba_cert_get_public_key (cert); n1 = gcry_sexp_canon_len (p1, 0, NULL, NULL); if (!n1) { fprintf(stderr, "libksba did not return a proper S-Exp\n"); exit(1); } err = gcry_sexp_sscan ( &s_pkey, NULL, p1, n1); ksba_free (p1); if (err) { fprintf(stderr, "gcry_sexp_scan failed: %s\n", "pubkey"); exit(1); } /* DN */ sub_dn = ksba_cert_get_subject (cert, 0); ksba_cert_release (cert); } for (idx=0; idx < 1; idx++) { int algo; int info_pkalgo; unsigned char *s; int s_len; int len_h; unsigned char *dgst_h; /* /PKCS#7 DN is_dn sub_p*/ /* */ /* , PKCS#7*/ err = ksba_cms_get_issuer_serial (cms, idx, &is_dn, &sub_p); if (err) { fprintf (stderr, "ksba_cms_get_issuer_serial cannot %s\n", fname); exit(1); } /* */ algoid = ksba_cms_get_digest_algo (cms, idx); err = ksba_cms_get_sigattr_oids (cms, 0, "1.2.840.113549.1.7.1",&dn); if (err && err != -1) { fprintf (stderr, "ksba_cms_get_sigattr_oids cannot %s err=%d\n", fname, err); exit(1); } algo = gcry_md_map_name (algoid); /* - (1) */ gost_key = !memcmp(algoid, "1.2.643", 7); gcry_md_enable (data_md, algo); rc = gcry_md_open (&md, algo, 0); if (rc) { fprintf(stderr, "md_open failed:\n"); exit(1); } /* -*/ ksba_cms_set_hash_function (cms, HASH_FNC, data_md); /* */ rc = ksba_cms_hash_signed_attrs (cms, idx); if (rc) { fprintf(stderr, "hashing signed attrs failed: \n"); gcry_md_close (md); continue; } gcry_md_final (md); digestlen = gcry_md_get_algo_dlen (algo); /* */ digest = gcry_md_read (data_md, algo); gcry_md_close (md); if (gost_key){ /* */ unsigned char *h; unsigned char c; int len_xy; /* littlt-endian big-endian*/ unsigned short arch = 1; /* 0x0001 */ h = digest; len_xy = *((unsigned char *) &arch) == 0 ? 0:gcry_md_get_algo_dlen (algo); /* */ for (i = 0; i < (len_xy/2); i++) { c = *(h + i); *(h + i) = *(h + len_xy - i - 1); *(h + len_xy - i - 1) = c; } } switch (gost_key) { case 0: if ( gcry_sexp_build (&s_hash, NULL, "(data(flags pkcs1)(hash %s %b))", algoid, (int)digestlen, digest) ) { fprintf(stderr, "BUG\n"); exit (1); } break; case 1: /* , S- */ if ( gcry_sexp_build (&s_hash, NULL, "(data(flags gost)(value %b))", (int)digestlen, digest) ) { exit (1); } break; default: exit (1); } /* */ rc = ksba_cms_get_signing_time (cms, idx, sigtime); if (rc) { fprintf(stderr, "error getting signing time\n"); // *sigtime = 0; /* (we can't encode an error in the time string.) */ exit(1); } /* PKCS#7 */ err = ksba_cms_get_message_digest (cms, idx, &dn, &n); if (err) { fprintf (stderr, "ksba_cms_get_message_digest cannot %s\n", fname); exit(1); } /* */ dgst_h = dgst_file ((char *)algoid, (char *)fcontent, &len_h); if (dgst_h == NULL) { fprintf(stderr, "\nBad digest %s\n", fcontent); exit (1); } if (memcmp(dgst_h, dn, n)) { /* : , , ..*/ fprintf(stderr, "\nBad content %s\n", fcontent); exit (1); } ksba_free (dn); putchar ('\n'); dn = ksba_cms_get_sig_val (cms, idx); if (!dn) { printf ("signer %d - signature not found\n", idx); exit(1); } n = gcry_sexp_canon_len ((ksba_sexp_t)dn, 0, NULL, NULL); if (!n){ fprintf(stderr, "libksba did not return a proper S-Exp\n"); exit(1); } err = gcry_sexp_sscan ( &s_sig, NULL, dn, n); if (err){ fprintf(stderr, "gcry_sexp_scan failed: %s\n", "Beda"); exit(1); } ksba_free (dn); } fprintf(stderr, "\n===========================================================\n"); if (*sigtime){ fprintf (stderr, " :\n"); dump_isotime (sigtime); fprintf (stderr, "\n"); } else fprintf (stderr, "[date not given]\n"); fprintf(stderr, "\n : %s\n", sub_dn); fprintf(stderr, "\n : %s\n", is_dn); n = gcry_sexp_canon_len ((ksba_sexp_t)sub_p, 0, NULL, NULL); if (!n){ fprintf(stderr, "libksba did not return a proper S-Exp NUM\n"); exit(1); } err = gcry_sexp_sscan ( &s_num, NULL, sub_p, n); show_sexp ("\n :\n", s_num); fprintf(stderr, "\n===========================================================\n"); /* */ err = gcry_pk_verify (s_sig, s_hash, s_pkey); // if(err) { show_sexp ("s_pkey:\n", s_pkey); show_sexp ("s_sig:\n", s_sig); show_sexp ("s_hash:\n", s_hash); // } ksba_cms_release (cms); ksba_reader_release (r); fclose (fp); return (err); } int main (int argc, char **argv) { gcry_error_t err; unsigned char *h; int *len_h; if(argc != 4) { fprintf(stderr, "Usage: check_cms < > < > < >\n"); exit(1); } err = one_file (argv[1], argv[2], argv[3]); if (err) { fprintf(stderr, "check_cms: verify %s error\n", argv[1]); } else { fprintf(stderr, "check_cms: verify %s Ok\n", argv[1]); fprintf(stderr, "check_cms: %s\n", argv[3]); } exit (0); }
, ( ) . check_cms_signed.c, :
bash-4.3$ cc -o check_cms_signed check_cms_signed.c -lgcrypt libksba.so.8.11.6 bash-4.3$ ./check_cms_signed Usage: check_cms < > < > < > bash-4.3$
:
bash-4.3$ ./check_cms_signed test_cms_ksba.txt.p7s test_cms_ksba.txt save_cert.der *** checking `test_cms_ksba.txt.p7s' *** =========================================================== : 2018-06-25 15:57:12 : SNILS=22222222222,INN=123456789012,O=CMS,STREET=PKCS7,L= ,ST=50 ,C=RU,GN=KSBA,SN=GCrypt,CN= GCrypt and KSBA,E=test@test.ru : E=info@lissi.ru,CN= ,OU= 2,O= ,C=RU,ST= ,L=. ,STREET=. .4 .7,OGRN=1234567890123,INN=123456789012 : (#73102E931BF9EA1369BA#) =========================================================== s_pkey: (public-key (ecc (curve "1.2.643.7.1.2.1.2.2") (hash "1.2.643.7.1.1.2.3") (q #044840A283684ECB537989536B9F080F7B914F3E6C153BC23F8A9212E303BF5B13905D29D0689CA5F2D0715D13FDC0FD387650193A7B46BE20C266776FAE36483750FE52A4C4E35EFB37EA64B48CB50ED5151289F59793574BD5FA59A2048A97FD94A1E5BB8DBF616B776D70C25774C1AC11CD6B6791D15850C37F7F176F49DBB6#) ) ) s_sig: (sig-val (gost (r #430C6EE1C0126F217B58EF5FB2E25055B2DF64AF0A1D769F2E7402145322ACD77B7D537B985AD7F3E3EDE94F9521D2F1E039B6F818B88D1CD709BE7BA97FE5E7#) (s #6A75146760E21BF6FA4CEDB41D37D938D5988DE048F9171796E764EC0E90891A7E02CA7F855C2468E11D217DB5C28DFAB1E31FF45793029FCDD666BE589F646A#) ) (hash stribog512) ) s_hash: (data (flags gost) (value #AD66AC68C832442C9520718AF9F67A87518CFE23098886C075F09DD19AC626DA65D7E39F6E0F81F5CF19C7DC5C3C9CC75FAD26A6C450ADD4C02FD31B49BA7CF1#) ) check_cms: verify test_cms_ksba.txt.p7s Ok check_cms: save_cert.der bash-4.3$
/ , :
bash-4.3$ ./check_cms_signed test_cms_ksba.txt.p7s test_cms_ksba_Change.txt save_cert.der *** checking `test_cms_ksba.txt.p7s' *** Bad content test_cms_ksba_Change.txt bash-4.3$
<
> ( sace_cert.der).
, .
. (PKCS#7, VKO, KEK), , . .