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

219 statements  

« prev     ^ index     » next       coverage.py v7.3.2, created at 2023-12-08 06:05 +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. 

4 

5from __future__ import annotations 

6 

7import abc 

8import typing 

9 

10from cryptography import utils 

11from cryptography.hazmat._oid import ObjectIdentifier 

12from cryptography.hazmat.primitives import _serialization, hashes 

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

14 

15 

16class EllipticCurveOID: 

17 SECP192R1 = ObjectIdentifier("1.2.840.10045.3.1.1") 

18 SECP224R1 = ObjectIdentifier("1.3.132.0.33") 

19 SECP256K1 = ObjectIdentifier("1.3.132.0.10") 

20 SECP256R1 = ObjectIdentifier("1.2.840.10045.3.1.7") 

21 SECP384R1 = ObjectIdentifier("1.3.132.0.34") 

22 SECP521R1 = ObjectIdentifier("1.3.132.0.35") 

23 BRAINPOOLP256R1 = ObjectIdentifier("1.3.36.3.3.2.8.1.1.7") 

24 BRAINPOOLP384R1 = ObjectIdentifier("1.3.36.3.3.2.8.1.1.11") 

25 BRAINPOOLP512R1 = ObjectIdentifier("1.3.36.3.3.2.8.1.1.13") 

26 SECT163K1 = ObjectIdentifier("1.3.132.0.1") 

27 SECT163R2 = ObjectIdentifier("1.3.132.0.15") 

28 SECT233K1 = ObjectIdentifier("1.3.132.0.26") 

29 SECT233R1 = ObjectIdentifier("1.3.132.0.27") 

30 SECT283K1 = ObjectIdentifier("1.3.132.0.16") 

31 SECT283R1 = ObjectIdentifier("1.3.132.0.17") 

32 SECT409K1 = ObjectIdentifier("1.3.132.0.36") 

33 SECT409R1 = ObjectIdentifier("1.3.132.0.37") 

34 SECT571K1 = ObjectIdentifier("1.3.132.0.38") 

35 SECT571R1 = ObjectIdentifier("1.3.132.0.39") 

36 

37 

38class EllipticCurve(metaclass=abc.ABCMeta): 

39 @property 

40 @abc.abstractmethod 

41 def name(self) -> str: 

42 """ 

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

44 """ 

45 

46 @property 

47 @abc.abstractmethod 

48 def key_size(self) -> int: 

49 """ 

50 Bit size of a secret scalar for the curve. 

51 """ 

52 

53 

54class EllipticCurveSignatureAlgorithm(metaclass=abc.ABCMeta): 

55 @property 

56 @abc.abstractmethod 

57 def algorithm( 

58 self, 

59 ) -> typing.Union[asym_utils.Prehashed, hashes.HashAlgorithm]: 

60 """ 

61 The digest algorithm used with this signature. 

62 """ 

63 

64 

65class EllipticCurvePrivateKey(metaclass=abc.ABCMeta): 

66 @abc.abstractmethod 

67 def exchange( 

68 self, algorithm: ECDH, peer_public_key: EllipticCurvePublicKey 

69 ) -> bytes: 

70 """ 

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

72 provided peer's public key. 

73 """ 

74 

75 @abc.abstractmethod 

76 def public_key(self) -> EllipticCurvePublicKey: 

77 """ 

78 The EllipticCurvePublicKey for this private key. 

79 """ 

80 

81 @property 

82 @abc.abstractmethod 

83 def curve(self) -> EllipticCurve: 

84 """ 

85 The EllipticCurve that this key is on. 

86 """ 

87 

88 @property 

89 @abc.abstractmethod 

90 def key_size(self) -> int: 

91 """ 

92 Bit size of a secret scalar for the curve. 

93 """ 

94 

95 @abc.abstractmethod 

96 def sign( 

97 self, 

98 data: bytes, 

99 signature_algorithm: EllipticCurveSignatureAlgorithm, 

100 ) -> bytes: 

101 """ 

102 Signs the data 

103 """ 

104 

105 @abc.abstractmethod 

106 def private_numbers(self) -> EllipticCurvePrivateNumbers: 

