Skip to content

serialization.load_der_private_key should load RFC5958 asymmetric private keys (regression in 45.0.0) #15631

Description

@saper

After #12296 (part of 45.0.0) release some well-formed private keys do not load.

Versions up to 45.0.0 could load both keys in the test case below without any issue.

Rust import code hardcodes the version field to 0, which is specified in RFC5912 and therefore does not accept the value of 1, which is also allowed by the updated definition of RFC5958.

For simplicity, I have encoded the same key with version 1 (value of 0) and version 2 (value of 1) - there is one byte difference only,
one key loads with 45.0.0+, the other does not.

The problem may pertain to all asymmetric keys, the examples below use Ed25519.

from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
import codecs
import unittest

class TestEd25519KeyFormats(unittest.TestCase):

    def test_load_version1_key(self):
        """
        Load RFC 5912 PrivateKeyInfo, algorithm 1.3.101.112

        PrivateKeyInfo SEQUENCE (3 elem)

            version Version INTEGER 0
            privateKeyAlgorithm AlgorithmIdentifier SEQUENCE (1 elem)
                algorithm OBJECT IDENTIFIER 1.3.101.112 ed25519 (EdDSA 25519 signature algorithm)
            privateKey PrivateKey OCTET STRING (34 byte) 04203535414135354141353541413535414135354141353541413535414135354141
                OCTET STRING (32 byte) 55AA55AA55AA55AA55AA55AA55AA55AA

        """
        VERSION0_KEY = codecs.decode(
            b"302e020100300506032b6570042204203535414135354141353541413535414135354141353541413535414135354141", "hex"
        )
        x = serialization.load_der_private_key(VERSION0_KEY, password=None)
        self.assertTrue(isinstance(x, Ed25519PrivateKey))

    def test_load_version2_key(self):
        """
        Load RFC 5959 OneAsymmetricKey (v2 PrivateKeyInfo), algorithm 1.3.101.112

        PrivateKeyInfo SEQUENCE (3 elem)

            version Version INTEGER 1
            privateKeyAlgorithm AlgorithmIdentifier SEQUENCE (1 elem)
                algorithm OBJECT IDENTIFIER 1.3.101.112 ed25519 (EdDSA 25519 signature algorithm)
            privateKey PrivateKey OCTET STRING (34 byte) 04203535414135354141353541413535414135354141353541413535414135354141
                OCTET STRING (32 byte) 55AA55AA55AA55AA55AA55AA55AA55AA

        """
        VERSION1_KEY = codecs.decode(
            b"302e020101300506032b6570042204203535414135354141353541413535414135354141353541413535414135354141", "hex"
        )
        x = serialization.load_der_private_key(VERSION1_KEY, password=None)
        self.assertTrue(isinstance(x, Ed25519PrivateKey))

if __name__ == "__main__":
    unittest.main()

This is different from #13538 which was a v1 (0) key.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions