.
This commit is contained in:
680
xmlrpcserver/deps/pygost-5.12/pygost/test_pfx.py
Normal file
680
xmlrpcserver/deps/pygost-5.12/pygost/test_pfx.py
Normal file
@@ -0,0 +1,680 @@
|
||||
# coding: utf-8
|
||||
# PyGOST -- Pure Python GOST cryptographic functions library
|
||||
# Copyright (C) 2015-2023 Sergey Matveev <stargrave@stargrave.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, version 3 of the License.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from base64 import b64decode
|
||||
from hmac import new as hmac_new
|
||||
from unittest import skipIf
|
||||
from unittest import TestCase
|
||||
|
||||
from pygost import gost3410
|
||||
from pygost.gost28147 import cfb_decrypt
|
||||
from pygost.gost34112012256 import GOST34112012256
|
||||
from pygost.gost34112012512 import GOST34112012512
|
||||
from pygost.gost34112012512 import pbkdf2 as gost34112012_pbkdf2
|
||||
from pygost.gost3412 import GOST3412Kuznechik
|
||||
from pygost.gost3412 import GOST3412Magma
|
||||
from pygost.gost3412 import KEYSIZE
|
||||
from pygost.gost3413 import ctr_acpkm
|
||||
from pygost.gost3413 import mac as omac
|
||||
from pygost.kdf import kdf_tree_gostr3411_2012_256
|
||||
from pygost.kdf import keg
|
||||
from pygost.utils import hexdec
|
||||
from pygost.wrap import kimp15
|
||||
|
||||
|
||||
try:
|
||||
from pyderasn import OctetString
|
||||
|
||||
from pygost.asn1schemas.cms import EncryptedData
|
||||
from pygost.asn1schemas.cms import EnvelopedData
|
||||
from pygost.asn1schemas.cms import SignedAttributes
|
||||
from pygost.asn1schemas.cms import SignedData
|
||||
from pygost.asn1schemas.oids import id_data
|
||||
from pygost.asn1schemas.oids import id_envelopedData
|
||||
from pygost.asn1schemas.oids import id_gostr3412_2015_kuznyechik_ctracpkm
|
||||
from pygost.asn1schemas.oids import id_gostr3412_2015_kuznyechik_wrap_kexp15
|
||||
from pygost.asn1schemas.oids import id_messageDigest
|
||||
from pygost.asn1schemas.oids import id_pbes2
|
||||
from pygost.asn1schemas.oids import id_pkcs12_bagtypes_certBag
|
||||
from pygost.asn1schemas.oids import id_pkcs12_bagtypes_keyBag
|
||||
from pygost.asn1schemas.oids import id_pkcs12_bagtypes_pkcs8ShroudedKeyBag
|
||||
from pygost.asn1schemas.oids import id_pkcs9_certTypes_x509Certificate
|
||||
from pygost.asn1schemas.oids import id_signedData
|
||||
from pygost.asn1schemas.oids import id_tc26_agreement_gost3410_2012_256
|
||||
from pygost.asn1schemas.oids import id_tc26_gost3411_2012_256
|
||||
from pygost.asn1schemas.pfx import CertBag
|
||||
from pygost.asn1schemas.pfx import KeyBag
|
||||
from pygost.asn1schemas.pfx import OctetStringSafeContents
|
||||
from pygost.asn1schemas.pfx import PBES2Params
|
||||
from pygost.asn1schemas.pfx import PFX
|
||||
from pygost.asn1schemas.pfx import PKCS8ShroudedKeyBag
|
||||
from pygost.asn1schemas.pfx import SafeContents
|
||||
from pygost.asn1schemas.x509 import Certificate
|
||||
except ImportError:
|
||||
pyderasn_exists = False
|
||||
else:
|
||||
pyderasn_exists = True
|
||||
|
||||
|
||||
@skipIf(not pyderasn_exists, "PyDERASN dependency is required")
|
||||
class TestPFX(TestCase):
|
||||
"""PFX test vectors from "Транспортный ключевой контейнер" (R50.1.112-2016.pdf)
|
||||
"""
|
||||
pfx_raw = b64decode("""
|
||||
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
|
||||
mwcl1xQV2G5/fgICB9A=
|
||||
""")
|
||||
password = u"Пароль для PFX"
|
||||
|
||||
def test_shrouded_key_bag(self):
|
||||
private_key_info_expected = b64decode(b"""
|
||||
MGYCAQAwHwYIKoUDBwEBAQEwEwYHKoUDAgIjAQYIKoUDBwEBAgIEQEYbRu86z+1JFKDcPDN9UbTG
|
||||
G2ki9enTqos4KpUU0j9IDpl1UXiaA1YDIwUjlAp+81GkLmyt8Fw6Gt/X5JZySAY=
|
||||
""")
|
||||
|
||||
pfx, tail = PFX().decode(self.pfx_raw)
|
||||
self.assertSequenceEqual(tail, b"")
|
||||
_, outer_safe_contents = pfx["authSafe"]["content"].defined
|
||||
safe_contents, tail = OctetStringSafeContents().decode(
|
||||
bytes(outer_safe_contents[0]["bagValue"]),
|
||||
)
|
||||
self.assertSequenceEqual(tail, b"")
|
||||
safe_bag = safe_contents[0]
|
||||
shrouded_key_bag, tail = PKCS8ShroudedKeyBag().decode(
|
||||
bytes(safe_bag["bagValue"]),
|
||||
)
|
||||
self.assertSequenceEqual(tail, b"")
|
||||
_, pbes2_params = shrouded_key_bag["encryptionAlgorithm"]["parameters"].defined
|
||||
_, pbkdf2_params = pbes2_params["keyDerivationFunc"]["parameters"].defined
|
||||
_, enc_scheme_params = pbes2_params["encryptionScheme"]["parameters"].defined
|
||||
|
||||
key = gost34112012_pbkdf2(
|
||||
password=self.password.encode("utf-8"),
|
||||
salt=bytes(pbkdf2_params["salt"]["specified"]),
|
||||
iterations=int(pbkdf2_params["iterationCount"]),
|
||||
dklen=32,
|
||||
)
|
||||
# key = hexdec("309dd0354c5603739403f2335e9e2055138f8b5c98b63009de0635eea1fd7ba8")
|
||||
self.assertSequenceEqual(
|
||||
cfb_decrypt(
|
||||
key,
|
||||
bytes(shrouded_key_bag["encryptedData"]),
|
||||
iv=bytes(enc_scheme_params["iv"]),
|
||||
sbox="id-tc26-gost-28147-param-Z",
|
||||
),
|
||||
private_key_info_expected,
|
||||
)
|
||||
|
||||
def test_encrypted_data(self):
|
||||
cert_bag_expected = b64decode(b"""
|
||||
MIIDSjCCA0YGCyqGSIb3DQEMCgEDoIIDHjCCAxoGCiqGSIb3DQEJFgGgggMKBIIDBjCCAwIwggKt
|
||||
oAMCAQICEAHQaF8xH5bAAAAACycJAAEwDAYIKoUDBwEBAwIFADBgMQswCQYDVQQGEwJSVTEVMBMG
|
||||
A1UEBwwM0JzQvtGB0LrQstCwMQ8wDQYDVQQKDAbQotCaMjYxKTAnBgNVBAMMIENBIGNlcnRpZmlj
|
||||
YXRlIChQS0NTIzEyIGV4YW1wbGUpMB4XDTE1MDMyNzA3MjUwMFoXDTIwMDMyNzA3MjMwMFowZDEL
|
||||
MAkGA1UEBhMCUlUxFTATBgNVBAcMDNCc0L7RgdC60LLQsDEPMA0GA1UECgwG0KLQmjI2MS0wKwYD
|
||||
VQQDDCRUZXN0IGNlcnRpZmljYXRlIDEgKFBLQ1MjMTIgZXhhbXBsZSkwZjAfBggqhQMHAQEBATAT
|
||||
BgcqhQMCAiMBBggqhQMHAQECAgNDAARA1xzymkpvr2dYJT8WTOX3Dt96/+hGsXNytUQpkWB5ImJM
|
||||
4tg9AsC4RIUwV5H41MhG0uBRFweTzN6AsAdBvhTClYEJADI3MDkwMDAxo4IBKTCCASUwKwYDVR0Q
|
||||
BCQwIoAPMjAxNTAzMjcwNzI1MDBagQ8yMDE2MDMyNzA3MjUwMFowDgYDVR0PAQH/BAQDAgTwMB0G
|
||||
A1UdDgQWBBQhWOsRQ68yYN2Utg/owHoWcqsVbTAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUH
|
||||
AwQwDAYDVR0TAQH/BAIwADCBmQYDVR0jBIGRMIGOgBQmnc7Xh5ykb5t/BMwOkxA4drfEmqFkpGIw
|
||||
YDELMAkGA1UEBhMCUlUxFTATBgNVBAcMDNCc0L7RgdC60LLQsDEPMA0GA1UECgwG0KLQmjI2MSkw
|
||||
JwYDVQQDDCBDQSBjZXJ0aWZpY2F0ZSAoUEtDUyMxMiBleGFtcGxlKYIQAdBoXvL8TSAAAAALJwkA
|
||||
ATAMBggqhQMHAQEDAgUAA0EA9oq0Vvk8kkgIwkp0x0J5eKtia4MNTiwKAm7jgnCZIx3O98BThaTX
|
||||
3ZQhEo2RL9pTCPr6wFMheeJ+YdGMReXvsjEVMBMGCSqGSIb3DQEJFTEGBAQBAAAA
|
||||
""")
|
||||
|
||||
pfx, tail = PFX().decode(self.pfx_raw)
|
||||
self.assertSequenceEqual(tail, b"")
|
||||
_, outer_safe_contents = pfx["authSafe"]["content"].defined
|
||||
_, encrypted_data = outer_safe_contents[1]["bagValue"].defined
|
||||
_, pbes2_params = encrypted_data["encryptedContentInfo"]["contentEncryptionAlgorithm"]["parameters"].defined
|
||||
_, pbkdf2_params = pbes2_params["keyDerivationFunc"]["parameters"].defined
|
||||
_, enc_scheme_params = pbes2_params["encryptionScheme"]["parameters"].defined
|
||||
key = gost34112012_pbkdf2(
|
||||
password=self.password.encode("utf-8"),
|
||||
salt=bytes(pbkdf2_params["salt"]["specified"]),
|
||||
iterations=int(pbkdf2_params["iterationCount"]),
|
||||
dklen=32,
|
||||
)
|
||||
# key = hexdec("0e93d71339e7f53b79a0bc41f9109dd4fb60b30ae10736c1bb77b84c07681cfc")
|
||||
self.assertSequenceEqual(
|
||||
cfb_decrypt(
|
||||
key,
|
||||
bytes(encrypted_data["encryptedContentInfo"]["encryptedContent"]),
|
||||
iv=bytes(enc_scheme_params["iv"]),
|
||||
sbox="id-tc26-gost-28147-param-Z",
|
||||
),
|
||||
cert_bag_expected,
|
||||
)
|
||||
|
||||
def test_mac(self):
|
||||
pfx, tail = PFX().decode(self.pfx_raw)
|
||||
self.assertSequenceEqual(tail, b"")
|
||||
_, outer_safe_contents = pfx["authSafe"]["content"].defined
|
||||
mac_data = pfx["macData"]
|
||||
mac_key = gost34112012_pbkdf2(
|
||||
password=self.password.encode("utf-8"),
|
||||
salt=bytes(mac_data["macSalt"]),
|
||||
iterations=int(mac_data["iterations"]),
|
||||
dklen=96,
|
||||
)[-32:]
|
||||
# mac_key = hexdec("cadbfbf3bceaa9b79f651508fac5abbeb4a13d0bd0e1876bd3c3efb2112128a5")
|
||||
self.assertSequenceEqual(
|
||||
hmac_new(
|
||||
key=mac_key,
|
||||
msg=SafeContents(outer_safe_contents).encode(),
|
||||
digestmod=GOST34112012512,
|
||||
).digest(),
|
||||
bytes(mac_data["mac"]["digest"]),
|
||||
)
|
||||
|
||||
|
||||
@skipIf(not pyderasn_exists, "PyDERASN dependency is required")
|
||||
class TestPFX2020(TestCase):
|
||||
"""PFX test vectors from newer PKCS#12 update
|
||||
"""
|
||||
ca_prv_raw = hexdec("092F8D059E97E22B90B1AE99F0087FC4D26620B91550CBB437C191005A290810")
|
||||
ca_curve = gost3410.CURVES["id-tc26-gost-3410-12-256-paramSetA"]
|
||||
ca_cert = Certificate().decod(b64decode(b"""
|
||||
MIIB+TCCAaagAwIBAgIEAYy6gTAKBggqhQMHAQEDAjA4MQ0wCwYDVQQKEwRUSzI2MS
|
||||
cwJQYDVQQDEx5DQSBUSzI2OiBHT1NUIDM0LjEwLTEyIDI1Ni1iaXQwHhcNMDEwMTAx
|
||||
MDAwMDAwWhcNNDkxMjMxMDAwMDAwWjA4MQ0wCwYDVQQKEwRUSzI2MScwJQYDVQQDEx
|
||||
5DQSBUSzI2OiBHT1NUIDM0LjEwLTEyIDI1Ni1iaXQwXjAXBggqhQMHAQEBATALBgkq
|
||||
hQMHAQIBAQEDQwAEQBpKgpyPDnhQAJyLqy8Qs0XQhgxEhby6tSypqYimgbjpcKqtU6
|
||||
4jpDXc3h3BxGxtl2oHJ/4YLZ/ll87dto3ltMqjgZgwgZUwYwYDVR0jBFwwWoAUrGwO
|
||||
TERmokKW4p8JOyVm88ukUyqhPKQ6MDgxDTALBgNVBAoTBFRLMjYxJzAlBgNVBAMTHk
|
||||
NBIFRLMjY6IEdPU1QgMzQuMTAtMTIgMjU2LWJpdIIEAYy6gTAdBgNVHQ4EFgQUrGwO
|
||||
TERmokKW4p8JOyVm88ukUyowDwYDVR0TAQH/BAUwAwEB/zAKBggqhQMHAQEDAgNBAB
|
||||
Gg3nhgQ5oCKbqlEdVaRxH+1WX4wVkawGXuTYkr1AC2OWw3ZC14Vvg3nazm8UMWUZtk
|
||||
vu1kJcHQ4jFKkjUeg2E=
|
||||
"""))
|
||||
ca_pub = gost3410.pub_unmarshal(bytes(OctetString().decod(bytes(
|
||||
ca_cert["tbsCertificate"]["subjectPublicKeyInfo"]["subjectPublicKey"]
|
||||
))))
|
||||
password = u"Пароль для PFX".encode("utf-8")
|
||||
cert_test = Certificate().decod(b64decode(b"""
|
||||
MIICLjCCAdugAwIBAgIEAYy6hDAKBggqhQMHAQEDAjA4MQ0wCwYDVQQKEwRUSzI2MS
|
||||
cwJQYDVQQDEx5DQSBUSzI2OiBHT1NUIDM0LjEwLTEyIDI1Ni1iaXQwHhcNMDEwMTAx
|
||||
MDAwMDAwWhcNNDkxMjMxMDAwMDAwWjA7MQ0wCwYDVQQKEwRUSzI2MSowKAYDVQQDEy
|
||||
FPUklHSU5BVE9SOiBHT1NUIDM0LjEwLTEyIDUxMi1iaXQwgaAwFwYIKoUDBwEBAQIw
|
||||
CwYJKoUDBwECAQIBA4GEAASBgLSLt1q8KQ4YZVxioU+1LV9QhE7MHR9gBEh7S1yVNG
|
||||
lqt7+rNG5VFqmrPM74rbUsOlhV8M+zZKprXdk35Oz8lSW/n2oIUHZxikXIH/SSHj4r
|
||||
v3K/Puvz7hYTQSZl/xPdp78nUmjrEa6d5wfX8biEy2z0dgufFvAkMw1Ua4gdXqDOo4
|
||||
GHMIGEMGMGA1UdIwRcMFqAFKxsDkxEZqJCluKfCTslZvPLpFMqoTykOjA4MQ0wCwYD
|
||||
VQQKEwRUSzI2MScwJQYDVQQDEx5DQSBUSzI2OiBHT1NUIDM0LjEwLTEyIDI1Ni1iaX
|
||||
SCBAGMuoEwHQYDVR0OBBYEFH4GVwmYDK1rCKhX7nkAWDrJ16CkMAoGCCqFAwcBAQMC
|
||||
A0EACl6p8dAbpi9Hk+3mgMyI0WIh17IrlrSp/mB0F7ZzMt8XUD1Dwz3JrrnxeXnfMv
|
||||
OA5BdUJ9hCyDgMVAGs/IcEEA==
|
||||
"""))
|
||||
prv_test_raw = b64decode("""
|
||||
MIHiAgEBMBcGCCqFAwcBAQECMAsGCSqFAwcBAgECAQRAEWkl+eblsHWs86SNgRKq
|
||||
SxMOgGhbvR/uZ5/WWfdNG1axvUwVhpcXIxDZUmzQuNzqJBkseI7f5/JjXyTFRF1a
|
||||
+YGBgQG0i7davCkOGGVcYqFPtS1fUIROzB0fYARIe0tclTRpare/qzRuVRapqzzO
|
||||
+K21LDpYVfDPs2Sqa13ZN+Ts/JUlv59qCFB2cYpFyB/0kh4+K79yvz7r8+4WE0Em
|
||||
Zf8T3ae/J1Jo6xGunecH1/G4hMts9HYLnxbwJDMNVGuIHV6gzg==
|
||||
""")
|
||||
|
||||
def test_cert_and_encrypted_key(self):
|
||||
pfx_raw = b64decode(b"""
|
||||
MIIFKwIBAzCCBMQGCSqGSIb3DQEHAaCCBLUEggSxMIIErTCCAswGCSqGSIb3DQEH
|
||||
AaCCAr0EggK5MIICtTCCArEGCyqGSIb3DQEMCgEDoIICSjCCAkYGCiqGSIb3DQEJ
|
||||
FgGgggI2BIICMjCCAi4wggHboAMCAQICBAGMuoQwCgYIKoUDBwEBAwIwODENMAsG
|
||||
A1UEChMEVEsyNjEnMCUGA1UEAxMeQ0EgVEsyNjogR09TVCAzNC4xMC0xMiAyNTYt
|
||||
Yml0MB4XDTAxMDEwMTAwMDAwMFoXDTQ5MTIzMTAwMDAwMFowOzENMAsGA1UEChME
|
||||
VEsyNjEqMCgGA1UEAxMhT1JJR0lOQVRPUjogR09TVCAzNC4xMC0xMiA1MTItYml0
|
||||
MIGgMBcGCCqFAwcBAQECMAsGCSqFAwcBAgECAQOBhAAEgYC0i7davCkOGGVcYqFP
|
||||
tS1fUIROzB0fYARIe0tclTRpare/qzRuVRapqzzO+K21LDpYVfDPs2Sqa13ZN+Ts
|
||||
/JUlv59qCFB2cYpFyB/0kh4+K79yvz7r8+4WE0EmZf8T3ae/J1Jo6xGunecH1/G4
|
||||
hMts9HYLnxbwJDMNVGuIHV6gzqOBhzCBhDBjBgNVHSMEXDBagBSsbA5MRGaiQpbi
|
||||
nwk7JWbzy6RTKqE8pDowODENMAsGA1UEChMEVEsyNjEnMCUGA1UEAxMeQ0EgVEsy
|
||||
NjogR09TVCAzNC4xMC0xMiAyNTYtYml0ggQBjLqBMB0GA1UdDgQWBBR+BlcJmAyt
|
||||
awioV+55AFg6ydegpDAKBggqhQMHAQEDAgNBAApeqfHQG6YvR5Pt5oDMiNFiIdey
|
||||
K5a0qf5gdBe2czLfF1A9Q8M9ya658Xl53zLzgOQXVCfYQsg4DFQBrPyHBBAxVDAj
|
||||
BgkqhkiG9w0BCRUxFgQUeVV0+dS25MICJChpmGc/8AoUwE0wLQYJKoZIhvcNAQkU
|
||||
MSAeHgBwADEAMgBGAHIAaQBlAG4AZABsAHkATgBhAG0AZTCCAdkGCSqGSIb3DQEH
|
||||
AaCCAcoEggHGMIIBwjCCAb4GCyqGSIb3DQEMCgECoIIBVzCCAVMwWQYJKoZIhvcN
|
||||
AQUNMEwwKQYJKoZIhvcNAQUMMBwECKf4N7NMwugqAgIIADAMBggqhQMHAQEEAgUA
|
||||
MB8GCSqFAwcBAQUCAjASBBAlmt2WDfaPJlsAs0mLKglzBIH1DMvEacbbWRNDVSnX
|
||||
JLWygYrKoipdOjDA/2HEnBZ34uFOLNheUqiKpCPoFpbR2GBiVYVTVK9ibiczgaca
|
||||
EQYzDXtcS0QCZOxpKWfteAlbdJLC/SqPurPYyKi0MVRUPROhbisFASDT38HDH1Dh
|
||||
0dL5f6ga4aPWLrWbbgWERFOoOPyh4DotlPF37AQOwiEjsbyyRHq3HgbWiaxQRuAh
|
||||
eqHOn4QVGY92/HFvJ7u3TcnQdLWhTe/lh1RHLNF3RnXtN9if9zC23laDZOiWZplU
|
||||
yLrUiTCbHrtn1RppPDmLFNMt9dJ7KKgCkOi7Zm5nhqPChbywX13wcfYxVDAjBgkq
|
||||
hkiG9w0BCRUxFgQUeVV0+dS25MICJChpmGc/8AoUwE0wLQYJKoZIhvcNAQkUMSAe
|
||||
HgBwADEAMgBGAHIAaQBlAG4AZABsAHkATgBhAG0AZTBeME4wCgYIKoUDBwEBAgME
|
||||
QAkBKw4ihn7pSIYTEhu0bcvTPZjI3WgVxCkUVlOsc80G69EKFEOTnObGJGSKJ51U
|
||||
KkOsXF0a7+VBZf3BcVVQh9UECIVEtO+VpuskAgIIAA==
|
||||
""")
|
||||
pfx = PFX().decod(pfx_raw)
|
||||
_, outer_safe_contents = pfx["authSafe"]["content"].defined
|
||||
|
||||
safe_contents = OctetStringSafeContents().decod(bytes(
|
||||
outer_safe_contents[0]["bagValue"]
|
||||
))
|
||||
safe_bag = safe_contents[0]
|
||||
self.assertEqual(safe_bag["bagId"], id_pkcs12_bagtypes_certBag)
|
||||
cert_bag = CertBag().decod(bytes(safe_bag["bagValue"]))
|
||||
self.assertEqual(cert_bag["certId"], id_pkcs9_certTypes_x509Certificate)
|
||||
_, cert = cert_bag["certValue"].defined
|
||||
self.assertEqual(Certificate(cert), self.cert_test)
|
||||
|
||||
safe_contents = OctetStringSafeContents().decod(bytes(
|
||||
outer_safe_contents[1]["bagValue"]
|
||||
))
|
||||
safe_bag = safe_contents[0]
|
||||
self.assertEqual(safe_bag["bagId"], id_pkcs12_bagtypes_pkcs8ShroudedKeyBag)
|
||||
shrouded_key_bag = PKCS8ShroudedKeyBag().decod(bytes(safe_bag["bagValue"]))
|
||||
_, pbes2_params = shrouded_key_bag["encryptionAlgorithm"]["parameters"].defined
|
||||
_, pbkdf2_params = pbes2_params["keyDerivationFunc"]["parameters"].defined
|
||||
_, enc_scheme_params = pbes2_params["encryptionScheme"]["parameters"].defined
|
||||
ukm = bytes(enc_scheme_params["ukm"])
|
||||
key = gost34112012_pbkdf2(
|
||||
password=self.password,
|
||||
salt=bytes(pbkdf2_params["salt"]["specified"]),
|
||||
iterations=int(pbkdf2_params["iterationCount"]),
|
||||
dklen=32,
|
||||
)
|
||||
# key = hexdec("4b7ae649ca31dd5fe3243a91a5188c03f1d7049bec8e0d241c0e1e8c39ea4c1f")
|
||||
key_enc, key_mac = kdf_tree_gostr3411_2012_256(
|
||||
key, b"kdf tree", ukm[GOST3412Kuznechik.blocksize // 2:], 2,
|
||||
)
|
||||
ciphertext = bytes(shrouded_key_bag["encryptedData"])
|
||||
plaintext = ctr_acpkm(
|
||||
GOST3412Kuznechik,
|
||||
GOST3412Kuznechik(key_enc).encrypt,
|
||||
section_size=256 * 1024,
|
||||
bs=GOST3412Kuznechik.blocksize,
|
||||
data=ciphertext,
|
||||
iv=ukm[:GOST3412Kuznechik.blocksize // 2],
|
||||
)
|
||||
mac_expected = plaintext[-GOST3412Kuznechik.blocksize:]
|
||||
plaintext = plaintext[:-GOST3412Kuznechik.blocksize]
|
||||
mac = omac(
|
||||
GOST3412Kuznechik(key_mac).encrypt,
|
||||
GOST3412Kuznechik.blocksize,
|
||||
plaintext,
|
||||
)
|
||||
self.assertSequenceEqual(mac, mac_expected)
|
||||
self.assertSequenceEqual(plaintext, self.prv_test_raw)
|
||||
|
||||
mac_data = pfx["macData"]
|
||||
mac_key = gost34112012_pbkdf2(
|
||||
password=self.password,
|
||||
salt=bytes(mac_data["macSalt"]),
|
||||
iterations=int(mac_data["iterations"]),
|
||||
dklen=96,
|
||||
)[-32:]
|
||||
# mac_key = hexdec("a81d1bc91a4a5cf1fd7320f92dda7e5b285816c3b20826a382d7ed0cbf3a9bf4")
|
||||
self.assertSequenceEqual(
|
||||
hmac_new(
|
||||
key=mac_key,
|
||||
msg=SafeContents(outer_safe_contents).encode(),
|
||||
digestmod=GOST34112012512,
|
||||
).digest(),
|
||||
bytes(mac_data["mac"]["digest"]),
|
||||
)
|
||||
self.assertTrue(gost3410.verify(
|
||||
self.ca_curve,
|
||||
self.ca_pub,
|
||||
GOST34112012256(cert["tbsCertificate"].encode()).digest()[::-1],
|
||||
bytes(cert["signatureValue"]),
|
||||
))
|
||||
|
||||
def test_encrypted_cert_and_key(self):
|
||||
pfx_raw = b64decode(b"""
|
||||
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
|
||||
""")
|
||||
pfx = PFX().decod(pfx_raw)
|
||||
_, outer_safe_contents = pfx["authSafe"]["content"].defined
|
||||
|
||||
encrypted_data = EncryptedData().decod(bytes(
|
||||
outer_safe_contents[0]["bagValue"]
|
||||
))
|
||||
eci = encrypted_data["encryptedContentInfo"]
|
||||
self.assertEqual(eci["contentEncryptionAlgorithm"]["algorithm"], id_pbes2)
|
||||
pbes2_params = PBES2Params().decod(bytes(
|
||||
eci["contentEncryptionAlgorithm"]["parameters"]
|
||||
))
|
||||
_, pbkdf2_params = pbes2_params["keyDerivationFunc"]["parameters"].defined
|
||||
_, enc_scheme_params = pbes2_params["encryptionScheme"]["parameters"].defined
|
||||
ukm = bytes(enc_scheme_params["ukm"])
|
||||
key = gost34112012_pbkdf2(
|
||||
password=self.password,
|
||||
salt=bytes(pbkdf2_params["salt"]["specified"]),
|
||||
iterations=int(pbkdf2_params["iterationCount"]),
|
||||
dklen=32,
|
||||
)
|
||||
# key = hexdec("d066a96fb326ba896a2352d3f40240a4ded6e7e7bd5b4db6b5241d631c8c381c")
|
||||
key_enc, key_mac = kdf_tree_gostr3411_2012_256(
|
||||
key, b"kdf tree", ukm[GOST3412Magma.blocksize // 2:], 2,
|
||||
)
|
||||
ciphertext = bytes(eci["encryptedContent"])
|
||||
plaintext = ctr_acpkm(
|
||||
GOST3412Magma,
|
||||
GOST3412Magma(key_enc).encrypt,
|
||||
section_size=8 * 1024,
|
||||
bs=GOST3412Magma.blocksize,
|
||||
data=ciphertext,
|
||||
iv=ukm[:GOST3412Magma.blocksize // 2],
|
||||
)
|
||||
mac_expected = plaintext[-GOST3412Magma.blocksize:]
|
||||
plaintext = plaintext[:-GOST3412Magma.blocksize]
|
||||
mac = omac(
|
||||
GOST3412Magma(key_mac).encrypt,
|
||||
GOST3412Magma.blocksize,
|
||||
plaintext,
|
||||
)
|
||||
self.assertSequenceEqual(mac, mac_expected)
|
||||
|
||||
safe_contents = SafeContents().decod(plaintext)
|
||||
safe_bag = safe_contents[0]
|
||||
self.assertEqual(safe_bag["bagId"], id_pkcs12_bagtypes_certBag)
|
||||
cert_bag = CertBag().decod(bytes(safe_bag["bagValue"]))
|
||||
self.assertEqual(cert_bag["certId"], id_pkcs9_certTypes_x509Certificate)
|
||||
_, cert = cert_bag["certValue"].defined
|
||||
self.assertEqual(Certificate(cert), self.cert_test)
|
||||
|
||||
safe_contents = OctetStringSafeContents().decod(bytes(
|
||||
outer_safe_contents[1]["bagValue"]
|
||||
))
|
||||
safe_bag = safe_contents[0]
|
||||
self.assertEqual(safe_bag["bagId"], id_pkcs12_bagtypes_pkcs8ShroudedKeyBag)
|
||||
shrouded_key_bag = PKCS8ShroudedKeyBag().decod(bytes(safe_bag["bagValue"]))
|
||||
_, pbes2_params = shrouded_key_bag["encryptionAlgorithm"]["parameters"].defined
|
||||
_, pbkdf2_params = pbes2_params["keyDerivationFunc"]["parameters"].defined
|
||||
_, enc_scheme_params = pbes2_params["encryptionScheme"]["parameters"].defined
|
||||
ukm = bytes(enc_scheme_params["ukm"])
|
||||
key = gost34112012_pbkdf2(
|
||||
password=self.password,
|
||||
salt=bytes(pbkdf2_params["salt"]["specified"]),
|
||||
iterations=int(pbkdf2_params["iterationCount"]),
|
||||
dklen=32,
|
||||
)
|
||||
# key = hexdec("f840d001fd11441e0fb7ccf48f471915e5bf35275309dbe7ade9da4fe460ba7e")
|
||||
ciphertext = bytes(shrouded_key_bag["encryptedData"])
|
||||
plaintext = ctr_acpkm(
|
||||
GOST3412Magma,
|
||||
GOST3412Magma(key).encrypt,
|
||||
section_size=8 * 1024,
|
||||
bs=GOST3412Magma.blocksize,
|
||||
data=ciphertext,
|
||||
iv=ukm[:GOST3412Magma.blocksize // 2],
|
||||
)
|
||||
self.assertSequenceEqual(plaintext, self.prv_test_raw)
|
||||
|
||||
mac_data = pfx["macData"]
|
||||
mac_key = gost34112012_pbkdf2(
|
||||
password=self.password,
|
||||
salt=bytes(mac_data["macSalt"]),
|
||||
iterations=int(mac_data["iterations"]),
|
||||
dklen=96,
|
||||
)[-32:]
|
||||
# mac_key = hexdec("084f81782af1534ffd67e3c579c14cb45d7a6f659f46fdbb51a552e874e66fb2")
|
||||
self.assertSequenceEqual(
|
||||
hmac_new(
|
||||
key=mac_key,
|
||||
msg=SafeContents(outer_safe_contents).encode(),
|
||||
digestmod=GOST34112012512,
|
||||
).digest(),
|
||||
bytes(mac_data["mac"]["digest"]),
|
||||
)
|
||||
|
||||
def test_dh(self):
|
||||
curve = gost3410.CURVES["id-tc26-gost-3410-12-256-paramSetA"]
|
||||
# sender_prv_raw = hexdec("0B20810E449978C7C3B76C6FF77A16C532421139344A058EF56310B6B6F377E8")
|
||||
sender_cert = Certificate().decod(b64decode("""
|
||||
MIIB6zCCAZigAwIBAgIEAYy6gjAKBggqhQMHAQEDAjA4MQ0wCwYDVQQKEwRUSzI2
|
||||
MScwJQYDVQQDEx5DQSBUSzI2OiBHT1NUIDM0LjEwLTEyIDI1Ni1iaXQwHhcNMDEw
|
||||
MTAxMDAwMDAwWhcNNDkxMjMxMDAwMDAwWjA7MQ0wCwYDVQQKEwRUSzI2MSowKAYD
|
||||
VQQDEyFPUklHSU5BVE9SOiBHT1NUIDM0LjEwLTEyIDI1Ni1iaXQwXjAXBggqhQMH
|
||||
AQEBATALBgkqhQMHAQIBAQEDQwAEQJYpDRNiWWqDgaZje0EmLLOldQ35o5X1ZuZN
|
||||
SKequYQc/soI3OgDMWD7ThJJCk01IelCeb6MsBmG4lol+pnpVtOjgYcwgYQwYwYD
|
||||
VR0jBFwwWoAUrGwOTERmokKW4p8JOyVm88ukUyqhPKQ6MDgxDTALBgNVBAoTBFRL
|
||||
MjYxJzAlBgNVBAMTHkNBIFRLMjY6IEdPU1QgMzQuMTAtMTIgMjU2LWJpdIIEAYy6
|
||||
gTAdBgNVHQ4EFgQUPx5RgcjkifhlJm4/jQdkbm30rVQwCgYIKoUDBwEBAwIDQQA6
|
||||
8x7Vk6PvP/8xOGHhf8PuqaXAYskSyJPuBu+3Bo/PEj10devwc1J9uYWIDCGdKKPy
|
||||
bSlnQHqUPBBPM30YX1YN
|
||||
"""))
|
||||
recipient_prv_raw = hexdec("0DC8DC1FF2BC114BABC3F1CA8C51E4F58610427E197B1C2FBDBA4AE58CBFB7CE")[::-1]
|
||||
recipient_prv = gost3410.prv_unmarshal(recipient_prv_raw)
|
||||
recipient_cert = Certificate().decod(b64decode("""
|
||||
MIIB6jCCAZegAwIBAgIEAYy6gzAKBggqhQMHAQEDAjA4MQ0wCwYDVQQKEwRUSzI2
|
||||
MScwJQYDVQQDEx5DQSBUSzI2OiBHT1NUIDM0LjEwLTEyIDI1Ni1iaXQwHhcNMDEw
|
||||
MTAxMDAwMDAwWhcNNDkxMjMxMDAwMDAwWjA6MQ0wCwYDVQQKEwRUSzI2MSkwJwYD
|
||||
VQQDEyBSRUNJUElFTlQ6IEdPU1QgMzQuMTAtMTIgMjU2LWJpdDBeMBcGCCqFAwcB
|
||||
AQEBMAsGCSqFAwcBAgEBAQNDAARAvyeCGXMsYwpYe5aE0w8w3m4vpKQapGInqpnF
|
||||
lv7h08psFP0s1W80q3BR534F4TmR+o5+iU+AW6ycvWuc73JEQ6OBhzCBhDBjBgNV
|
||||
HSMEXDBagBSsbA5MRGaiQpbinwk7JWbzy6RTKqE8pDowODENMAsGA1UEChMEVEsy
|
||||
NjEnMCUGA1UEAxMeQ0EgVEsyNjogR09TVCAzNC4xMC0xMiAyNTYtYml0ggQBjLqB
|
||||
MB0GA1UdDgQWBBQ35gHPN1bx8l2eEMTbrtIg+5MU0TAKBggqhQMHAQEDAgNBABF2
|
||||
RHDaRqQuBS2yu7yGIGFgA6c/LG4GKjSOwYsRVmXJNNkQ4TB7PB8j3q7gx2koPsVB
|
||||
m90WfMWSL6SNSh3muuM=
|
||||
"""))
|
||||
self.assertTrue(gost3410.verify(
|
||||
self.ca_curve,
|
||||
self.ca_pub,
|
||||
GOST34112012256(sender_cert["tbsCertificate"].encode()).digest()[::-1],
|
||||
bytes(sender_cert["signatureValue"]),
|
||||
))
|
||||
self.assertTrue(gost3410.verify(
|
||||
self.ca_curve,
|
||||
self.ca_pub,
|
||||
GOST34112012256(recipient_cert["tbsCertificate"].encode()).digest()[::-1],
|
||||
bytes(recipient_cert["signatureValue"]),
|
||||
))
|
||||
|
||||
pfx_raw = b64decode("""
|
||||
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
|
||||
kxFG6QUFH8uuoX8=
|
||||
""")
|
||||
pfx = PFX().decod(pfx_raw)
|
||||
self.assertEqual(pfx["authSafe"]["contentType"], id_signedData)
|
||||
|
||||
sd = SignedData().decod(bytes(pfx["authSafe"]["content"]))
|
||||
self.assertEqual(sd["certificates"][0]["certificate"], sender_cert)
|
||||
si = sd["signerInfos"][0]
|
||||
self.assertEqual(
|
||||
si["digestAlgorithm"]["algorithm"],
|
||||
id_tc26_gost3411_2012_256,
|
||||
)
|
||||
digest = [
|
||||
bytes(attr["attrValues"][0].defined[1]) for attr in si["signedAttrs"]
|
||||
if attr["attrType"] == id_messageDigest
|
||||
][0]
|
||||
sender_pub = gost3410.pub_unmarshal(bytes(OctetString().decod(bytes(
|
||||
sender_cert["tbsCertificate"]["subjectPublicKeyInfo"]["subjectPublicKey"]
|
||||
))))
|
||||
content = bytes(sd["encapContentInfo"]["eContent"])
|
||||
self.assertSequenceEqual(digest, GOST34112012256(content).digest())
|
||||
self.assertTrue(gost3410.verify(
|
||||
curve,
|
||||
sender_pub,
|
||||
GOST34112012256(
|
||||
SignedAttributes(si["signedAttrs"]).encode()
|
||||
).digest()[::-1],
|
||||
bytes(si["signature"]),
|
||||
))
|
||||
|
||||
outer_safe_contents = SafeContents().decod(content)
|
||||
|
||||
safe_bag = outer_safe_contents[0]
|
||||
self.assertEqual(safe_bag["bagId"], id_data)
|
||||
safe_contents = OctetStringSafeContents().decod(bytes(safe_bag["bagValue"]))
|
||||
safe_bag = safe_contents[0]
|
||||
self.assertEqual(safe_bag["bagId"], id_pkcs12_bagtypes_certBag)
|
||||
cert_bag = CertBag().decod(bytes(safe_bag["bagValue"]))
|
||||
self.assertEqual(cert_bag["certId"], id_pkcs9_certTypes_x509Certificate)
|
||||
_, cert = cert_bag["certValue"].defined
|
||||
self.assertEqual(Certificate(cert), self.cert_test)
|
||||
|
||||
safe_bag = outer_safe_contents[1]
|
||||
self.assertEqual(safe_bag["bagId"], id_envelopedData)
|
||||
ed = EnvelopedData().decod(bytes(safe_bag["bagValue"]))
|
||||
kari = ed["recipientInfos"][0]["kari"]
|
||||
ukm = bytes(kari["ukm"])
|
||||
self.assertEqual(
|
||||
kari["keyEncryptionAlgorithm"]["algorithm"],
|
||||
id_gostr3412_2015_kuznyechik_wrap_kexp15,
|
||||
)
|
||||
self.assertEqual(
|
||||
kari["keyEncryptionAlgorithm"]["parameters"].defined[1]["algorithm"],
|
||||
id_tc26_agreement_gost3410_2012_256,
|
||||
)
|
||||
kexp = bytes(kari["recipientEncryptedKeys"][0]["encryptedKey"])
|
||||
keymat = keg(curve, recipient_prv, sender_pub, ukm)
|
||||
kim, kek = keymat[:KEYSIZE], keymat[KEYSIZE:]
|
||||
cek = kimp15(
|
||||
GOST3412Kuznechik(kek).encrypt,
|
||||
GOST3412Kuznechik(kim).encrypt,
|
||||
GOST3412Kuznechik.blocksize,
|
||||
kexp,
|
||||
ukm[24:24 + GOST3412Kuznechik.blocksize // 2],
|
||||
)
|
||||
eci = ed["encryptedContentInfo"]
|
||||
self.assertEqual(
|
||||
eci["contentEncryptionAlgorithm"]["algorithm"],
|
||||
id_gostr3412_2015_kuznyechik_ctracpkm,
|
||||
)
|
||||
eci_ukm = bytes(
|
||||
eci["contentEncryptionAlgorithm"]["parameters"].defined[1]["ukm"]
|
||||
)
|
||||
content = ctr_acpkm(
|
||||
GOST3412Kuznechik,
|
||||
GOST3412Kuznechik(cek).encrypt,
|
||||
256 * 1024,
|
||||
GOST3412Kuznechik.blocksize,
|
||||
bytes(eci["encryptedContent"]),
|
||||
eci_ukm[:GOST3412Kuznechik.blocksize // 2],
|
||||
)
|
||||
|
||||
safe_contents = SafeContents().decod(content)
|
||||
safe_bag = safe_contents[0]
|
||||
self.assertEqual(safe_bag["bagId"], id_pkcs12_bagtypes_keyBag)
|
||||
KeyBag().decod(bytes(safe_bag["bagValue"]))
|
||||
self.assertSequenceEqual(bytes(safe_bag["bagValue"]), self.prv_test_raw)
|
||||
Reference in New Issue
Block a user