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

216 statements  

« prev     ^ index     » next       coverage.py v7.2.2, created at 2023-03-26 06:36 +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 

5 

6import abc 

7import typing 

8 

9from cryptography import utils 

10from cryptography.hazmat._oid import ObjectIdentifier 

11from cryptography.hazmat.primitives import _serialization, hashes 

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

13 

14 

15class EllipticCurveOID: 

16 SECP192R1 = ObjectIdentifier("1.2.840.10045.3.1.1") 

17 SECP224R1 = ObjectIdentifier("1.3.132.0.33") 

18 SECP256K1 = ObjectIdentifier("1.3.132.0.10") 

19 SECP256R1 = ObjectIdentifier("1.2.840.10045.3.1.7") 

20 SECP384R1 = ObjectIdentifier("1.3.132.0.34") 

21 SECP521R1 = ObjectIdentifier("1.3.132.0.35") 

22 BRAINPOOLP256R1 = ObjectIdentifier("1.3.36.3.3.2.8.1.1.7") 

23 BRAINPOOLP384R1 = ObjectIdentifier("1.3.36.3.3.2.8.1.1.11") 

24 BRAINPOOLP512R1 = ObjectIdentifier("1.3.36.3.3.2.8.1.1.13") 

25 SECT163K1 = ObjectIdentifier("1.3.132.0.1") 

26 SECT163R2 = ObjectIdentifier("1.3.132.0.15") 

27 SECT233K1 = ObjectIdentifier("1.3.132.0.26") 

28 SECT233R1 = ObjectIdentifier("1.3.132.0.27") 

29 SECT283K1 = ObjectIdentifier("1.3.132.0.16") 

30 SECT283R1 = ObjectIdentifier("1.3.132.0.17") 

31 SECT409K1 = ObjectIdentifier("1.3.132.0.36") 

32 SECT409R1 = ObjectIdentifier("1.3.132.0.37") 

33 SECT571K1 = ObjectIdentifier("1.3.132.0.38") 

34 SECT571R1 = ObjectIdentifier("1.3.132.0.39") 

35 

36 

37class EllipticCurve(metaclass=abc.ABCMeta): 

38 @property 

39 @abc.abstractmethod 

40 def name(self) -> str: 

41 """ 

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

43 """ 

44 

45 @property 

46 @abc.abstractmethod 

47 def key_size(self) -> int: 

48 """ 

49 Bit size of a secret scalar for the curve. 

50 """ 

51 

52 

53class EllipticCurveSignatureAlgorithm(metaclass=abc.ABCMeta): 

54 @property 

55 @abc.abstractmethod 

