diff --git a/django_x509/base/models.py b/django_x509/base/models.py index 84f45c5..7d6da30 100644 --- a/django_x509/base/models.py +++ b/django_x509/base/models.py @@ -32,6 +32,14 @@ ('sha256', 'SHA256'), ('sha384', 'SHA384'), ('sha512', 'SHA512'), + ('ecdsa-with-sha1', 'ECDSA with SHA1'), + ('ecdsa-with-sha256', 'ECDSA with SHA256'), + ('ecdsa-with-sha384', 'ECDSA with SHA384'), + ('ecdsa-with-sha512', 'ECDSA with SHA512'), + ('dsaWithSHA1', 'DSA with SHA1'), + ('dsaWithSHA256', 'DSA with SHA256'), + ('ed25519', 'Ed25519'), + ('ed448', 'Ed448'), ) SIGNATURE_MAPPING = { @@ -40,6 +48,15 @@ 'sha256WithRSAEncryption': 'sha256', 'sha384WithRSAEncryption': 'sha384', 'sha512WithRSAEncryption': 'sha512', + 'ecdsa-with-SHA384': 'sha384', + 'ecdsa-with-SHA1': 'sha1', + 'ecdsa-with-SHA256': 'sha256', + 'ecdsa-with-SHA384': 'sha384', + 'ecdsa-with-SHA512': 'sha512', + 'dsaWithSHA1': 'sha1', + 'dsaWithSHA256': 'sha256', + 'ed25519': 'ed25519', + 'ed448': 'ed448', } @@ -121,7 +138,7 @@ class BaseX509(models.Model): help_text=_('bits'), choices=DIGEST_CHOICES, default=default_digest_algorithm, - max_length=8, + max_length=20, ) validity_start = models.DateTimeField( blank=True, null=True, default=default_validity_start diff --git a/django_x509/migrations/0010_alter_ca_digest_alter_cert_digest.py b/django_x509/migrations/0010_alter_ca_digest_alter_cert_digest.py new file mode 100644 index 0000000..2f730a2 --- /dev/null +++ b/django_x509/migrations/0010_alter_ca_digest_alter_cert_digest.py @@ -0,0 +1,64 @@ +# Generated by Django 4.2.13 on 2024-05-21 18:07 + +from django.db import migrations, models +import django_x509.base.models + + +class Migration(migrations.Migration): + + dependencies = [ + ("django_x509", "0009_alter_ca_digest_alter_ca_key_length_and_more"), + ] + + operations = [ + migrations.AlterField( + model_name="ca", + name="digest", + field=models.CharField( + choices=[ + ("sha1", "SHA1"), + ("sha224", "SHA224"), + ("sha256", "SHA256"), + ("sha384", "SHA384"), + ("sha512", "SHA512"), + ("ecdsa-with-sha1", "ECDSA with SHA1"), + ("ecdsa-with-sha256", "ECDSA with SHA256"), + ("ecdsa-with-sha384", "ECDSA with SHA384"), + ("ecdsa-with-sha512", "ECDSA with SHA512"), + ("dsaWithSHA1", "DSA with SHA1"), + ("dsaWithSHA256", "DSA with SHA256"), + ("ed25519", "Ed25519"), + ("ed448", "Ed448"), + ], + default=django_x509.base.models.default_digest_algorithm, + help_text="bits", + max_length=20, + verbose_name="digest algorithm", + ), + ), + migrations.AlterField( + model_name="cert", + name="digest", + field=models.CharField( + choices=[ + ("sha1", "SHA1"), + ("sha224", "SHA224"), + ("sha256", "SHA256"), + ("sha384", "SHA384"), + ("sha512", "SHA512"), + ("ecdsa-with-sha1", "ECDSA with SHA1"), + ("ecdsa-with-sha256", "ECDSA with SHA256"), + ("ecdsa-with-sha384", "ECDSA with SHA384"), + ("ecdsa-with-sha512", "ECDSA with SHA512"), + ("dsaWithSHA1", "DSA with SHA1"), + ("dsaWithSHA256", "DSA with SHA256"), + ("ed25519", "Ed25519"), + ("ed448", "Ed448"), + ], + default=django_x509.base.models.default_digest_algorithm, + help_text="bits", + max_length=20, + verbose_name="digest algorithm", + ), + ), + ] diff --git a/django_x509/tests/test_ca.py b/django_x509/tests/test_ca.py index 92c8c5e..00d9c06 100644 --- a/django_x509/tests/test_ca.py +++ b/django_x509/tests/test_ca.py @@ -1,4 +1,5 @@ from datetime import datetime, timedelta +from unittest.mock import MagicMock, patch from django.core.exceptions import ValidationError from django.test import TestCase @@ -680,3 +681,32 @@ def test_ca_without_key_length_and_digest_algo(self): self.fail(f'Got exception: {e}') else: self.fail('ValidationError not raised as expected') + + def test_import_with_various_signature_algorithms(self): + algorithms = [ + 'ecdsa-with-SHA1', + 'ecdsa-with-SHA256', + 'ecdsa-with-SHA384', + 'ecdsa-with-SHA512', + 'dsaWithSHA1', + 'dsaWithSHA256', + 'ed25519', + 'ed448', + ] + + for algo in algorithms: + cert_mock = MagicMock() + cert_mock.get_signature_algorithm.return_value = algo.encode() + cert_mock.get_pubkey.return_value.bits.return_value = '384' + cert_mock.get_notBefore.return_value.decode.return_value = '20240101000000Z' + + with patch( + 'django_x509.base.models.crypto.load_certificate', + return_value=cert_mock, + ): + ca = self._create_ca() + + try: + ca.full_clean() + except ValidationError as e: + self.fail(f"Unexpected ValidationError for {algo}: {e}") diff --git a/tests/openwisp2/sample_x509/migrations/0003_alter_ca_digest_alter_cert_digest_and_more.py b/tests/openwisp2/sample_x509/migrations/0003_alter_ca_digest_alter_cert_digest_and_more.py new file mode 100644 index 0000000..aa9fef0 --- /dev/null +++ b/tests/openwisp2/sample_x509/migrations/0003_alter_ca_digest_alter_cert_digest_and_more.py @@ -0,0 +1,89 @@ +# Generated by Django 4.2.13 on 2024-05-21 18:24 + +from django.db import migrations, models +import django_x509.base.models + + +class Migration(migrations.Migration): + + dependencies = [ + ("sample_x509", "0002_common_name_max_length"), + ] + + operations = [ + migrations.AlterField( + model_name="ca", + name="digest", + field=models.CharField( + choices=[ + ("sha1", "SHA1"), + ("sha224", "SHA224"), + ("sha256", "SHA256"), + ("sha384", "SHA384"), + ("sha512", "SHA512"), + ("ecdsa-with-sha1", "ECDSA with SHA1"), + ("ecdsa-with-sha256", "ECDSA with SHA256"), + ("ecdsa-with-sha384", "ECDSA with SHA384"), + ("ecdsa-with-sha512", "ECDSA with SHA512"), + ("dsaWithSHA1", "DSA with SHA1"), + ("dsaWithSHA256", "DSA with SHA256"), + ("ed25519", "Ed25519"), + ("ed448", "Ed448"), + ], + default=django_x509.base.models.default_digest_algorithm, + help_text="bits", + max_length=20, + verbose_name="digest algorithm", + ), + ), + migrations.AlterField( + model_name="cert", + name="digest", + field=models.CharField( + choices=[ + ("sha1", "SHA1"), + ("sha224", "SHA224"), + ("sha256", "SHA256"), + ("sha384", "SHA384"), + ("sha512", "SHA512"), + ("ecdsa-with-sha1", "ECDSA with SHA1"), + ("ecdsa-with-sha256", "ECDSA with SHA256"), + ("ecdsa-with-sha384", "ECDSA with SHA384"), + ("ecdsa-with-sha512", "ECDSA with SHA512"), + ("dsaWithSHA1", "DSA with SHA1"), + ("dsaWithSHA256", "DSA with SHA256"), + ("ed25519", "Ed25519"), + ("ed448", "Ed448"), + ], + default=django_x509.base.models.default_digest_algorithm, + help_text="bits", + max_length=20, + verbose_name="digest algorithm", + ), + ), + migrations.AlterField( + model_name="customcert", + name="digest", + field=models.CharField( + choices=[ + ("sha1", "SHA1"), + ("sha224", "SHA224"), + ("sha256", "SHA256"), + ("sha384", "SHA384"), + ("sha512", "SHA512"), + ("ecdsa-with-sha1", "ECDSA with SHA1"), + ("ecdsa-with-sha256", "ECDSA with SHA256"), + ("ecdsa-with-sha384", "ECDSA with SHA384"), + ("ecdsa-with-sha512", "ECDSA with SHA512"), + ("dsaWithSHA1", "DSA with SHA1"), + ("dsaWithSHA256", "DSA with SHA256"), + ("ed25519", "Ed25519"), + ("ed448", "Ed448"), + ], + default=django_x509.base.models.default_digest_algorithm, + help_text="bits", + max_length=20, + verbose_name="digest algorithm", + ), + ), + ]