107 """ 

108 Returns an EllipticCurvePrivateNumbers. 

109 """ 

110 

111 @abc.abstractmethod 

112 def private_bytes( 

113 self, 

114 encoding: _serialization.Encoding, 

115 format: _serialization.PrivateFormat, 

116 encryption_algorithm: _serialization.KeySerializationEncryption, 

117 ) -> bytes: 

118 """ 

119 Returns the key serialized as bytes. 

120 """ 

121 

122 

123EllipticCurvePrivateKeyWithSerialization = EllipticCurvePrivateKey 

124 

125 

126class EllipticCurvePublicKey(metaclass=abc.ABCMeta): 

127 @property 

128 @abc.abstractmethod 

129 def curve(self) -> EllipticCurve: 

130 """ 

131 The EllipticCurve that this key is on. 

132 """ 

133 

134 @property 

135 @abc.abstractmethod 

136 def key_size(self) -> int: 

137 """ 

138 Bit size of a secret scalar for the curve. 

139 """ 

140 

141 @abc.abstractmethod 

142 def public_numbers(self) -> EllipticCurvePublicNumbers: 

143 """ 

144 Returns an EllipticCurvePublicNumbers. 

145 """ 

146 

147 @abc.abstractmethod 

148 def public_bytes( 

149 self, 

150 encoding: _serialization.Encoding, 

151 format: _serialization.PublicFormat, 

152 ) -> bytes: 

153 """ 

154 Returns the key serialized as bytes. 

155 """ 

156 

157 @abc.abstractmethod 

158 def verify( 

159 self, 

160 signature: bytes, 

161 data: bytes, 

162 signature_algorithm: EllipticCurveSignatureAlgorithm, 

163 ) -> None: 

164 """ 

165 Verifies the signature of the data. 

166 """ 

167 

168 @classmethod 

169 def from_encoded_point( 

170 cls, curve: EllipticCurve, data: bytes 

171 ) -> EllipticCurvePublicKey: 

172 utils._check_bytes("data", data) 

173 

174 if not isinstance(curve, EllipticCurve): 

175 raise TypeError("curve must be an EllipticCurve instance") 

176 

177 if len(data) == 0: 

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

179 

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

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

182 

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

184 

185 return backend.load_elliptic_curve_public_bytes(curve, data) 

186 

187 @abc.abstractmethod 

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

189 """ 

190 Checks equality. 

191 """ 

192 

193 

194EllipticCurvePublicKeyWithSerialization = EllipticCurvePublicKey 

195 

196 

197class SECT571R1(EllipticCurve): 

198 name = "sect571r1" 

199 key_size = 570 

200 

201 

202class SECT409R1(EllipticCurve): 

203 name = "sect409r1" 

204 key_size = 409 

205 

206 

207class SECT283R1(EllipticCurve): 

208 name = "sect283r1" 

209 key_size = 283 

210 

211 

212class SECT233R1(EllipticCurve): 

213 name = "sect233r1" 

214 key_size = 233 

215 

216 

217class SECT163R2(EllipticCurve): 

218 name = "sect163r2" 

219 key_size = 163 

220 

221 

222class SECT571K1(EllipticCurve): 

223 name = "sect571k1" 

224 key_size = 571 

225 

226 

227class SECT409K1(EllipticCurve): 

228 name = "sect409k1" 

229 key_size = 409 

230 

231 

232class SECT283K1(EllipticCurve): 

233 name = "sect283k1" 

234 key_size = 283 

235 

236 

237class SECT233K1(EllipticCurve): 

238 name = "sect233k1" 

239 key_size = 233 

240 

241 

242class SECT163K1(EllipticCurve): 

243 name = "sect163k1" 

244 key_size = 163 

245 

246 

247class SECP521R1(EllipticCurve): 

248 name = "secp521r1" 

249 key_size = 521 

250 

251 

252class SECP384R1(EllipticCurve): 

253 name = "secp384r1" 

254 key_size = 384 

255 

256 

257class SECP256R1(EllipticCurve): 

258 name = "secp256r1" 

259 key_size = 256 

260 

261 

262class SECP256K1(EllipticCurve): 