56 def algorithm( 

57 self, 

58 ) -> typing.Union[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: bytes, 

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 

122EllipticCurvePrivateKeyWithSerialization = EllipticCurvePrivateKey 

123 

124 

125class EllipticCurvePublicKey(metaclass=abc.ABCMeta): 

126 @property 

127 @abc.abstractmethod 

128 def curve(self) -> EllipticCurve: 

129 """ 

130 The EllipticCurve that this key is on. 

131 """ 

132 

133 @property 

134 @abc.abstractmethod 

135 def key_size(self) -> int: 

136 """ 

137 Bit size of a secret scalar for the curve. 

138 """ 

139 

140 @abc.abstractmethod 

141 def public_numbers(self) -> "EllipticCurvePublicNumbers": 

142 """ 

143 Returns an EllipticCurvePublicNumbers. 

144 """ 

145 

146 @abc.abstractmethod 

147 def public_bytes( 

148 self, 

149 encoding: _serialization.Encoding, 

150 format: _serialization.PublicFormat, 

151 ) -> bytes: 

152 """ 

153 Returns the key serialized as bytes. 

154 """ 

155 

156 @abc.abstractmethod 

157 def verify( 

158 self, 

159 signature: bytes, 

160 data: bytes, 

161 signature_algorithm: EllipticCurveSignatureAlgorithm, 

162 ) -> None: 

163 """ 

164 Verifies the signature of the data. 

165 """ 

166 

167 @classmethod 

168 def from_encoded_point( 

169 cls, curve: EllipticCurve, data: bytes 

170 ) -> "EllipticCurvePublicKey": 

171 utils._check_bytes("data", data) 

172 

173 if not isinstance(curve, EllipticCurve): 

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

175 

176 if len(data) == 0: 

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

178 

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

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

181 

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

183 

184 return backend.load_elliptic_curve_public_bytes(curve, data) 

185 

186 

187EllipticCurvePublicKeyWithSerialization = EllipticCurvePublicKey 

188 

189 

190class SECT571R1(EllipticCurve): 

191 name = "sect571r1" 

192 key_size = 570 

193 

194 

195class SECT409R1(EllipticCurve): 

196 name = "sect409r1" 

197 key_size = 409 

198 

199 

200class SECT283R1(EllipticCurve): 

201 name = "sect283r1" 

202 key_size = 283 

203 

204 

205class SECT233R1(EllipticCurve): 

206 name = "sect233r1" 

207 key_size = 233 

208 

209 

210class SECT163R2(EllipticCurve): 

211 name = "sect163r2" 

212 key_size = 163 

213 

214 

215class SECT571K1(EllipticCurve): 

216 name = "sect571k1" 

217 key_size = 571 

218 

219 

220class SECT409K1(EllipticCurve): 

221 name = "sect409k1" 

222 key_size = 409 

223 

224 

225class SECT283K1(EllipticCurve): 

226 name = "sect283k1" 

227 key_size = 283 

228 

229 

230class SECT233K1(EllipticCurve): 

231 name = "sect233k1" 

232 key_size = 233 

233 

234 

235class SECT163K1(EllipticCurve): 

236 name = "sect163k1" 

237 key_size = 163 

238 

239 

240class SECP521R1(EllipticCurve): 

241 name = "secp521r1" 

242 key_size = 521 

243 

244 

245class SECP384R1(EllipticCurve): 

246 name = "secp384r1" 

247 key_size = 384 

248 

249 

250class SECP256R1(EllipticCurve): 

251 name = "secp256r1" 

252 key_size = 256 

253 

254 

255class SECP256K1(EllipticCurve): 

256 name = "secp256k1" 

257 key_size = 256 

258 

259 

260class SECP224R1(EllipticCurve): 

261 name = "secp224r1" 

262 key_size = 224 

263 

264 

265class SECP192R1(EllipticCurve): 

266 name = "secp192r1" 

267 key_size = 192 

268 

269 

270class BrainpoolP256R1(EllipticCurve): 

271 name = "brainpoolP256r1" 

272 key_size = 256 

273 

274 

275class BrainpoolP384R1(EllipticCurve): 

276 name = "brainpoolP384r1" 

277 key_size = 384 

278 

279 

280class BrainpoolP512R1(EllipticCurve): 

281 name = "brainpoolP512r1" 

282 key_size = 512 

283 

284 

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

286 "prime192v1": SECP192R1, 

287 "prime256v1": SECP256R1, 

288 "secp192r1": SECP192R1, 

289 "secp224r1": SECP224R1, 

290 "secp256r1": SECP256R1, 

291 "secp384r1": SECP384R1, 

292 "secp521r1": SECP521R1, 

293 "secp256k1": SECP256K1, 

294 "sect163k1": SECT163K1, 

295 "sect233k1": SECT233K1, 

296 "sect283k1": SECT283K1, 

297 "sect409k1": SECT409K1, 

298 "sect571k1": SECT571K1, 

299 "sect163r2": SECT163R2, 

300 "sect233r1": SECT233R1, 

301 "sect283r1": SECT283R1, 

302 "sect409r1": SECT409R1, 

303 "sect571r1": SECT571R1, 

304 "brainpoolP256r1": BrainpoolP256R1, 

305 "brainpoolP384r1": BrainpoolP384R1, 

306 "brainpoolP512r1": BrainpoolP512R1, 

307} 

308 

309 

310class ECDSA(EllipticCurveSignatureAlgorithm): 

311 def __init__( 

312 self, 

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

314 ): 

315 self._algorithm = algorithm 

316 

317 @property 

