PyDERASN: ki jan mwen te ekri yon bibliyotèk ASN.1 ak emplacements ak blobs

ASN.1 sa a se yon estanda (ISO, ITU-T, GOST) nan yon lang ki dekri enfòmasyon estriktire, osi byen ke règ pou kode enfòmasyon sa a. Pou mwen, kòm yon pwogramè, sa a se jis yon lòt fòma pou seri ak prezante done, ansanm ak JSON, XML, XDR ak lòt moun. Li trè komen nan lavi chak jou nou an, ak anpil moun rankontre li: nan selilè, telefòn, kominikasyon VoIP (UMTS, LTE, WiMAX, SS7, H.323), nan pwotokòl rezo (LDAP, SNMP, Kerberos), nan tout bagay ki konsène kriptografik (X.509, CMS, PKCS estanda), nan kat labank ak paspò byometrik, ak plis ankò.

Atik sa a trete PyDERASN: Python ASN.1 bibliyotèk itilize aktivman nan pwojè ki gen rapò ak kriptografik nan Atlas.

PyDERASN: ki jan mwen te ekri yon bibliyotèk ASN.1 ak emplacements ak blobs
An jeneral, ASN.1 pa vo rekòmande pou travay kriptografik: ASN.1 ak kodèk li yo konplèks. Sa vle di ke kòd la pa pral senp, epi sa a se toujou yon vektè atak siplemantè. Jis gade nan lis la vilnerabilite nan bibliyotèk ASN.1. Bruce Schneier nan li Jeni kriptografik tou konseye pa sèvi ak estanda sa a akòz konpleksite li: "Kodaj TLV ki pi koni a se ASN.1, men li ekstrèmman konplèks epi nou timid lwen li." Men, malerezman, jodi a nou genyen enfrastrikti kle piblik kote yo aktivman itilize Sètifika X.509, CRL, OCSP, TSP, CMP pwotokòl, CMC, mesaj CMS, ak anpil estanda PKCS. Se poutèt sa, ou dwe kapab travay ak ASN.1 si w ap fè anyen ki gen rapò ak kriptografik.

ASN.1 ka kode nan yon varyete fason/kodèk:

  • Sonje (Règ debaz kodaj)
  • CER (Règ kodaj kanonik)
  • DER (Règ kodaj distenge)
  • GSER (Règ jenerik kòd kòd)
  • JER (Règ kodaj JSON)
  • LWER (Règ kodaj pwa limyè)
  • REO (Règ kodaj Octet)
  • POU CHAK (Pakè Règ Kodaj)
  • SER (Siyal Règ espesifik Kodaj)
  • DISIP (Règ kodaj XML)

ak yon kantite lòt. Men, nan travay kriptografik, nan pratik, yo itilize de: BER ak DER. Menm nan dokiman XML siyen (XMLDSig, XAdES) pral toujou gen objè DER ASN.64 kode Base1, tankou nan pwotokòl oryante JSON. akme soti nan Ann ankripte. Ou ka pi byen konprann tout kodèk sa yo ak prensip kodaj BER/CER/DER nan atik ak liv: ASN.1 nan mo senp, ASN.1 — Kominikasyon ant sistèm etewojèn pa Olivier Dubuisson, ASN.1 Konplete pa Prof John Larmouth.

BER se yon fòma TLV binè oryante byte (pa egzanp PER, popilè nan kominikasyon selilè - bit-oryante). Chak eleman kode kòm: tag (Tag), idantifye ki kalite eleman yo dwe kode (nèg nonb, fisèl, dat, elatriye), longè (Length) kontni ak kontni an li menm (Vali). BER opsyonèlman pèmèt ou pa presize yon valè longè lè w mete yon valè longè endefini espesyal epi mete fen nan mesaj Fen-Oktèt la ak yon mak Fen-Oktèt. Anplis kodaj longè, BER gen anpil varyasyon nan fason li kode kalite done, tankou:

  • ENTÈJÈ, IDANTIFIKÈ OBJÈ, BIT STRING ak longè eleman yo ka pa nòmalize (pa kode nan fòm minim);
  • BOOLEAN se vre pou nenpòt kontni ki pa zewo;
  • BIT STRING ka genyen "anplis" zewo bit;
  • BIT STRING, OCTET STRING ak tout kalite fisèl ki sòti yo, ki gen ladan dat/lè, ka kase an fragman longè varyab, longè ki pa konnen davans nan moman (de)kodaj la;
  • UTCTime/GeneralizedTime ka gen diferan fason pou presize desantre zòn tan an ak fraksyon zewo "anplis" nan segonn;
  • Valè SEKANS DEFAULT yo ka oswa pa ka kode;
  • Valè yo nonmen dènye bit yo nan yon BIT STRING ka opsyonèlman pa kode;
  • SEQUENCE (OF)/SET (OF) ka gen nenpòt lòd nan eleman.

