diff --git a/irctest/client_tests/test_sasl.py b/irctest/client_tests/test_sasl.py index f150ed1..d0b25d3 100644 --- a/irctest/client_tests/test_sasl.py +++ b/irctest/client_tests/test_sasl.py @@ -1,4 +1,8 @@ import base64 +import hashlib + +import ecdsa +from ecdsa.util import sigencode_der, sigdecode_der try: import pyxmpp2_scram as scram @@ -9,6 +13,27 @@ from irctest import cases from irctest import authentication from irctest.irc_utils.message_parser import Message +ECDSA_KEY = """ +-----BEGIN EC PARAMETERS----- +BggqhkjOPQMBBw== +-----END EC PARAMETERS----- +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIIJueQ3W2IrGbe9wKdOI75yGS7PYZSj6W4tg854hlsvmoAoGCCqGSM49 +AwEHoUQDQgAEAZmaVhNSMmV5r8FXPvKuMnqDKyIA9pDHN5TNMfiF3mMeikGgK10W +IRX9cyi2wdYg9mUUYyh9GKdBCYHGUJAiCA== +-----END EC PRIVATE KEY----- +""" + +CHALLENGE = bytes(range(32)) +assert len(CHALLENGE) == 32 + +class IdentityHash: + def __init__(self, data): + self._data = data + + def digest(self): + return self._data + class SaslTestCase(cases.BaseClientTestCase, cases.ClientNegociationHelper, cases.OptionalityHelper): @cases.OptionalityHelper.skipUnlessHasMechanism('PLAIN') @@ -122,6 +147,36 @@ class SaslTestCase(cases.BaseClientTestCase, cases.ClientNegociationHelper, m = self.negotiateCapabilities(['sasl'], False) self.assertEqual(m, Message({}, None, 'CAP', ['END'])) + @cases.OptionalityHelper.skipUnlessHasMechanism('ECDSA-NIST256P-CHALLENGE') + def testEcdsa(self): + """Test ECDSA authentication. + """ + auth = authentication.Authentication( + mechanisms=[authentication.Mechanisms.ecdsa_nist256p_challenge], + username='jilles', + ecdsa_key=ECDSA_KEY, + ) + m = self.negotiateCapabilities(['sasl'], auth=auth) + self.assertEqual(m, Message({}, None, 'AUTHENTICATE', ['ECDSA-NIST256P-CHALLENGE'])) + self.sendLine('AUTHENTICATE +') + m = self.getMessage() + self.assertEqual(m, Message({}, None, 'AUTHENTICATE', + ['amlsbGVz'])) # jilles + self.sendLine('AUTHENTICATE {}'.format(base64.b64encode(CHALLENGE).decode('ascii'))) + m = self.getMessage() + self.assertMessageEqual(m, command='AUTHENTICATE') + sk = ecdsa.SigningKey.from_pem(ECDSA_KEY) + vk = sk.get_verifying_key() + signature = base64.b64decode(m.params[0]) + try: + vk.verify(signature, CHALLENGE, hashfunc=IdentityHash, sigdecode=sigdecode_der) + except ecdsa.BadSignatureError: + raise AssertionError('Bad signature') + self.sendLine('900 * * foo :You are now logged in.') + self.sendLine('903 * :SASL authentication successful') + m = self.negotiateCapabilities(['sasl'], False) + self.assertEqual(m, Message({}, None, 'CAP', ['END'])) + @cases.OptionalityHelper.skipUnlessHasMechanism('SCRAM-SHA-256') def testScram(self): """Test SCRAM-SHA-256 authentication.