Repository: openwisp/django-x509 (language: python)

Issue:
[pki] CA can't be created when `Key length` set to `None` or `Digest algorithm` set to `None`
### Steps to reproduce :-
**First Error**
1. Start creating a new CA.
2. Set the name.
3. Set the `Key length` choice to `None`.
4. Hit the save button.

Error[Screenshot]:-
![image](https://user-images.githubusercontent.com/45564404/116928944-57dd2e00-ac7b-11eb-8faf-29452079a560.png)

**Second Error**
3. Set the `Digest algorithm` to `None`
4. Hit the save button.

Error[Screenshot]:-
![image](https://user-images.githubusercontent.com/45564404/116929389-fb2e4300-ac7b-11eb-9c6a-894b43f754f2.png)

[pki] CA can't be created when `Key length` set to `None` or `Digest algorithm` set to `None`
### Steps to reproduce :-
**First Error**
1. Start creating a new CA.
2. Set the name.
3. Set the `Key length` choice to `None`.
4. Hit the save button.

Error[Screenshot]:-
![image](https://user-images.githubusercontent.com/45564404/116928944-57dd2e00-ac7b-11eb-8faf-29452079a560.png)

**Second Error**
3. Set the `Digest algorithm` to `None`
4. Hit the save button.

Error[Screenshot]:-
![image](https://user-images.githubusercontent.com/45564404/116929389-fb2e4300-ac7b-11eb-9c6a-894b43f754f2.png)



Discussion / hints:
I was able to replicate this in django-x509. I believe we can move this issue to that repository 
@pandafy @ManishShah120 @atb00ker issue moved to django-x509.
I was able to replicate this in django-x509. I believe we can move this issue to that repository 
@pandafy @ManishShah120 @atb00ker issue moved to django-x509.

Fix patch:
diff --git a/django_x509/base/models.py b/django_x509/base/models.py
index 780ac63..b9dc05f 100644
--- a/django_x509/base/models.py
+++ b/django_x509/base/models.py
@@ -20,7 +20,6 @@
 utc_time = '%y%m%d%H%M%SZ'
 
 KEY_LENGTH_CHOICES = (
-    ('', ''),
     ('512', '512'),
     ('1024', '1024'),
     ('2048', '2048'),
@@ -28,7 +27,6 @@
 )
 
 DIGEST_CHOICES = (
-    ('', ''),
     ('sha1', 'SHA1'),
     ('sha224', 'SHA224'),
     ('sha256', 'SHA256'),
@@ -114,7 +112,6 @@ class BaseX509(models.Model):
     key_length = models.CharField(
         _('key length'),
         help_text=_('bits'),
-        blank=True,
         choices=KEY_LENGTH_CHOICES,
         default=default_key_length,
         max_length=6,
@@ -122,7 +119,6 @@ class BaseX509(models.Model):
     digest = models.CharField(
         _('digest algorithm'),
         help_text=_('bits'),
-        blank=True,
         choices=DIGEST_CHOICES,
         default=default_digest_algorithm,
         max_length=8,
diff --git a/django_x509/migrations/0009_alter_ca_digest_alter_ca_key_length_and_more.py b/django_x509/migrations/0009_alter_ca_digest_alter_ca_key_length_and_more.py
new file mode 100644
index 0000000..9e48788
--- /dev/null
+++ b/django_x509/migrations/0009_alter_ca_digest_alter_ca_key_length_and_more.py
@@ -0,0 +1,80 @@
+# Generated by Django 4.0.2 on 2022-02-16 14:01
+
+from django.db import migrations, models
+import django_x509.base.models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('django_x509', '0008_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'),
+                ],
+                default=django_x509.base.models.default_digest_algorithm,
+                help_text='bits',
+                max_length=8,
+                verbose_name='digest algorithm',
+            ),
+        ),
+        migrations.AlterField(
+            model_name='ca',
+            name='key_length',
+            field=models.CharField(
+                choices=[
+                    ('512', '512'),
+                    ('1024', '1024'),
+                    ('2048', '2048'),
+                    ('4096', '4096'),
+                ],
+                default=django_x509.base.models.default_key_length,
+                help_text='bits',
+                max_length=6,
+                verbose_name='key length',
+            ),
+        ),
+        migrations.AlterField(
+            model_name='cert',
+            name='digest',
+            field=models.CharField(
+                choices=[
+                    ('sha1', 'SHA1'),
+                    ('sha224', 'SHA224'),
+                    ('sha256', 'SHA256'),
+                    ('sha384', 'SHA384'),
+                    ('sha512', 'SHA512'),
+                ],
+                default=django_x509.base.models.default_digest_algorithm,
+                help_text='bits',
+                max_length=8,
+                verbose_name='digest algorithm',
+            ),
+        ),
+        migrations.AlterField(
+            model_name='cert',
+            name='key_length',
+            field=models.CharField(
+                choices=[
+                    ('512', '512'),
+                    ('1024', '1024'),
+                    ('2048', '2048'),
+                    ('4096', '4096'),
+                ],
+                default=django_x509.base.models.default_key_length,
+                help_text='bits',
+                max_length=6,
+                verbose_name='key length',
+            ),
+        ),
+    ]


Test patch:
diff --git a/django_x509/tests/test_ca.py b/django_x509/tests/test_ca.py
index 74f76ce..b6ca756 100644
--- a/django_x509/tests/test_ca.py
+++ b/django_x509/tests/test_ca.py
@@ -681,3 +681,14 @@ def test_ca_common_name_length(self):
         message_dict = context_manager.exception.message_dict
         self.assertIn('common_name', message_dict)
         self.assertEqual(message_dict['common_name'][0], msg)
+
+    def test_ca_without_key_length_and_digest_algo(self):
+        try:
+            self._create_ca(key_length='', digest='')
+        except ValidationError as e:
+            self.assertIn('key_length', e.error_dict)
+            self.assertIn('digest', e.error_dict)
+        except Exception as e:
+            self.fail(f'Got exception: {e}')
+        else:
+            self.fail('ValidationError not raised as expected')
diff --git a/tests/openwisp2/sample_x509/migrations/0001_initial.py b/tests/openwisp2/sample_x509/migrations/0001_initial.py
index c06ad77..cfa051e 100644
--- a/tests/openwisp2/sample_x509/migrations/0001_initial.py
+++ b/tests/openwisp2/sample_x509/migrations/0001_initial.py
@@ -33,9 +33,7 @@ class Migration(migrations.Migration):
                 (
                     'key_length',
                     models.CharField(
-                        blank=True,
                         choices=[
-                            ('', ''),
                             ('512', '512'),
                             ('1024', '1024'),
                             ('2048', '2048'),
@@ -50,9 +48,7 @@ class Migration(migrations.Migration):
                 (
                     'digest',
                     models.CharField(
-                        blank=True,
                         choices=[
-                            ('', ''),
                             ('sha1', 'SHA1'),
                             ('sha224', 'SHA224'),
                             ('sha256', 'SHA256'),
@@ -191,9 +187,7 @@ class Migration(migrations.Migration):
                 (
                     'key_length',
                     models.CharField(
-                        blank=True,
                         choices=[
-                            ('', ''),
                             ('512', '512'),
                             ('1024', '1024'),
                             ('2048', '2048'),
@@ -208,9 +202,7 @@ class Migration(migrations.Migration):
                 (
                     'digest',
                     models.CharField(
-                        blank=True,
                         choices=[
-                            ('', ''),
                             ('sha1', 'SHA1'),
                             ('sha224', 'SHA224'),
                             ('sha256', 'SHA256'),
@@ -380,9 +372,7 @@ class Migration(migrations.Migration):
                 (
                     'key_length',
                     models.CharField(
-                        blank=True,
                         choices=[
-                            ('', ''),
                             ('512', '512'),
                             ('1024', '1024'),
                             ('2048', '2048'),
@@ -397,9 +387,7 @@ class Migration(migrations.Migration):
                 (
                     'digest',
                     models.CharField(
-                        blank=True,
                         choices=[
-                            ('', ''),
                             ('sha1', 'SHA1'),
                             ('sha224', 'SHA224'),
                             ('sha256', 'SHA256'),