Akòz tout sa ki anwo yo, done kode pou li idantik ak fòm orijinal la pa toujou posib. Se poutèt sa, yo te envante yon sou-ansanm nan règ: DER - estrikteman reglemante yon sèl metòd kodaj ki valab, ki se kritik pou travay kriptografik kote, pou egzanp, chanje yon ti jan ap fè siyati a oswa checksum envalid. DER gen yon dezavantaj enpòtan: longè tout eleman yo dwe konnen davans nan tan kodaj, ki pa pèmèt serializasyon kouran done yo. Codec CER la pa gen dezavantaj sa a, menm jan an tou garanti yon reprezantasyon san anbigwi nan done yo. Malerezman (oswa èske li ere ke nou pa gen menm dekodè ki pi konplèks?), Li pa t 'vin popilè. Se poutèt sa, nan pratik nou rankontre yon itilizasyon "melanje" nan BER ak DER done kode. Piske tou de CER ak DER yo se yon ti gwoup BER, nenpòt dekodeur BER ka okipe yo.

Pwoblèm ak pyasn1

Nan travay nou ekri anpil pwogram Python ki gen rapò ak kriptografi. Ak kèk ane de sa pa te gen pratikman pa gen okenn chwa nan bibliyotèk gratis: swa sa yo se bibliyotèk trè ba-nivo ki pèmèt ou tou senpleman kode / dekode, pou egzanp, yon nonb antye relatif ak yon header estrikti, oswa bibliyotèk sa a. pyasn1. Nou te viv sou li pandan plizyè ane e okòmansman nou te trè kontan, paske li pèmèt ou travay ak estrikti ASN.1 menm jan ak objè wo nivo: pou egzanp, yon objè sètifika X.509 dekode pèmèt ou jwenn aksè nan jaden li yo atravè. yon koòdone diksyonè: cert[“tbsCertificate”] ["serialNumber"] ap montre nou nimewo seri sètifika sa a. Menm jan an tou, ou ka "rasanble" objè konplèks lè w ap travay avèk yo kòm lis, diksyonè, epi tou senpleman rele fonksyon pyasn1.codec.der.encoder.encode epi jwenn yon reprezantasyon seri dokiman an.

Sepandan, enpèfeksyon, pwoblèm ak limit yo te revele. Te gen epi, malerezman, toujou gen erè nan pyasn1: nan moman sa a nan ekri a, youn nan kalite debaz yo nan pyasn1 se GeneralizedTime, kòrèk dekode ak kode.

Nan pwojè nou yo, pou konsève pou espas, nou souvan estoke sèlman chemen fichye a, konpanse ak longè an byte nan objè a nou vle referans. Pa egzanp, yon fichye siyen abitrè pral gen plis chans nan estrikti CMS SignedData ASN.1:

  0     [1,3,1018]  ContentInfo SEQUENCE
  4     [1,1,   9]   . contentType: ContentType OBJECT IDENTIFIER 1.2.840.113549.1.7.2 (id_signedData)
 19-4   [0,0,1003]   . content: [0] EXPLICIT [UNIV 16] ANY
 19     [1,3, 999]   . . DEFINED BY id_signedData: SignedData SEQUENCE
 23     [1,1,   1]   . . . version: CMSVersion INTEGER v3 (03)
 26     [1,1,  19]   . . . digestAlgorithms: DigestAlgorithmIdentifiers SET OF
                           [...]
 47     [1,3, 769]   . . . encapContentInfo: EncapsulatedContentInfo SEQUENCE
 51     [1,1,   8]   . . . . eContentType: ContentType OBJECT IDENTIFIER 1.3.6.1.5.5.7.12.2 (id_cct_PKIData)
 65-4   [1,3, 751]   . . . . eContent: [0] EXPLICIT OCTET STRING 751 bytes OPTIONAL

                 ТУТ СОДЕРЖИМОЕ ПОДПИСЫВАЕМОГО ФАЙЛА РАЗМЕРОМ 751 байт