263 name = "secp256k1" 

264 key_size = 256 

265 

266 

267class SECP224R1(EllipticCurve): 

268 name = "secp224r1" 

269 key_size = 224 

270 

271 

272class SECP192R1(EllipticCurve): 

273 name = "secp192r1" 

274 key_size = 192 

275 

276 

277class BrainpoolP256R1(EllipticCurve): 

278 name = "brainpoolP256r1" 

279 key_size = 256 

280 

281 

282class BrainpoolP384R1(EllipticCurve): 

283 name = "brainpoolP384r1" 

284 key_size = 384 

285 

286 

287class BrainpoolP512R1(EllipticCurve): 

288 name = "brainpoolP512r1" 

289 key_size = 512 

290 

291 

292_CURVE_TYPES: typing.Dict[str, typing.Type[EllipticCurve]] = { 

293 "prime192v1": SECP192R1, 

294 "prime256v1": SECP256R1, 

295 "secp192r1": SECP192R1, 

296 "secp224r1": SECP224R1, 

297 "secp256r1": SECP256R1, 

298 "secp384r1": SECP384R1, 

299 "secp521r1": SECP521R1, 

300 "secp256k1": SECP256K1, 

301 "sect163k1": SECT163K1, 

302 "sect233k1": SECT233K1, 

303 "sect283k1": SECT283K1, 

304 "sect409k1": SECT409K1, 

305 "sect571k1": SECT571K1, 

306 "sect163r2": SECT163R2, 

307 "sect233r1": SECT233R1, 

308 "sect283r1": SECT283R1, 

309 "sect409r1": SECT409R1, 

310 "sect571r1": SECT571R1, 

311 "brainpoolP256r1": BrainpoolP256R1, 

312 "brainpoolP384r1": BrainpoolP384R1, 

313 "brainpoolP512r1": BrainpoolP512R1, 

314} 

315 

316 

317class ECDSA(EllipticCurveSignatureAlgorithm): 

318 def __init__( 

319 self, 

320 algorithm: typing.Union[asym_utils.Prehashed, hashes.HashAlgorithm], 

321 ): 

322 self._algorithm = algorithm 

323 

324 @property 

325 def algorithm( 

326 self, 

327 ) -> typing.Union[asym_utils.Prehashed, hashes.HashAlgorithm]: 

328 return self._algorithm 

329 

330 

331def generate_private_key( 

332 curve: EllipticCurve, backend: typing.Any = None 

333) -> EllipticCurvePrivateKey: 

334 from cryptography.hazmat.backends.openssl.backend import backend as ossl 

335 

336 return ossl.generate_elliptic_curve_private_key(curve) 

337 

338 

339def derive_private_key( 

340 private_value: int, 

341 curve: EllipticCurve, 

342 backend: typing.Any = None, 

343) -> EllipticCurvePrivateKey: 

344 from cryptography.hazmat.backends.openssl.backend import backend as ossl 

345 

346 if not isinstance(private_value, int): 

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

348 

349 if private_value <= 0: 

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

351 

352 if not isinstance(curve, EllipticCurve): 

353 raise TypeError("curve must provide the EllipticCurve interface.") 

354 

355 return ossl.derive_elliptic_curve_private_key(private_value, curve) 

356 

357 

358class EllipticCurvePublicNumbers: 

359 def __init__(self, x: int, y: int, curve: EllipticCurve): 

360 if not isinstance(x, int) or not isinstance(y, int): 

361 raise TypeError("x and y must be integers.") 

362 

363 if not isinstance(curve, EllipticCurve): 

364 raise TypeError("curve must provide the EllipticCurve interface.") 

365 

366 self._y = y 

367 self._x = x 

368 self._curve = curve 

369 

370 def public_key(self, backend: typing.Any = None) -> EllipticCurvePublicKey: 

371 from cryptography.hazmat.backends.openssl.backend import ( 

372 backend as ossl, 

373 ) 

374 

375 return ossl.load_elliptic_curve_public_numbers(self) 

376 

377 @property 

378 def curve(self) -> EllipticCurve: 

379 return self._curve 

380 

381 @property 

