def decode(buffer: bytes, **kwargs) -> object: """ Decodes a JWK JSON string into EdDSA parameters. Parameters: buffer (bytes/str): JWK JSON string. Returns: EdDSA: EdDSA object. """ from samson.public_key.eddsa import EdDSA from samson.protocols.dh25519 import DH25519 if issubclass(type(buffer), (bytes, bytearray)): buffer = buffer.decode() jwk = json.loads(buffer) curve = JWK_INVERSE_CURVE_LOOKUP[jwk['crv']] x = Bytes(url_b64_decode(jwk['x'].encode('utf-8')), 'little') if 'd' in jwk: d = Bytes(url_b64_decode(jwk['d'].encode('utf-8'))).int() else: d = 0 if jwk['crv'] in ['Ed25519', 'Ed448']: eddsa = EdDSA(curve=curve, d=d) eddsa.A = eddsa.decode_point(x) else: eddsa = DH25519(curve=curve, d=d, pub=x.int()) return eddsa
def test_import_ssh(self): priv = EdDSA.import_key(TEST_SSH_PRIV) pubv1 = EdDSA.import_key(TEST_SSH_PUB) pubv2 = EdDSA.import_key(TEST_SSH2_PUB) self.assertEqual(priv.A, pubv1.A) self.assertEqual(priv.A, pubv2.A) self.assertEqual(pubv1.export_public_key(encoding=PKIEncoding.OpenSSH).replace(b'\n', b''), TEST_SSH_PUB.replace(b'\n', b'')) self.assertEqual(pubv2.export_public_key(encoding=PKIEncoding.SSH2).replace(b'\n', b''), TEST_SSH2_PUB_NO_CMT.replace(b'\n', b''))
def _run_test(self, message, d, curve, hash_alg, expected_public_key=None, expected_sig=None): eddsa = EdDSA(d=d, curve=curve, hash_obj=hash_alg) sig = eddsa.sign(message) if expected_public_key: self.assertEqual(eddsa.encode_point(eddsa.A).int(), expected_public_key) if expected_sig: self.assertEqual(sig, expected_sig) self.assertTrue(eddsa.verify(message, sig))
def test_import_openssh(self): for key, passphrase in [TEST_OPENSSH0, TEST_OPENSSH1, TEST_OPENSSH2, TEST_OPENSSH3]: if passphrase: with self.assertRaises(ValueError): EdDSA.import_key(key) eddsa = EdDSA.import_key(key, passphrase=passphrase) # EdDSA's little-endian causes a pretty big headache other_eddsa = EdDSA(h=eddsa.h[:32][::-1], clamp=False) self.assertEqual(eddsa.a, other_eddsa.a)
def decode(buffer: bytes, **kwargs): from samson.public_key.eddsa import EdDSA items = bytes_to_der_sequence(buffer) pub_point = Bytes(int(items[1])) curve_oid = str(items[0][0]) curve = EDCURVE_OID_LOOKUP[curve_oid] eddsa = EdDSA(curve=curve) eddsa.A = eddsa.decode_point(pub_point) return eddsa
def test_import_pkcs8(self): priv = EdDSA.import_key(TEST_PKCS8) priv_out = priv.export_private_key(encoding=PKIEncoding.PKCS8) self.assertEqual((priv.d, priv.curve), (Bytes(0xD4EE72DBF913584AD5B6D8F1F769F8AD3AFE7C28CBF1D4FBE097A88F44755842), EdwardsCurve25519)) self.assertEqual(priv_out.replace(b'\n', b''), TEST_PKCS8.replace(b'\n', b''))
def decode(buffer: bytes, **kwargs): from samson.public_key.eddsa import EdDSA from samson.math.algebra.curves.named import EdwardsCurve25519 _, pub = parse_openssh_key(buffer, SSH_PUBLIC_HEADER, EdDSAPublicKey, EdDSAPrivateKey, None) a, h = pub.a, 0 eddsa = EdDSA(curve=EdwardsCurve25519, h=h, a=a, d=0, clamp=False) return eddsa
def decode(buffer: bytes, **kwargs): from samson.public_key.eddsa import EdDSA from samson.math.algebra.curves.named import EdwardsCurve25519 priv, _ = parse_openssh_key(buffer, SSH_PUBLIC_HEADER, EdDSAPublicKey, EdDSAPrivateKey, kwargs.get('passphrase')) a, h = priv.a, priv.h eddsa = EdDSA(curve=EdwardsCurve25519, h=h, a=a, d=0, clamp=False) return eddsa
def decode(buffer: bytes, **kwargs): from samson.public_key.eddsa import EdDSA items = bytes_to_der_sequence(buffer) curve_oid = str(items[1][0]) priv_key, _ = decoder.decode(bytes(items[2])) d = Bytes(priv_key).int() curve = EDCURVE_OID_LOOKUP[curve_oid] eddsa = EdDSA(d=d, curve=curve) return eddsa
def test_gauntlet(self): for jwa in [JWASignatureAlg.HS256, JWASignatureAlg.HS384, JWASignatureAlg.HS512]: for _ in range(50): key = Bytes.random(16) jws = JWS.create(jwa, BODY, key) self.assertTrue(jws.verify(key)) for jwa, curve, hash_obj in [(JWASignatureAlg.ES256, P256, SHA256()), (JWASignatureAlg.ES384, P384, SHA384()), (JWASignatureAlg.ES512, P521, SHA512())]: for _ in range(10): key = ECDSA(G=curve.G, hash_obj=hash_obj) jws = JWS.create(jwa, BODY, key) self.assertTrue(jws.verify(key)) for jwa in [JWASignatureAlg.RS256, JWASignatureAlg.RS384, JWASignatureAlg.RS512, JWASignatureAlg.PS256, JWASignatureAlg.PS384, JWASignatureAlg.PS512]: for _ in range(10): key = RSA(2048) jws = JWS.create(jwa, BODY, key) correct = jws.verify(key) if not correct: print(key) print(jws) self.assertTrue(correct) for i in range(10): if i % 2: curve = EdwardsCurve25519 else: curve = EdwardsCurve448 key = EdDSA(curve=curve) jws = JWS.create(JWASignatureAlg.EdDSA, BODY, key) correct = jws.verify(key) if not correct: print(key) print(jws) self.assertTrue(correct)
def test_openssh_gauntlet(self): num_runs = 1 num_enc = num_runs // 3 for i in range(num_runs): eddsa = EdDSA() passphrase = None if i < num_enc: passphrase = Bytes.random(Bytes.random(1).int()) priv = eddsa.export_private_key(encoding=PKIEncoding.OpenSSH, encryption=b'aes256-ctr', passphrase=passphrase) pub_openssh = eddsa.export_public_key(encoding=PKIEncoding.OpenSSH) pub_ssh2 = eddsa.export_public_key(encoding=PKIEncoding.SSH2) new_priv = EdDSA.import_key(priv, passphrase=passphrase) new_pub_openssh = EdDSA.import_key(pub_openssh) new_pub_ssh2 = EdDSA.import_key(pub_ssh2) self.assertEqual((new_priv.h, new_priv.a, new_priv.A), (eddsa.h, eddsa.a, eddsa.A)) self.assertEqual((new_pub_openssh.a, new_pub_openssh.A), (eddsa.a, eddsa.A)) self.assertEqual((new_pub_ssh2.a, new_pub_ssh2.A), (eddsa.a, eddsa.A))
def test_eddsa(self): key = json.dumps({"kty":"OKP","crv":"Ed25519","d":"nWGxne_9WmC6hEr0kuwsxERJxWl7MmkZcDusAxyuf2A","x":"11qYAYKxCrfVS_7TyWQHOg7hcvPapiMlrwIaaPcHURo"}).encode('utf-8') token = b'eyJhbGciOiJFZERTQSJ9.RXhhbXBsZSBvZiBFZDI1NTE5IHNpZ25pbmc.hgyY0il_MGCjP0JzlnLWG1PPOt7-09PGcvMg3AIbQR6dWbhijcNR4ki4iylGjg5BhVsPt9g7sVvpAr_MuM0KAg' jws = JWS.parse(token) self.assertTrue(jws.verify(EdDSA.import_key(key)))
def test_import_jwk(self): eddsa = EdDSA.import_key(TEST_JWK) self.assertEqual((eddsa.A.x, eddsa.A.y), (38815646466658113194383306759739515082307681141926459231621296960732224964046, 11903303657706407974989296177215005343713679411332034699907763981919547054807)) self.assertEqual(eddsa.d, b'\x9da\xb1\x9d\xef\xfdZ`\xba\x84J\xf4\x92\xec,\xc4DI\xc5i{2i\x19p;\xac\x03\x1c\xae\x7f`') self.assertEqual(eddsa.export_private_key(encoding=PKIEncoding.JWK).replace(b'\n', b'').replace(b' ', b''), TEST_JWK)
def test_import_x509(self): eddsa = EdDSA.import_key(TEST_X509) self.assertEqual((eddsa.A.x, eddsa.A.y), (14952151952356719083710889065620775312428310390022181962301901207657981878023, 44054905936511465773410409843262024357620586324426155423091388570442095968025)) self.assertEqual(eddsa.export_public_key(encoding=PKIEncoding.X509).replace(b'\n', b''), TEST_X509.replace(b'\n', b''))