class ECPrivateKey(Sequence): schema = ( ("version", Integer(ecPrivkeyVer1)), ("privateKey", OctetString()), ("parameters", ECParameters(expl=tag_ctxc(0), optional=True)), ("publicKey", BitString(expl=tag_ctxc(1), optional=True)), )
class EncapsulatedContentInfo(Sequence): # EncapsulatedContentInfo ::= SEQUENCE { # eContentType ContentType, # eContent [0] EXPLICIT OCTET STRING OPTIONAL } schema = ( ("eContentType", ContentType()), ("eContent", OctetString(expl=tag_ctxc(0), optional=True)), )
class GostR34102001TransportParameters(Sequence): schema = ( ("encryptionParamSet", ObjectIdentifier()), ("ephemeralPublicKey", SubjectPublicKeyInfo( impl=tag_ctxc(0), optional=True, )), ("ukm", OctetString()), )
def process_cert(self, curve_name, mode, hasher, prv_key_raw, cert_raw): cert, tail = Certificate().decode( cert_raw, ctx={ "defines_by_path": (( ( "tbsCertificate", "subjectPublicKeyInfo", "algorithm", "algorithm", ), (( ("..", "subjectPublicKey"), { id_tc26_gost3410_2012_256: OctetString(), id_tc26_gost3410_2012_512: OctetString(), }, ), ), ), ), }) self.assertSequenceEqual(tail, b"") curve = CURVES[curve_name] prv_key = prv_unmarshal(prv_key_raw) spk = cert["tbsCertificate"]["subjectPublicKeyInfo"][ "subjectPublicKey"] self.assertIsNotNone(spk.defined) _, pub_key_raw = spk.defined pub_key = pub_unmarshal(bytes(pub_key_raw), mode=mode) self.assertSequenceEqual(pub_key, public_key(curve, prv_key)) self.assertTrue( verify( curve, pub_key, hasher(cert["tbsCertificate"].encode()).digest()[::-1], bytes(cert["signatureValue"]), mode=mode, ))
def process_cert(self, curve_name, mode, hasher, prv_key_raw, cert_raw): cert, tail = Certificate().decode(cert_raw) self.assertSequenceEqual(tail, b"") curve = GOST3410Curve(*CURVE_PARAMS[curve_name]) prv_key = prv_unmarshal(prv_key_raw) pub_key_raw, tail = OctetString().decode( bytes(cert["tbsCertificate"]["subjectPublicKeyInfo"] ["subjectPublicKey"])) pub_key = pub_unmarshal(bytes(pub_key_raw), mode=mode) self.assertSequenceEqual(tail, b"") self.assertSequenceEqual(pub_key, public_key(curve, prv_key)) self.assertTrue( verify( curve, pub_key, hasher(cert["tbsCertificate"].encode()).digest()[::-1], bytes(cert["signatureValue"]), mode=mode, ))
class GeneralName(Choice): # GeneralName ::= CHOICE { # otherName [0] OtherName, # rfc822Name [1] IA5String, # dNSName [2] IA5String, # x400Address [3] ORAddress, # directoryName [4] Name, # ediPartyName [5] EDIPartyName, # uniformResourceIdentifier [6] IA5String, # iPAddress [7] OCTET STRING, # registeredID [8] OBJECT IDENTIFIER } schema = ( ("otherName", OtherName(impl=tag_ctxp(0))), ("rfc822Name", IA5String(impl=tag_ctxp(1))), ("dNSName", IA5String(impl=tag_ctxp(2))), ("x400Address", ORAddress(impl=tag_ctxp(3))), ("directoryName", Name(expl=tag_ctxp(4))), ("ediPartyName", EDIPartyName(impl=tag_ctxp(5))), ("uniformResourceIdentifier", IA5String(impl=tag_ctxp(6))), ("iPAddress", OctetString(impl=tag_ctxp(7))), ("registeredID", ObjectIdentifier(impl=tag_ctxp(8))), )
def process_cms( self, content_info_raw, prv_key_our, curve_name, keker, plaintext_expected, ): sbox = "Gost28147_tc26_ParamZ" content_info, tail = ContentInfo().decode(content_info_raw) self.assertSequenceEqual(tail, b"") enveloped_data, tail = EnvelopedData().decode( bytes(content_info["content"])) self.assertSequenceEqual(tail, b"") eci = enveloped_data["encryptedContentInfo"] ri = enveloped_data["recipientInfos"][0] encrypted_key, tail = GostR3410KeyTransport().decode( bytes(ri["ktri"]["encryptedKey"])) self.assertSequenceEqual(tail, b"") ukm = bytes(encrypted_key["transportParameters"]["ukm"]) spk = bytes(encrypted_key["transportParameters"]["ephemeralPublicKey"] ["subjectPublicKey"]) pub_key_their, tail = OctetString().decode(spk) self.assertSequenceEqual(tail, b"") curve = GOST3410Curve(*CURVE_PARAMS[curve_name]) kek = keker(curve, prv_key_our, bytes(pub_key_their), ukm) key_wrapped = bytes( encrypted_key["sessionEncryptedKey"]["encryptedKey"]) mac = bytes(encrypted_key["sessionEncryptedKey"]["macKey"]) cek = unwrap_cryptopro(kek, ukm + key_wrapped + mac, sbox=sbox) ciphertext = bytes(eci["encryptedContent"]) encryption_params, tail = Gost2814789Parameters().decode( bytes(eci["contentEncryptionAlgorithm"]["parameters"])) self.assertSequenceEqual(tail, b"") iv = bytes(encryption_params["iv"]) self.assertSequenceEqual( cfb_decrypt(cek, ciphertext, iv, sbox=sbox, mesh=True), plaintext_expected, )
def process_cms( self, content_info_raw, prv_key_our, curve_name, keker, plaintext_expected, ): sbox = "Gost28147_tc26_ParamZ" content_info, tail = ContentInfo().decode(content_info_raw) self.assertSequenceEqual(tail, b"") enveloped_data, tail = EnvelopedData().decode( bytes(content_info["content"])) self.assertSequenceEqual(tail, b"") eci = enveloped_data["encryptedContentInfo"] kari = enveloped_data["recipientInfos"][0]["kari"] pub_key_their, tail = OctetString().decode( bytes(kari["originator"]["originatorKey"]["publicKey"]), ) self.assertSequenceEqual(tail, b"") ukm = bytes(kari["ukm"]) rek = kari["recipientEncryptedKeys"][0] curve = GOST3410Curve(*CURVE_PARAMS[curve_name]) kek = keker(curve, prv_key_our, bytes(pub_key_their), ukm) encrypted_key, tail = Gost2814789EncryptedKey().decode( bytes(rek["encryptedKey"]), ) self.assertSequenceEqual(tail, b"") key_wrapped = bytes(encrypted_key["encryptedKey"]) mac = bytes(encrypted_key["macKey"]) cek = unwrap_gost(kek, ukm + key_wrapped + mac, sbox=sbox) ciphertext = bytes(eci["encryptedContent"]) encryption_params, tail = Gost2814789Parameters().decode( bytes(eci["contentEncryptionAlgorithm"]["parameters"])) self.assertSequenceEqual(tail, b"") iv = bytes(encryption_params["iv"]) self.assertSequenceEqual( cfb_decrypt(cek, ciphertext, iv, sbox=sbox, mesh=True), plaintext_expected, )
def _parse_asn_public_key(cls, info: SubjectPublicKeyInfo) -> OctetString: private_key, tail = OctetString().decode( bytes(info["subjectPublicKey"])) if tail: raise CertNotValid("trailing data after ASN.1 of public key info") return private_key
def _test_vector( self, curve_name, mode, hsh, ai_spki, ai_sign, cert_serial, prv_hex, cr_sign_hex, cr_b64, c_sign_hex, c_b64, crl_sign_hex, crl_b64, ): prv_raw = hexdec(prv_hex)[::-1] prv = prv_unmarshal(prv_raw) curve = CURVES[curve_name] pub = public_key(curve, prv) pub_raw = pub_marshal(pub, mode=mode) subj = Name( ("rdnSequence", RDNSequence([ RelativeDistinguishedName((AttributeTypeAndValue(( ("type", AttributeType(id_at_commonName)), ("value", AttributeValue(PrintableString("Example"))), )), )) ]))) spki = SubjectPublicKeyInfo(( ("algorithm", ai_spki), ("subjectPublicKey", BitString(OctetString(pub_raw).encode())), )) # Certification request cri = CertificationRequestInfo(( ("version", Integer(0)), ("subject", subj), ("subjectPKInfo", spki), ("attributes", Attributes()), )) sign = hexdec(cr_sign_hex) self.assertTrue( verify( curve, pub, hsh(cri.encode()).digest()[::-1], sign, mode=mode, )) cr = CertificationRequest(( ("certificationRequestInfo", cri), ("signatureAlgorithm", ai_sign), ("signature", BitString(sign)), )) self.assertSequenceEqual(cr.encode(), b64decode(cr_b64)) # Certificate tbs = TBSCertificate(( ("version", Version("v3")), ("serialNumber", CertificateSerialNumber(cert_serial)), ("signature", ai_sign), ("issuer", subj), ("validity", Validity(( ("notBefore", Time(("utcTime", UTCTime(b"010101000000Z")))), ("notAfter", Time(("generalTime", GeneralizedTime(b"20501231000000Z")))), ))), ("subject", subj), ("subjectPublicKeyInfo", spki), ("extensions", Extensions((Extension(( ("extnID", id_ce_basicConstraints), ("critical", Boolean(True)), ("extnValue", OctetString( BasicConstraints((("cA", Boolean(True)), )).encode())), )), ))), )) sign = hexdec(c_sign_hex) self.assertTrue( verify( curve, pub, hsh(tbs.encode()).digest()[::-1], sign, mode=mode, )) cert = Certificate(( ("tbsCertificate", tbs), ("signatureAlgorithm", ai_sign), ("signatureValue", BitString(sign)), )) self.assertSequenceEqual(cert.encode(), b64decode(c_b64)) # CRL tbs = TBSCertList(( ("version", Version("v2")), ("signature", ai_sign), ("issuer", subj), ("thisUpdate", Time(("utcTime", UTCTime(b"140101000000Z")))), ("nextUpdate", Time(("utcTime", UTCTime(b"140102000000Z")))), )) sign = hexdec(crl_sign_hex) self.assertTrue( verify( curve, pub, hsh(tbs.encode()).digest()[::-1], sign, mode=mode, )) crl = CertificateList(( ("tbsCertList", tbs), ("signatureAlgorithm", ai_sign), ("signatureValue", BitString(sign)), )) self.assertSequenceEqual(crl.encode(), b64decode(crl_b64))
def process_cms( self, content_info_raw, prv_key_our, curve_name, keker, plaintext_expected, ): sbox = "id-tc26-gost-28147-param-Z" content_info, tail = ContentInfo().decode( content_info_raw, ctx={ "defines_by_path": [( ( "content", DecodePathDefBy(id_envelopedData), "recipientInfos", any, "kari", "originator", "originatorKey", "algorithm", "algorithm", ), (( ("..", "publicKey"), { id_tc26_gost3410_2012_256: OctetString(), id_tc26_gost3410_2012_512: OctetString(), }, ), ), ) for _ in ( id_tc26_gost3410_2012_256, id_tc26_gost3410_2012_512, )], }) self.assertSequenceEqual(tail, b"") self.assertIsNotNone(content_info["content"].defined) _, enveloped_data = content_info["content"].defined eci = enveloped_data["encryptedContentInfo"] kari = enveloped_data["recipientInfos"][0]["kari"] self.assertIsNotNone( kari["originator"]["originatorKey"]["publicKey"].defined) _, pub_key_their = kari["originator"]["originatorKey"][ "publicKey"].defined ukm = bytes(kari["ukm"]) rek = kari["recipientEncryptedKeys"][0] curve = CURVES[curve_name] kek = keker(curve, prv_key_our, bytes(pub_key_their), ukm) self.assertIsNotNone(rek["encryptedKey"].defined) _, encrypted_key = rek["encryptedKey"].defined key_wrapped = bytes(encrypted_key["encryptedKey"]) mac = bytes(encrypted_key["macKey"]) cek = unwrap_gost(kek, ukm + key_wrapped + mac, sbox=sbox) ciphertext = bytes(eci["encryptedContent"]) self.assertIsNotNone( eci["contentEncryptionAlgorithm"]["parameters"].defined) _, encryption_params = eci["contentEncryptionAlgorithm"][ "parameters"].defined iv = bytes(encryption_params["iv"]) self.assertSequenceEqual( cfb_decrypt(cek, ciphertext, iv, sbox=sbox, mesh=True), plaintext_expected, )
class Extension(Sequence): schema = ( ("extnID", ObjectIdentifier()), ("critical", Boolean(default=False)), ("extnValue", OctetString()), )
class MacData(Sequence): schema = ( ("mac", DigestInfo()), ("macSalt", OctetString()), ("iterations", Integer(default=1)), )
class DigestInfo(Sequence): schema = ( ("digestAlgorithm", AlgorithmIdentifier()), ("digest", OctetString()), )
class EncryptedPrivateKeyInfo(Sequence): schema = ( ("encryptionAlgorithm", EncryptionAlgorithmIdentifier()), ("encryptedData", OctetString()), )
class EncapsulatedContentInfo(Sequence): schema = ( ("eContentType", ContentType()), ("eContent", OctetString(expl=tag_ctxc(0), optional=True)), )
class PBKDF2Salt(Choice): schema = ( ("specified", OctetString()), # ("otherSource", PBKDF2SaltSources()), )
class RevokedCertificates(SequenceOf): # schema = RevokedCertificate() schema = OctetString() # dummy
("signature", ai_sign), ("issuer", subj), ("validity", Validity(( ("notBefore", Time(("utcTime", UTCTime(not_before)))), ("notAfter", Time(("utcTime", UTCTime(not_after)))), ))), ("subject", subj), ("subjectPublicKeyInfo", SubjectPublicKeyInfo(( ("algorithm", AlgorithmIdentifier(( ("algorithm", id_tc26_gost3410_2012_512), ("parameters", Any(key_params)), ))), ("subjectPublicKey", BitString(OctetString(pub_raw).encode())), ))), ("extensions", Extensions((Extension(( ("extnID", id_ce_subjectKeyIdentifier), ("extnValue", OctetString( SubjectKeyIdentifier( GOST34112012512(pub_raw).digest()[:20]).encode())), )), ))), )) cert = Certificate(( ("tbsCertificate", tbs), ("signatureAlgorithm", ai_sign), ("signatureValue", BitString(