Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/cryptography/hazmat/primitives/asymmetric/ec.py: 85%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

153 statements  

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. 

4 

5from __future__ import annotations 

6 

7import abc 

8import typing 

9 

10from cryptography import utils 

11from cryptography.exceptions import UnsupportedAlgorithm, _Reasons 

12from cryptography.hazmat._oid import ObjectIdentifier 

13from cryptography.hazmat.bindings._rust import openssl as rust_openssl 

14from cryptography.hazmat.primitives import _serialization, hashes 

15from cryptography.hazmat.primitives.asymmetric import utils as asym_utils 

16 

17 

18class EllipticCurveOID: 

19 SECP192R1 = ObjectIdentifier("1.2.840.10045.3.1.1") 

20 SECP224R1 = ObjectIdentifier("1.3.132.0.33") 

21 SECP256K1 = ObjectIdentifier("1.3.132.0.10") 

22 SECP256R1 = ObjectIdentifier("1.2.840.10045.3.1.7") 

23 SECP384R1 = ObjectIdentifier("1.3.132.0.34") 

24 SECP521R1 = ObjectIdentifier("1.3.132.0.35") 

25 BRAINPOOLP256R1 = ObjectIdentifier("1.3.36.3.3.2.8.1.1.7") 

26 BRAINPOOLP384R1 = ObjectIdentifier("1.3.36.3.3.2.8.1.1.11") 

27 BRAINPOOLP512R1 = ObjectIdentifier("1.3.36.3.3.2.8.1.1.13") 

28 

29 

30class EllipticCurve(metaclass=abc.ABCMeta): 

31 @property 

32 @abc.abstractmethod 

33 def name(self) -> str: 

34 """ 

35 The name of the curve. e.g. secp256r1. 

36 """ 

37 

38 @property 

39 @abc.abstractmethod 

40 def key_size(self) -> int: 

41 """ 

42 Bit size of a secret scalar for the curve. 

43 """ 

44 

45 @property 

46 @abc.abstractmethod 

47 def group_order(self) -> int: 

48 """ 

49 The order of the curve's group. 

50 """ 

51 

52 

53class EllipticCurveSignatureAlgorithm(metaclass=abc.ABCMeta): 

54 @property 

55 @abc.abstractmethod 

56 def algorithm( 

57 self, 

58 ) -> asym_utils.Prehashed | hashes.HashAlgorithm: 

59 """ 

60 The digest algorithm used with this signature. 

61 """ 

62 

63 

64class EllipticCurvePrivateKey(metaclass=abc.ABCMeta): 

65 @abc.abstractmethod 

66 def exchange( 

67 self, algorithm: ECDH, peer_public_key: EllipticCurvePublicKey 

68 ) -> bytes: 

69 """ 

70 Performs a key exchange operation using the provided algorithm with the 

71 provided peer's public key. 

72 """ 

73 

74 @abc.abstractmethod 

75 def public_key(self) -> EllipticCurvePublicKey: 

76 """ 

77 The EllipticCurvePublicKey for this private key. 

78 """ 

79 

80 @property 

81 @abc.abstractmethod 

82 def curve(self) -> EllipticCurve: 

83 """ 

84 The EllipticCurve that this key is on. 

85 """ 

86 

87 @property 

88 @abc.abstractmethod 

89 def key_size(self) -> int: 

90 """ 

91 Bit size of a secret scalar for the curve. 

92 """ 

93 

94 @abc.abstractmethod 

95 def sign( 

96 self, 

97 data: utils.Buffer, 

98 signature_algorithm: EllipticCurveSignatureAlgorithm, 

99 ) -> bytes: 

100 """ 

101 Signs the data 

102 """ 

103 

104 @abc.abstractmethod 

105 def private_numbers(self) -> EllipticCurvePrivateNumbers: 

106 """ 

107 Returns an EllipticCurvePrivateNumbers. 

108 """ 

109 

110 @abc.abstractmethod 

111 def private_bytes( 

112 self, 

113 encoding: _serialization.Encoding, 

114 format: _serialization.PrivateFormat, 

115 encryption_algorithm: _serialization.KeySerializationEncryption, 

116 ) -> bytes: 