820     [1,2, 199]   . . . signerInfos: SignerInfos SET OF
823     [1,2, 196]   . . . . 0: SignerInfo SEQUENCE
826     [1,1,   1]   . . . . . version: CMSVersion INTEGER v3 (03)
829     [0,0,  22]   . . . . . sid: SignerIdentifier CHOICE subjectKeyIdentifier
                               [...]
956     [1,1,  64]   . . . . . signature: SignatureValue OCTET STRING 64 bytes
                     . . . . . . C1:B3:88:BA:F8:92:1C:E6:3E:41:9B:E0:D3:E9:AF:D8
                     . . . . . . 47:4A:8A:9D:94:5D:56:6B:F0:C1:20:38:D2:72:22:12
                     . . . . . . 9F:76:46:F6:51:5F:9A:8D:BF:D7:A6:9B:FD:C5:DA:D2
                     . . . . . . F3:6B:00:14:A4:9D:D7:B5:E1:A6:86:44:86:A7:E8:C9

epi nou ka jwenn fichye orijinal la siyen nan konpanse 65 bytes, 751 bytes long. pyasn1 pa estoke enfòmasyon sa a nan objè dekode li yo. Sa yo rele TLVSeeker la te ekri - yon ti bibliyotèk ki pèmèt ou dekode tag ak longè objè, nan koòdone nan ki nou te bay lòd "ale nan pwochen tag la", "ale andedan tag la" (ale andedan objè a SEQUENCE), "ale nan pwochen tag la", "di konpanse ou ak longè objè a kote nou ye." Sa a se te yon "manyèl" mache nan done ASN.1 DER-serialize. Men, li te enposib travay ak done BER-serialize nan fason sa a, paske, pou egzanp, OCTET STRING kòd byte a te kapab kode nan fòm lan nan plizyè fragman.

Yon lòt dezavantaj pou travay pyasn1 nou yo se enkapasite pou konprann nan objè yo dekode si yon jaden bay te prezan nan SEQUANS la oswa ou pa. Pa egzanp, si estrikti a gen yon jaden SEQUENCE OF Smth OPTIONAL, Lè sa a, li ta ka konplètman absan nan done yo fèk ap rantre (OPTIONAL), oswa li ta ka prezan, men li dwe nan longè zewo (lis vid). An jeneral, sa a pa t 'kapab detèmine. Lè sa a se nesesè pou verifikasyon strik nan validite a nan done yo resevwa. Imajine ke kèk otorite sètifikasyon ta bay yon sètifika ak done ki "pa totalman" valab nan pwen de vi rapid ASN.1! Pou egzanp, otorite sètifikasyon "TÜRKTRUST Elektronik Sertifika Hizmet Sağlayıcısı" depase limit akseptab nan sètifika rasin li yo. RFC 5280 limit sou longè eleman sijè a - li pa ka onètman dekode dapre konplo a. Kodèk DER a mande pou yon jaden ki gen valè ki egal a DEFAULT pa kode pandan transmisyon - dokiman sa yo rive nan lavi a, e premye vèsyon PyDERASN a menm fè espre pèmèt yon konpòtman envalid (soti nan pwen de vi DER la) pou dedomajman pou yo. konpatibilite bak.

Yon lòt limit se enkapasite a fasil pou chèche konnen nan ki fòm (BER/DER) yon objè patikilye te kode nan estrikti a. Pou egzanp, estanda CMS la di ke mesaj la se BER-kode, men jaden an signedAttrs, sou ki siyati kriptografik la pwodwi, dwe nan DER. Si nou dekode ak DER, nou pral echwe nan pwosesis CMS la li menm; si nou dekode ak BER, nou pa pral konnen nan ki fòm siyenAttrs la te nan. Kòm yon rezilta, TLVSeeker (ki pa gen okenn analogue nan pyasn1) ap oblije chèche kote chak nan jaden siyenAttrs yo, epi separeman, pran li soti nan reprezantasyon seri a, dekode li ak DER.

