Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/cryptography/hazmat/backends/openssl/x25519.py: 30%
53 statements
« prev ^ index » next coverage.py v7.0.1, created at 2022-12-25 06:11 +0000
« prev ^ index » next coverage.py v7.0.1, created at 2022-12-25 06:11 +0000
1# This file is dual licensed under the terms of the Apache License, Version
2# 2.0, and the BSD License. See the LICENSE file in the root of this repository
3# for complete details.
5import typing
7from cryptography.hazmat.backends.openssl.utils import _evp_pkey_derive
8from cryptography.hazmat.primitives import serialization
9from cryptography.hazmat.primitives.asymmetric.x25519 import (
10 X25519PrivateKey,
11 X25519PublicKey,
12)
14if typing.TYPE_CHECKING:
15 from cryptography.hazmat.backends.openssl.backend import Backend
18_X25519_KEY_SIZE = 32
21class _X25519PublicKey(X25519PublicKey):
22 def __init__(self, backend: "Backend", evp_pkey):
23 self._backend = backend
24 self._evp_pkey = evp_pkey
26 def public_bytes(
27 self,
28 encoding: serialization.Encoding,
29 format: serialization.PublicFormat,
30 ) -> bytes:
31 if (
32 encoding is serialization.Encoding.Raw
33 or format is serialization.PublicFormat.Raw
34 ):
35 if (
36 encoding is not serialization.Encoding.Raw
37 or format is not serialization.PublicFormat.Raw
38 ):
39 raise ValueError(
40 "When using Raw both encoding and format must be Raw"
41 )
43 return self._raw_public_bytes()
45 return self._backend._public_key_bytes(
46 encoding, format, self, self._evp_pkey, None
47 )
49 def _raw_public_bytes(self) -> bytes:
50 ucharpp = self._backend._ffi.new("unsigned char **")
51 res = self._backend._lib.EVP_PKEY_get1_tls_encodedpoint(
52 self._evp_pkey, ucharpp
53 )
54 self._backend.openssl_assert(res == 32)
55 self._backend.openssl_assert(ucharpp[0] != self._backend._ffi.NULL)
56 data = self._backend._ffi.gc(
57 ucharpp[0], self._backend._lib.OPENSSL_free
58 )
59 return self._backend._ffi.buffer(data, res)[:]
62class _X25519PrivateKey(X25519PrivateKey):
63 def __init__(self, backend: "Backend", evp_pkey):
64 self._backend = backend
65 self._evp_pkey = evp_pkey
67 def public_key(self) -> X25519PublicKey:
68 bio = self._backend._create_mem_bio_gc()
69 res = self._backend._lib.i2d_PUBKEY_bio(bio, self._evp_pkey)
70 self._backend.openssl_assert(res == 1)
71 evp_pkey = self._backend._lib.d2i_PUBKEY_bio(
72 bio, self._backend._ffi.NULL
73 )
74 self._backend.openssl_assert(evp_pkey != self._backend._ffi.NULL)
75 evp_pkey = self._backend._ffi.gc(
76 evp_pkey, self._backend._lib.EVP_PKEY_free
77 )
78 return _X25519PublicKey(self._backend, evp_pkey)
80 def exchange(self, peer_public_key: X25519PublicKey) -> bytes:
81 if not isinstance(peer_public_key, X25519PublicKey):
82 raise TypeError("peer_public_key must be X25519PublicKey.")
84 return _evp_pkey_derive(self._backend, self._evp_pkey, peer_public_key)
86 def private_bytes(
87 self,
88 encoding: serialization.Encoding,
89 format: serialization.PrivateFormat,
90 encryption_algorithm: serialization.KeySerializationEncryption,
91 ) -> bytes:
92 if (
93 encoding is serialization.Encoding.Raw
94 or format is serialization.PublicFormat.Raw
95 ):
96 if (
97 format is not serialization.PrivateFormat.Raw
98 or encoding is not serialization.Encoding.Raw
99 or not isinstance(
100 encryption_algorithm, serialization.NoEncryption
101 )
102 ):
103 raise ValueError(
104 "When using Raw both encoding and format must be Raw "
105 "and encryption_algorithm must be NoEncryption()"
106 )
108 return self._raw_private_bytes()
110 return self._backend._private_key_bytes(
111 encoding, format, encryption_algorithm, self, self._evp_pkey, None
112 )
114 def _raw_private_bytes(self) -> bytes:
115 # When we drop support for CRYPTOGRAPHY_OPENSSL_LESS_THAN_111 we can
116 # switch this to EVP_PKEY_new_raw_private_key
117 # The trick we use here is serializing to a PKCS8 key and just
118 # using the last 32 bytes, which is the key itself.
119 bio = self._backend._create_mem_bio_gc()
120 res = self._backend._lib.i2d_PKCS8PrivateKey_bio(
121 bio,
122 self._evp_pkey,
123 self._backend._ffi.NULL,
124 self._backend._ffi.NULL,
125 0,
126 self._backend._ffi.NULL,
127 self._backend._ffi.NULL,
128 )
129 self._backend.openssl_assert(res == 1)
130 pkcs8 = self._backend._read_mem_bio(bio)
131 self._backend.openssl_assert(len(pkcs8) == 48)
132 return pkcs8[-_X25519_KEY_SIZE:]