Modify rule S4426: Add how to fix it for cryptodome and pyOpenSSL and close gap with NIST (#3678)

This commit is contained in:
gaetan-ferry-sonarsource 2024-02-29 09:55:54 +01:00 committed by GitHub
parent 6aed7888c4
commit 0006c98874
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 175 additions and 28 deletions

View File

@ -73,34 +73,35 @@
* WordPress
* Mcrypt
// Python
* aiohttp
* Amazon DynamoDB
* Amazon DynamoDB
* Cryptodome
* Django
* Django Templates
* Flask
* aiohttp
* FastAPI
* FastAPI
* Flask
* HTTPX
* Jinja
* lxml
* Paramiko
* python-ldap
* Python SQLite
* MySQL Connector/Python
* Python Standard Library
* PyYAML
* Requests
* HTTPX
* SQLAlchemy
* Amazon DynamoDB
* python-ldap
* Request
* Cryptodome
* Paramiko
* pyca
* PyCrypto
* pyDes
* PyJWT
* python-jwt
* FastAPI
* pyOpenSSL
* python-jose
* python-jwt
* python-ldap
* python-ldap
* Python SQLite
* Python Standard Library
* PyYAML
* Request
* Requests
* SQLAlchemy
* ssl
// Docker
* Wget

View File

@ -1,3 +1,2 @@
Here is an example of an Elliptic Curve (EC) initialization. It implicitly
generates a private key whose size is indicated in the algorithm name:
generates a private key whose size is indicated in the elliptic curve name:

View File

@ -1,5 +1,5 @@
As a rule of thumb, use the cryptographic algorithms and mechanisms that are
considered strong by the cryptographic community.
considered strong by the cryptography community.
The appropriate choices are the following.
@ -8,7 +8,9 @@ The appropriate choices are the following.
The security of these algorithms depends on the difficulty of attacks
attempting to solve their underlying mathematical problem.
In general, a minimum key size of *2048* bits is recommended for both.
In general, a minimum key size of *2048* bits is recommended for both. It
provides 112 bits of security. A key length of *3072* or *4092* should be
preferred when possible.
==== AES (Advanced Encryption Standard)
@ -24,8 +26,19 @@ Currently, a minimum key size of *128 bits* is recommended for AES.
==== Elliptic Curve Cryptography (ECC)
Elliptic curve cryptography is also used in various algorithms, such as ECDSA,
ECDH, or ECMQV. The length of keys generated with elliptic curve algorithms are mentioned
ECDH, or ECMQV. The length of keys generated with elliptic curve algorithms is mentioned
directly in their names. For example, `secp256k1` generates a 256-bits long
private key.
Currently, a minimum key size of *224 bits* is recommended for EC algorithms.
Currently, a minimum key size of *224 bits* is recommended for EC-based
algorithms.
Additionally, some curves that theoretically provide sufficiently long keys are
still discouraged. This can be because of a flaw in the curve parameters, a bad
overall design, or poor performance. It is generally advised to use a
NIST-approved elliptic curve wherever possible. Such curves currently include:
* NIST P curves with a size of at least 224 bits, e.g. secp256r1.
* Curve25519, generally known as ed25519 or x25519 depending on its application.
* Curve448.
* Brainpool curves with a size of at least 224 bits, e.g. brainpoolP224r1

View File

@ -0,0 +1,4 @@
** Documentation
* NIST Documentation - https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-186.pdf[NIST SP 800-186: Recommendations for Discrete Logarithm-based Cryptography: Elliptic Curve Domain Parameters]
* IETF - https://datatracker.ietf.org/doc/html/rfc5639[rfc5639: Elliptic Curve Cryptography (ECC) Brainpool Standard Curves and Curve Generation]

View File

@ -0,0 +1,61 @@
== How to fix it in pyOpenSSL
=== Code examples
include::../../common/fix/code-rationale.adoc[]
==== Noncompliant code example
include::../../common/fix/rsa.adoc[]
[source,python,diff-id=4,diff-type=noncompliant]
----
from OpenSSL.crypto import PKey, TYPE_RSA
key_rsa1024 = PKey()
key_rsa1024.generate_key(type=TYPE_RSA, bits=1024) # Noncompliant
----
include::../../common/fix/dsa.adoc[]
[source,python,diff-id=5,diff-type=noncompliant]
----
from OpenSSL.crypto import PKey, TYPE_DSA
key_dsa1024 = PKey()
key_dsa1024.generate_key(type=TYPE_DSA, bits=1024) # Noncompliant
----
==== Compliant solution
[source,python,diff-id=4,diff-type=compliant]
----
from OpenSSL.crypto import PKey, TYPE_RSA
key_rsa1024 = PKey()
key_rsa1024.generate_key(type=TYPE_RSA, bits=3072)
----
[source,python,diff-id=5,diff-type=compliant]
----
from OpenSSL.crypto import PKey, TYPE_DSA
key_dsa1024 = PKey()
key_dsa1024.generate_key(type=TYPE_DSA, bits=3072)
----
=== How does this work?
As a rule of thumb, use the cryptographic algorithms and mechanisms that are
considered strong by the cryptography community.
The security of the RSA and DSA algorithms depends on the difficulty of attacks
attempting to solve their underlying mathematical problem.
In general, a minimum key size of *2048* bits is recommended for both. It
provides 112 bits of security. A key length of *3072* or *4096* should be
preferred when possible.
=== Going the extra mile
include::../../common/extra-mile/pre-quantum.adoc[]

View File

@ -34,14 +34,14 @@ public_key = private_key.public_key()
include::../../common/fix/ec.adoc[]
[source,python,diff-id=4,diff-type=noncompliant]
[source,python,diff-id=3,diff-type=noncompliant]
----
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.backends import default_backend
backend = default_backend()
private_key = ec.generate_private_key(curve=ec.SECT163R2, backend=backend) # Noncompliant
private_key = ec.generate_private_key(curve=ec.SECT163R2(), backend=backend) # Noncompliant
public_key = private_key.public_key()
----
@ -54,7 +54,7 @@ from cryptography.hazmat.backends import default_backend
backend = default_backend()
private_key = rsa.generate_private_key(key_size = 2048, backend = backend)
private_key = rsa.generate_private_key(key_size = 3072, backend = backend)
public_key = private_key.public_key()
----
@ -65,18 +65,18 @@ from cryptography.hazmat.backends import default_backend
backend = default_backend()
private_key = dsa.generate_private_key(key_size = 2048, backend = backend)
private_key = dsa.generate_private_key(key_size = 3072, backend = backend)
public_key = private_key.public_key()
----
[source,python,diff-id=4,diff-type=compliant]
[source,python,diff-id=3,diff-type=compliant]
----
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.backends import default_backend
backend = default_backend()
private_key = ec.generate_private_key(curve=ec.SECT409R1, backend=backend)
private_key = ec.generate_private_key(curve=ec.SECP521R1(), backend=backend)
public_key = private_key.public_key()
----

View File

@ -0,0 +1,65 @@
== How to fix it in Cryptodome
=== Code examples
include::../../common/fix/code-rationale.adoc[]
==== Noncompliant code example
include::../../common/fix/rsa.adoc[]
[source,python,diff-id=6,diff-type=noncompliant]
----
from Crypto.PublicKey import RSA
key_rsa1024 = RSA.generate(1024) # Noncompliant
----
include::../../common/fix/dsa.adoc[]
[source,python,diff-id=7,diff-type=noncompliant]
----
from Crypto.PublicKey import DSA
key_dsa1024 = DSA.generate(1024) # Noncompliant
----
include::../../common/fix/ec.adoc[]
[source,python,diff-id=8,diff-type=noncompliant]
----
from Crypto.PublicKey import DSA
key_p192 = ECC.generate(curve="secp192r1") # Noncompliant
----
==== Compliant solution
[source,python,diff-id=6,diff-type=compliant]
----
from Crypto.PublicKey import RSA
key_rsa1024 = RSA.generate(3072)
----
[source,python,diff-id=7,diff-type=compliant]
----
from Crypto.PublicKey import DSA
key_dsa1024 = DSA.generate(3072)
----
[source,python,diff-id=8,diff-type=compliant]
----
from Crypto.PublicKey import DSA
key_ed25519 = ECC.generate(curve="ed25519")
----
=== How does this work?
include::../../common/fix/fix.adoc[]
=== Going the extra mile
include::../../common/extra-mile/pre-quantum.adoc[]

View File

@ -10,6 +10,10 @@ include::../impact.adoc[]
include::how-to-fix-it/pyca.adoc[]
include::how-to-fix-it/pycryptodome.adoc[][]
include::how-to-fix-it/pyOpenSSL.adoc[][]
== Resources
include::../common/resources/docs.adoc[]