Kapasite nan otomatikman trete jaden DEFINI BY, ki rive trè souvan, te trè dezirab pou nou. Apre dekode estrikti ASN.1 a, nou ka rete ak anpil NENPÒT jaden ki dwe trete pi lwen dapre konplo a chwazi ki baze sou IDENTIFÈ OBJÈ ki espesifye nan jaden an estrikti. Nan kòd Python, sa vle di ekri si ak Lè sa a, rele dekodè a pou nenpòt ki jaden.

Aparisyon PyDERASN

Atlas, nou regilyèman voye plak nan tèt lè nou jwenn kèk pwoblèm oswa amelyore pwogram gratis nou itilize yo. Nou te soumèt amelyorasyon nan pyasn1 plizyè fwa, men kòd pyasn1 a se pa pi fasil pou konprann epi pafwa te gen chanjman API enkonpatib ki te bat nou. Anplis, nou abitye ekri tès ak tès jeneratif, ki pa t 'ka a nan pyasn1.

Yon bon jou mwen te deside ke mwen te gen ase nan li e li te tan eseye ekri pwòp bibliyotèk mwen ak __slot__s, konpanse ak bèl parèt blobs! Senpleman kreye yon codec ASN.1 pa ta ase - nou bezwen transfere tout pwojè depandan nou yo nan li, ak sa yo se dè santèn de milye de liy nan kòd ki plen ak travay ak estrikti ASN.1. Sa se, youn nan kondisyon yo pou li: fasilite nan tradiksyon nan aktyèl la pyasn1 kòd. Mwen te pase tout vakans mwen yo, mwen te ekri bibliyotèk sa a epi mwen te transfere tout pwojè yo nan li. Depi yo gen prèske 100% pwoteksyon ak tès yo, sa vle di ke bibliyotèk la te konplètman operasyonèl.

PyDERASN, menm jan an tou, gen prèske 100% pwoteksyon tès. Sèvi ak tès jeneratif ak yon bibliyotèk gwo ipotèz. Li te tou te pote soti flou py-afl- Mwen manje sou 32 machin nikleyè. Malgre lefèt ke nou pa gen pratikman okenn kòd Python2 ki rete, PyDERASN toujou kenbe konpatibilite ak li ak poutèt sa a gen sèlman nan. sis dejwe. Anplis, li teste kont ASN.1:2008 konfòmite tès suite.

Prensip la nan travay avèk li se menm jan ak pyasn1 - travay ak objè wo nivo Python. Deskripsyon plan ASN.1 yo sanble.

class TBSCertificate(Sequence):
    schema = (
        ("version", Version(expl=tag_ctxc(0), default="v1")),
        ("serialNumber", CertificateSerialNumber()),
        ("signature", AlgorithmIdentifier()),
        ("issuer", Name()),
        ("validity", Validity()),
        ("subject", Name()),
        ("subjectPublicKeyInfo", SubjectPublicKeyInfo()),
        ("issuerUniqueID", UniqueIdentifier(impl=tag_ctxp(1), optional=True)),
        ("subjectUniqueID", UniqueIdentifier(impl=tag_ctxp(2), optional=True)),
        ("extensions", Extensions(expl=tag_ctxc(3), optional=True)),
    )

Sepandan, PyDERASN gen kèk sanble nan sezisman fò. Nan pyasn1, si yon jaden te nan kalite CMSVersion (INTEGER), Lè sa a, li ta ka asiyen int oswa INTEGER. PyDERASN entèdi mande pou objè a asiyen egzakteman CMSVersion. Anplis ekri kòd Python3, nou itilize tou sezisman anons yo, kidonk fonksyon nou yo p ap gen agiman fènwa tankou def func (seri, kontni), men def func (seri: CertificateSerialNumber, kontni: EncapsulatedContentInfo), ak PyDERASN ede kenbe kòd sa a.

An menm tan an, PyDERASN gen konsesyon trè pratik nan sezisman sa a. pyasn1 pa t pèmèt jaden SubjectKeyIdentifier().subtype(implicitTag=Tag(...)) bay yon objè nan SubjectKeyIdentifier() (san TAG ENPLLICIT ki nesesè a) e li te nesesè pou souvan kopye ak rekreye objè jis paske tags ENPLLIS/EXPLICIT yo chanje. PyDERASN estrikteman obsève sèlman kalite baz la - li pral otomatikman ranplase tags nan chema ASN.1 ki deja egziste nan estrikti a. Sa a anpil senplifye kòd aplikasyon an.