117 """ 

118 Returns the key serialized as bytes. 

119 """ 

120 

121 @abc.abstractmethod 

122 def __copy__(self) -> EllipticCurvePrivateKey: 

123 """ 

124 Returns a copy. 

125 """ 

126 

127 @abc.abstractmethod 

128 def __deepcopy__(self, memo: dict) -> EllipticCurvePrivateKey: 

129 """ 

130 Returns a deep copy. 

131 """ 

132 

133 

134EllipticCurvePrivateKeyWithSerialization = EllipticCurvePrivateKey 

135EllipticCurvePrivateKey.register(rust_openssl.ec.ECPrivateKey) 

136 

137 

138class EllipticCurvePublicKey(metaclass=abc.ABCMeta): 

139 @property 

140 @abc.abstractmethod 

141 def curve(self) -> EllipticCurve: 

142 """ 

143 The EllipticCurve that this key is on. 

144 """ 

145 

146 @property 

147 @abc.abstractmethod 

148 def key_size(self) -> int: 

149 """ 

150 Bit size of a secret scalar for the curve. 

151 """ 

152 

153 @abc.abstractmethod 

154 def public_numbers(self) -> EllipticCurvePublicNumbers: 

155 """ 

156 Returns an EllipticCurvePublicNumbers. 

157 """ 

158 

159 @abc.abstractmethod 

160 def public_bytes( 

161 self, 

162 encoding: _serialization.Encoding, 

163 format: _serialization.PublicFormat, 

164 ) -> bytes: 

165 """ 

166 Returns the key serialized as bytes. 

167 """ 

168 

169 @abc.abstractmethod 

170 def verify( 

171 self, 

172 signature: utils.Buffer, 

173 data: utils.Buffer, 

174 signature_algorithm: EllipticCurveSignatureAlgorithm, 

175 ) -> None: 

176 """ 

177 Verifies the signature of the data. 

178 """ 

179 

180 @classmethod 

181 def from_encoded_point( 

182 cls, curve: EllipticCurve, data: bytes 

183 ) -> EllipticCurvePublicKey: 

184 utils._check_bytes("data", data) 

185 

186 if len(data) == 0: 

187 raise ValueError("data must not be an empty byte string") 

188 

189 if data[0] not in [0x02, 0x03, 0x04]: 

190 raise ValueError("Unsupported elliptic curve point type") 

191 

192 return rust_openssl.ec.from_public_bytes(curve, data) 

193 

194 @abc.abstractmethod 

195 def __eq__(self, other: object) -> bool: 

196 """ 

197 Checks equality. 

198 """ 

199 

200 @abc.abstractmethod 

201 def __copy__(self) -> EllipticCurvePublicKey: 

202 """ 

203 Returns a copy. 

204 """ 

205 

206 @abc.abstractmethod 

207 def __deepcopy__(self, memo: dict) -> EllipticCurvePublicKey: 

208 """ 

209 Returns a deep copy. 

210 """ 

211 

212 

213EllipticCurvePublicKeyWithSerialization = EllipticCurvePublicKey 

214EllipticCurvePublicKey.register(rust_openssl.ec.ECPublicKey) 

215 

216EllipticCurvePrivateNumbers = rust_openssl.ec.EllipticCurvePrivateNumbers 

217EllipticCurvePublicNumbers = rust_openssl.ec.EllipticCurvePublicNumbers 

218 

219 

220class SECP521R1(EllipticCurve): 

221 name = "secp521r1" 

222 key_size = 521 

223 group_order = 0x1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409 # noqa: E501 

224 

225 

226class SECP384R1(EllipticCurve): 

227 name = "secp384r1" 

228 key_size = 384 

229 group_order = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973 # noqa: E501 

230 

231 

232class SECP256R1(EllipticCurve): 

233 name = "secp256r1" 

234 key_size = 256 

235 group_order = ( 

236 0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551 

237 ) 

238 

239 

240class SECP256K1(EllipticCurve): 

241 name = "secp256k1" 

242 key_size = 256 

243 group_order = ( 

244 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 

245 ) 

246 

247 

248class SECP224R1(EllipticCurve): 

249 name = "secp224r1" 

250 key_size = 224 

251 group_order = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D 

252 

253 