318 def algorithm( 

319 self, 

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

321 return self._algorithm 

322 

323 

324def generate_private_key( 

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

326) -> EllipticCurvePrivateKey: 

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

328 

329 return ossl.generate_elliptic_curve_private_key(curve) 

330 

331 

332def derive_private_key( 

333 private_value: int, 

334 curve: EllipticCurve, 

335 backend: typing.Any = None, 

336) -> EllipticCurvePrivateKey: 

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

338 

339 if not isinstance(private_value, int): 

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

341 

342 if private_value <= 0: 

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

344 

345 if not isinstance(curve, EllipticCurve): 

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

347 

348 return ossl.derive_elliptic_curve_private_key(private_value, curve) 

349 

350 

351class EllipticCurvePublicNumbers: 

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

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

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

355 

356 if not isinstance(curve, EllipticCurve): 

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

358 

359 self._y = y 

360 self._x = x 

361 self._curve = curve 

362 

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

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

365 backend as ossl, 

366 ) 

367 

368 return ossl.load_elliptic_curve_public_numbers(self) 

369 

370 @property 

371 def curve(self) -> EllipticCurve: 

372 return self._curve 

373 

374 @property 

375 def x(self) -> int: 

376 return self._x 

377 

378 @property 

379 def y(self) -> int: 

380 return self._y 

381 

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

383 if not isinstance(other, EllipticCurvePublicNumbers): 

384 return NotImplemented 

385 

386 return ( 

387 self.x == other.x 

388 and self.y == other.y 

389 and self.curve.name == other.curve.name 

390 and self.curve.key_size == other.curve.key_size 

391 ) 

392 

393 def __hash__(self) -> int: 

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

395 

396 def __repr__(self) -> str: 

397 return ( 

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

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

400 ) 

401 

402 

403class EllipticCurvePrivateNumbers: 

404 def __init__( 

405 self, private_value: int, public_numbers: EllipticCurvePublicNumbers 

406 ): 

407 if not isinstance(private_value, int): 

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

409 

410 if not isinstance(public_numbers, EllipticCurvePublicNumbers): 

411 raise TypeError( 

412 "public_numbers must be an EllipticCurvePublicNumbers " 

413 "instance." 

414 ) 

415 

416 self._private_value = private_value 

417 self._public_numbers = public_numbers 

418 

419 def private_key( 

420 self, backend: typing.Any = None 

421 ) -> EllipticCurvePrivateKey: 

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

423 backend as ossl, 

424 ) 

425 

426 return ossl.load_elliptic_curve_private_numbers(self) 

427 

428 @property 

429 def private_value(self) -> int: 

430 return self._private_value 

431 

432 @property 

433 def public_numbers(self) -> EllipticCurvePublicNumbers: 

434 return self._public_numbers 

435 

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

437 if not isinstance(other, EllipticCurvePrivateNumbers): 

438 return NotImplemented 

439 

440 return ( 

441 self.private_value == other.private_value 

442 and self.public_numbers == other.public_numbers 

443 ) 

444 

445 def __hash__(self) -> int: 

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

447 

448 

449class ECDH: 

450 pass 

451 

452 

453_OID_TO_CURVE = { 

454 EllipticCurveOID.SECP192R1: SECP192R1, 

455 EllipticCurveOID.SECP224R1: SECP224R1, 

456 EllipticCurveOID.SECP256K1: SECP256K1, 

457 EllipticCurveOID.SECP256R1: SECP256R1, 

458 EllipticCurveOID.SECP384R1: SECP384R1, 

459 EllipticCurveOID.SECP521R1: SECP521R1, 

460 EllipticCurveOID.BRAINPOOLP256R1: BrainpoolP256R1, 

461 EllipticCurveOID.BRAINPOOLP384R1: BrainpoolP384R1, 

462 EllipticCurveOID.BRAINPOOLP512R1: BrainpoolP512R1, 

463 EllipticCurveOID.SECT163K1: SECT163K1, 

464 EllipticCurveOID.SECT163R2: SECT163R2, 

465 EllipticCurveOID.SECT233K1: SECT233K1, 

466 EllipticCurveOID.SECT233R1: SECT233R1, 

467 EllipticCurveOID.SECT283K1: SECT283K1, 

468 EllipticCurveOID.SECT283R1: SECT283R1, 

469 EllipticCurveOID.SECT409K1: SECT409K1, 

470 EllipticCurveOID.SECT409R1: SECT409R1, 

471 EllipticCurveOID.SECT571K1: SECT571K1, 

472 EllipticCurveOID.SECT571R1: SECT571R1, 

473} 

474 

475 

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

477 try: 

478 return _OID_TO_CURVE[oid] 

479 except KeyError: 

480 raise LookupError( 

481 "The provided object identifier has no matching elliptic " 

482 "curve class" 

483 )