Si yon erè rive pandan dekodaj, Lè sa a, nan pyasn1 li pa fasil pou konprann ki kote egzakteman li te fèt. Pou egzanp, nan sètifika Tik ki deja mansyone pi wo a, nou pral resevwa erè sa a: UTF8String (tbsCertificate:issuer:rdnSequence:3:0:value:DEFINED BY 2.5.4.10:utf8String) (nan 138) limit ki pa satisfè: 1 ⇐ 77 ⇐ 64 Lè yo ekri estrikti ASN .1 moun ka fè erè, e sa fè li pi fasil pou debogaj aplikasyon yo oswa pou detèmine pwoblèm ak dokiman kode lòt pati a.

Premye vèsyon PyDERASN pa t sipòte kodaj BER. Li te parèt pita epi li toujou pa sipòte pwosesis UTCTime/GeneralizedTime ak zòn tan yo. Sa a pral vini nan tan kap vini an, paske se pwojè a ekri sitou nan tan lib mwen an.

Epitou, nan premye vèsyon an pa te gen okenn travay ak DEFINED BY jaden. Kèk mwa apre sa opòtinite leve epi yo te kòmanse aktivman itilize, siyifikativman diminye kòd aplikasyon - nan yon sèl operasyon dekodaj li te posib jwenn estrikti a tout antye demonte nan pwofondè anpil. Pou fè sa, chema a presize ki jaden "defini" ki sa. Pou egzanp, yon deskripsyon konplo CMS la:

class ContentInfo(Sequence):
    schema = (
        ("contentType", ContentType(defines=((("content",), {
            id_authenticatedData: AuthenticatedData(),
            id_digestedData: DigestedData(),
            id_encryptedData: EncryptedData(),
            id_envelopedData: EnvelopedData(),
            id_signedData: SignedData(),
        }),))),
        ("content", Any(expl=tag_ctxc(0))),
    )

di ke si contentType a gen yon OID ki gen valè id_signedData, Lè sa a, jaden kontni an (ki sitiye nan menm SEQUANS la) dwe dekode dapre konplo a SignedData. Poukisa gen anpil parantèz? Yon jaden ka "defini" plizyè jaden an menm tan, tankou se ka a nan EnvelopedData estrikti. Jaden defini yo idantifye pa sa yo rele chemen dekode - li presize kote egzak nenpòt eleman nan tout estrikti.

Ou pa toujou vle oswa ou pa toujou gen opòtinite imedyatman ajoute defini sa yo nan dyagram nan. Ka gen ka aplikasyon espesifik lè OID ak estrikti yo konnen sèlman nan yon pwojè twazyèm pati. PyDERASN bay kapasite pou mete defini sa yo dwat nan moman dekode estrikti a:

ContentInfo().decode(data, ctx={"defines_by_path": ((
    (
        "content", DecodePathDefBy(id_signedData),
        "certificates", any, "certificate", "tbsCertificate",
        "extensions", any, "extnID",
    ),
    ((("extnValue",), {
        id_ce_authorityKeyIdentifier: AuthorityKeyIdentifier(),
        id_ce_basicConstraints: BasicConstraints(),
        [...]
        id_ru_subjectSignTool: SubjectSignTool(),
    }),),
),)})

Isit la nou di ke nan CMS SignedData pou tout sètifika tache, dekode tout ekstansyon yo (AuthorityKeyIdentifier, BasicConstraints, SubjectSignTool, elatriye). Nou endike nan chemen an dekode ki eleman ki bezwen "ranplase" ak defini, tankou si li te espesifye nan chema a.

Finalman, PyDERASN gen kapasite pou kouri soti liy lòd pou dekode dosye ASN.1 epi li gen moun rich bèl enprime. Ou ka dekode yon ASN.1 abitrè, oswa ou ka presize yon konplo defini aklè epi wè yon bagay tankou sa a:

PyDERASN: ki jan mwen te ekri yon bibliyotèk ASN.1 ak emplacements ak blobs