254class SECP192R1(EllipticCurve): 

255 name = "secp192r1" 

256 key_size = 192 

257 group_order = 0xFFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831 

258 

259 

260class BrainpoolP256R1(EllipticCurve): 

261 name = "brainpoolP256r1" 

262 key_size = 256 

263 group_order = ( 

264 0xA9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7 

265 ) 

266 

267 

268class BrainpoolP384R1(EllipticCurve): 

269 name = "brainpoolP384r1" 

270 key_size = 384 

271 group_order = 0x8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565 # noqa: E501 

272 

273 

274class BrainpoolP512R1(EllipticCurve): 

275 name = "brainpoolP512r1" 

276 key_size = 512 

277 group_order = 0xAADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069 # noqa: E501 

278 

279 

280_CURVE_TYPES: dict[str, EllipticCurve] = { 

281 "prime192v1": SECP192R1(), 

282 "prime256v1": SECP256R1(), 

283 "secp192r1": SECP192R1(), 

284 "secp224r1": SECP224R1(), 

285 "secp256r1": SECP256R1(), 

286 "secp384r1": SECP384R1(), 

287 "secp521r1": SECP521R1(), 

288 "secp256k1": SECP256K1(), 

289 "brainpoolP256r1": BrainpoolP256R1(), 

290 "brainpoolP384r1": BrainpoolP384R1(), 

291 "brainpoolP512r1": BrainpoolP512R1(), 

292} 

293 

294 

295class ECDSA(EllipticCurveSignatureAlgorithm): 

296 def __init__( 

297 self, 

298 algorithm: asym_utils.Prehashed | hashes.HashAlgorithm, 

299 deterministic_signing: bool = False, 

300 ): 

301 from cryptography.hazmat.backends.openssl.backend import backend 

302 

303 if ( 

304 deterministic_signing 

305 and not backend.ecdsa_deterministic_supported() 

306 ): 

307 raise UnsupportedAlgorithm( 

308 "ECDSA with deterministic signature (RFC 6979) is not " 

309 "supported by this version of OpenSSL.", 

310 _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM, 

311 ) 

312 self._algorithm = algorithm 

313 self._deterministic_signing = deterministic_signing 

314 

315 @property 

316 def algorithm( 

317 self, 

318 ) -> asym_utils.Prehashed | hashes.HashAlgorithm: 

319 return self._algorithm 

320 

321 @property 

322 def deterministic_signing( 

323 self, 

324 ) -> bool: 

325 return self._deterministic_signing 

326 

327 

328generate_private_key = rust_openssl.ec.generate_private_key 

329 

330 

331def derive_private_key( 

332 private_value: int, 

333 curve: EllipticCurve, 

334 backend: typing.Any = None, 

335) -> EllipticCurvePrivateKey: 

336 if not isinstance(private_value, int): 

337 raise TypeError("private_value must be an integer type.") 

338 

339 if private_value <= 0: 

340 raise ValueError("private_value must be a positive integer.") 

341 

342 return rust_openssl.ec.derive_private_key(private_value, curve) 

343 

344 

345class ECDH: 

346 pass 

347 

348 

349_OID_TO_CURVE = { 

350 EllipticCurveOID.SECP192R1: SECP192R1, 

351 EllipticCurveOID.SECP224R1: SECP224R1, 

352 EllipticCurveOID.SECP256K1: SECP256K1, 

353 EllipticCurveOID.SECP256R1: SECP256R1, 

354 EllipticCurveOID.SECP384R1: SECP384R1, 

355 EllipticCurveOID.SECP521R1: SECP521R1, 

356 EllipticCurveOID.BRAINPOOLP256R1: BrainpoolP256R1, 

357 EllipticCurveOID.BRAINPOOLP384R1: BrainpoolP384R1, 

358 EllipticCurveOID.BRAINPOOLP512R1: BrainpoolP512R1, 

359} 

360 

361 

362def get_curve_for_oid(oid: ObjectIdentifier) -> type[EllipticCurve]: 

363 try: 

364 return _OID_TO_CURVE[oid] 

365 except KeyError: 

366 raise LookupError( 

367 "The provided object identifier has no matching elliptic " 

368 "curve class" 

369 )