382 def x(self) -> int: 

383 return self._x 

384 

385 @property 

386 def y(self) -> int: 

387 return self._y 

388 

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

390 if not isinstance(other, EllipticCurvePublicNumbers): 

391 return NotImplemented 

392 

393 return ( 

394 self.x == other.x 

395 and self.y == other.y 

396 and self.curve.name == other.curve.name 

397 and self.curve.key_size == other.curve.key_size 

398 ) 

399 

400 def __hash__(self) -> int: 

401 return hash((self.x, self.y, self.curve.name, self.curve.key_size)) 

402 

403 def __repr__(self) -> str: 

404 return ( 

405 "<EllipticCurvePublicNumbers(curve={0.curve.name}, x={0.x}, " 

406 "y={0.y}>".format(self) 

407 ) 

408 

409 

410class EllipticCurvePrivateNumbers: 

411 def __init__( 

412 self, private_value: int, public_numbers: EllipticCurvePublicNumbers 

413 ): 

414 if not isinstance(private_value, int): 

415 raise TypeError("private_value must be an integer.") 

416 

417 if not isinstance(public_numbers, EllipticCurvePublicNumbers): 

418 raise TypeError( 

419 "public_numbers must be an EllipticCurvePublicNumbers " 

420 "instance." 

421 ) 

422 

423 self._private_value = private_value 

424 self._public_numbers = public_numbers 

425 

426 def private_key( 

427 self, backend: typing.Any = None 

428 ) -> EllipticCurvePrivateKey: 

429 from cryptography.hazmat.backends.openssl.backend import ( 

430 backend as ossl, 

431 ) 

432 

433 return ossl.load_elliptic_curve_private_numbers(self) 

434 

435 @property 

436 def private_value(self) -> int: 

437 return self._private_value 

438 

439 @property 

440 def public_numbers(self) -> EllipticCurvePublicNumbers: 

441 return self._public_numbers 

442 

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

444 if not isinstance(other, EllipticCurvePrivateNumbers): 

445 return NotImplemented 

446 

447 return ( 

448 self.private_value == other.private_value 

449 and self.public_numbers == other.public_numbers 

450 ) 

451 

452 def __hash__(self) -> int: 

453 return hash((self.private_value, self.public_numbers)) 

454 

455 

456class ECDH: 

457 pass 

458 

459 

460_OID_TO_CURVE = { 

461 EllipticCurveOID.SECP192R1: SECP192R1, 

462 EllipticCurveOID.SECP224R1: SECP224R1, 

463 EllipticCurveOID.SECP256K1: SECP256K1, 

464 EllipticCurveOID.SECP256R1: SECP256R1, 

465 EllipticCurveOID.SECP384R1: SECP384R1, 

466 EllipticCurveOID.SECP521R1: SECP521R1, 

467 EllipticCurveOID.BRAINPOOLP256R1: BrainpoolP256R1, 

468 EllipticCurveOID.BRAINPOOLP384R1: BrainpoolP384R1, 

469 EllipticCurveOID.BRAINPOOLP512R1: BrainpoolP512R1, 

470 EllipticCurveOID.SECT163K1: SECT163K1, 

471 EllipticCurveOID.SECT163R2: SECT163R2, 

472 EllipticCurveOID.SECT233K1: SECT233K1, 

473 EllipticCurveOID.SECT233R1: SECT233R1, 

474 EllipticCurveOID.SECT283K1: SECT283K1, 

475 EllipticCurveOID.SECT283R1: SECT283R1, 

476 EllipticCurveOID.SECT409K1: SECT409K1, 

477 EllipticCurveOID.SECT409R1: SECT409R1, 

478 EllipticCurveOID.SECT571K1: SECT571K1, 

479 EllipticCurveOID.SECT571R1: SECT571R1, 

480} 

481 

482 

483def get_curve_for_oid(oid: ObjectIdentifier) -> typing.Type[EllipticCurve]: 

484 try: 

485 return _OID_TO_CURVE[oid] 

486 except KeyError: 

487 raise LookupError( 

488 "The provided object identifier has no matching elliptic " 

489 "curve class" 

490 )