Enfòmasyon ki parèt: desantre objè, longè tag, longè longè, longè kontni, prezans EOC (fen-oktèt), atribi kodaj BER, atribi kodaj longè endefini, longè ak konpanse tag EXPLICIT (si genyen), pwofondè nidifikasyon nan objè a nan estrikti, valè tag IMPLICIT/EXPLICIT, non objè dapre konplo a, kalite baz ASN.1 li yo, nimewo sekans andedan SEQUENCE/SET OF, CHOICE valè (si genyen), non moun lizib INTEGER/ENUMERATED/BIT STRING dapre konplo a, valè nenpòt ki kalite baz , DEFAULT/OPTIONAL drapo soti nan konplo a, yon siy ke objè a te otomatikman dekode kòm DEFINI BY ak akòz ki OID sa te rive, OID moun-lizib.

Se sistèm nan enprime bèl ki fèt espesyalman pou ke li jenere yon sekans nan objè PP ke yo vizyalize lè l sèvi avèk mwayen separe. Ekran an montre rannman an nan tèks ki senp koulè. Genyen tou rann nan fòma JSON/HTML, pou li ka wè ak en nan navigatè ASN.1, tankou nan asn1js pwojè.

Lòt bibliyotèk

Sa a pa t 'objektif la, men PyDERASN te tounen soti anpil pi vit pase pyasn1. Pou egzanp, dekode dosye CRL ki gen gwosè megaokte ka pran anpil tan ke ou oblije reflechi sou fòma depo done entèmedyè (vit) epi chanje achitekti aplikasyon an. pyasn1 dekode CRL CACert.org sou laptop mwen an pran plis pase 20 minit, pandan y ap PyDERASN pran jis 28 segonn! Gen yon pwojè asn1crypto, ki vize a travay rapid ak estrikti kriptografik: li dekode (konplètman, pa parese) menm CRL nan 29 segonn, men konsome prèske de fwa plis RAM lè kouri anba Python3 (983 MiB kont 498), ak nan 3.5 fwa anba Python2 (1677). kont 488), pandan y ap pyasn1 konsome otan ke 4.3 fwa plis (2093 kont 488).

Nou pa t konsidere asn1crypto, ke mwen mansyone, paske pwojè a te toujou nan anfans li epi nou pa t 'tande pale sou li. Koulye a, nou pa ta gade nan direksyon li tou, paske mwen imedyatman dekouvri ke menm GeneralizedTime a pa pran yon fòm abitrè, epi pandan serializasyon li an silans retire yon fraksyon nan yon segonn. Sa a se akseptab pou travay ak sètifika X.509, men an jeneral li pa pral travay.

Nan moman sa a, PyDERASN se pi strik dekode Python/Go DER gratis mwen konnen. Nan bibliyotèk kodaj/asn1 Go mennaj mwen an pa yon chèk strik OBJECT IDENTIFIER ak UTCTime/GeneralizedTime fisèl. Pafwa sevèrte ka jwenn nan wout la (sitou akòz konpatibilite bak ak aplikasyon ki pi gran ke pèsonn pa pral ranje), kidonk PyDERASN ka pase. divès kalite anviwònman chèk febli.

Kòd pwojè a eseye senp ke posib. Tout bibliyotèk la se yon sèl dosye. Kòd la ekri ak yon anfaz sou fasilite nan konpreyansyon, san yo pa optimize pèfòmans nesesè ak kòd SEK. Li pa, jan mwen te deja di, sipòte dekodaj BER konplè nan UTCTime/GeneralizedTime fisèl, osi byen ke kalite done REAL, RELATIVE OID, EXTERNAL, INSTANCE OF, EMBEDDED PDV, CHARACTER STRING. Nan tout lòt ka yo, mwen pèsonèlman pa wè pwen pou yo sèvi ak lòt bibliyotèk nan Python.

Tankou tout pwojè mwen yo, like PyGOST, GoGOST, NCCP, GoVPN, PyDERASN se konplètman lojisyèl gratis, distribye anba kondisyon yo LGPLv3+, epi li disponib pou telechaje gratis. Gen egzanp itilizasyon isit la ak Tès PyGOST.

Sergey Matveev, cypherpunk, manm Fondasyon SPO, Pwomotè Python/Go, espesyalis an chèf FSUE "STC "Atlas".

Sous: www.habr.com

Add nouvo kòmantè