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

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

172 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 SECT163K1 = ObjectIdentifier("1.3.132.0.1") 

29 SECT163R2 = ObjectIdentifier("1.3.132.0.15") 

30 SECT233K1 = ObjectIdentifier("1.3.132.0.26") 

31 SECT233R1 = ObjectIdentifier("1.3.132.0.27") 

32 SECT283K1 = ObjectIdentifier("1.3.132.0.16") 

33 SECT283R1 = ObjectIdentifier("1.3.132.0.17") 

34 SECT409K1 = ObjectIdentifier("1.3.132.0.36") 

35 SECT409R1 = ObjectIdentifier("1.3.132.0.37") 

36 SECT571K1 = ObjectIdentifier("1.3.132.0.38") 

37 SECT571R1 = ObjectIdentifier("1.3.132.0.39") 

38 

39 

40class EllipticCurve(metaclass=abc.ABCMeta): 

41 @property 

42 @abc.abstractmethod 

43 def name(self) -> str: 

44 """ 

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

46 """ 

47 

48 @property 

49 @abc.abstractmethod 

50 def key_size(self) -> int: 

51 """ 

52 Bit size of a secret scalar for the curve. 

53 """ 

54 

55 

56class EllipticCurveSignatureAlgorithm(metaclass=abc.ABCMeta): 

57 @property 

58 @abc.abstractmethod 

59 def algorithm( 

60 self, 

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

62 """ 

63 The digest algorithm used with this signature. 

64 """ 

65 

66 

67class EllipticCurvePrivateKey(metaclass=abc.ABCMeta): 

68 @abc.abstractmethod 

69 def exchange( 

70 self, algorithm: ECDH, peer_public_key: EllipticCurvePublicKey 

71 ) -> bytes: 

72 """ 

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

74 provided peer's public key. 

75 """ 

76 

77 @abc.abstractmethod 

78 def public_key(self) -> EllipticCurvePublicKey: 

79 """ 

80 The EllipticCurvePublicKey for this private key. 

81 """ 

82 

83 @property 

84 @abc.abstractmethod 

85 def curve(self) -> EllipticCurve: 

86 """ 

87 The EllipticCurve that this key is on. 

88 """ 

89 

90 @property 

91 @abc.abstractmethod 

92 def key_size(self) -> int: 

93 """ 

94 Bit size of a secret scalar for the curve. 

95 """ 

96 

97 @abc.abstractmethod 

98 def sign( 

99 self, 

100 data: bytes, 

101 signature_algorithm: EllipticCurveSignatureAlgorithm, 

102 ) -> bytes: 

103 """ 

104 Signs the data 

105 """ 

106 

107 @abc.abstractmethod 

108 def private_numbers(self) -> EllipticCurvePrivateNumbers: 

109 """ 

110 Returns an EllipticCurvePrivateNumbers. 

111 """ 

112 

113 @abc.abstractmethod 

114 def private_bytes( 

115 self, 

116 encoding: _serialization.Encoding, 

117 format: _serialization.PrivateFormat, 

118 encryption_algorithm: _serialization.KeySerializationEncryption, 

119 ) -> bytes: 

120 """ 

121 Returns the key serialized as bytes. 

122 """ 

123 

124 

125EllipticCurvePrivateKeyWithSerialization = EllipticCurvePrivateKey 

126EllipticCurvePrivateKey.register(rust_openssl.ec.ECPrivateKey) 

127 

128 

129class EllipticCurvePublicKey(metaclass=abc.ABCMeta): 

130 @property 

131 @abc.abstractmethod 

132 def curve(self) -> EllipticCurve: 

133 """ 

134 The EllipticCurve that this key is on. 

135 """ 

136 

137 @property 

138 @abc.abstractmethod 

139 def key_size(self) -> int: 

140 """ 

141 Bit size of a secret scalar for the curve. 

142 """ 

143 

144 @abc.abstractmethod 

145 def public_numbers(self) -> EllipticCurvePublicNumbers: 

146 """ 

147 Returns an EllipticCurvePublicNumbers. 

148 """ 

149 

150 @abc.abstractmethod 

151 def public_bytes( 

152 self, 

153 encoding: _serialization.Encoding, 

154 format: _serialization.PublicFormat, 

155 ) -> bytes: 

156 """ 

157 Returns the key serialized as bytes. 

158 """ 

159 

160 @abc.abstractmethod 

161 def verify( 

162 self, 

163 signature: bytes, 

164 data: bytes, 

165 signature_algorithm: EllipticCurveSignatureAlgorithm, 

166 ) -> None: 

167 """ 

168 Verifies the signature of the data. 

169 """ 

170 

171 @classmethod 

172 def from_encoded_point( 

173 cls, curve: EllipticCurve, data: bytes 

174 ) -> EllipticCurvePublicKey: 

175 utils._check_bytes("data", data) 

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 return rust_openssl.ec.from_public_bytes(curve, data) 

184 

185 @abc.abstractmethod 

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

187 """ 

188 Checks equality. 

189 """ 

190 

191 

192EllipticCurvePublicKeyWithSerialization = EllipticCurvePublicKey 

193EllipticCurvePublicKey.register(rust_openssl.ec.ECPublicKey) 

194 

195EllipticCurvePrivateNumbers = rust_openssl.ec.EllipticCurvePrivateNumbers 

196EllipticCurvePublicNumbers = rust_openssl.ec.EllipticCurvePublicNumbers 

197 

198 

199class SECT571R1(EllipticCurve): 

200 name = "sect571r1" 

201 key_size = 570 

202 

203 

204class SECT409R1(EllipticCurve): 

205 name = "sect409r1" 

206 key_size = 409 

207 

208 

209class SECT283R1(EllipticCurve): 

210 name = "sect283r1" 

211 key_size = 283 

212 

213 

214class SECT233R1(EllipticCurve): 

215 name = "sect233r1" 

216 key_size = 233 

217 

218 

219class SECT163R2(EllipticCurve): 

220 name = "sect163r2" 

221 key_size = 163 

222 

223 

224class SECT571K1(EllipticCurve): 

225 name = "sect571k1" 

226 key_size = 571 

227 

228 

229class SECT409K1(EllipticCurve): 

230 name = "sect409k1" 

231 key_size = 409 

232 

233 

234class SECT283K1(EllipticCurve): 

235 name = "sect283k1" 

236 key_size = 283 

237 

238 

239class SECT233K1(EllipticCurve): 

240 name = "sect233k1" 

241 key_size = 233 

242 

243 

244class SECT163K1(EllipticCurve): 

245 name = "sect163k1" 

246 key_size = 163 

247 

248 

249class SECP521R1(EllipticCurve): 

250 name = "secp521r1" 

251 key_size = 521 

252 

253 

254class SECP384R1(EllipticCurve): 

255 name = "secp384r1" 

256 key_size = 384 

257 

258 

259class SECP256R1(EllipticCurve): 

260 name = "secp256r1" 

261 key_size = 256 

262 

263 

264class SECP256K1(EllipticCurve): 

265 name = "secp256k1" 

266 key_size = 256 

267 

268 

269class SECP224R1(EllipticCurve): 

270 name = "secp224r1" 

271 key_size = 224 

272 

273 

274class SECP192R1(EllipticCurve): 

275 name = "secp192r1" 

276 key_size = 192 

277 

278 

279class BrainpoolP256R1(EllipticCurve): 

280 name = "brainpoolP256r1" 

281 key_size = 256 

282 

283 

284class BrainpoolP384R1(EllipticCurve): 

285 name = "brainpoolP384r1" 

286 key_size = 384 

287 

288 

289class BrainpoolP512R1(EllipticCurve): 

290 name = "brainpoolP512r1" 

291 key_size = 512 

292 

293 

294_CURVE_TYPES: dict[str, EllipticCurve] = { 

295 "prime192v1": SECP192R1(), 

296 "prime256v1": SECP256R1(), 

297 "secp192r1": SECP192R1(), 

298 "secp224r1": SECP224R1(), 

299 "secp256r1": SECP256R1(), 

300 "secp384r1": SECP384R1(), 

301 "secp521r1": SECP521R1(), 

302 "secp256k1": SECP256K1(), 

303 "sect163k1": SECT163K1(), 

304 "sect233k1": SECT233K1(), 

305 "sect283k1": SECT283K1(), 

306 "sect409k1": SECT409K1(), 

307 "sect571k1": SECT571K1(), 

308 "sect163r2": SECT163R2(), 

309 "sect233r1": SECT233R1(), 

310 "sect283r1": SECT283R1(), 

311 "sect409r1": SECT409R1(), 

312 "sect571r1": SECT571R1(), 

313 "brainpoolP256r1": BrainpoolP256R1(), 

314 "brainpoolP384r1": BrainpoolP384R1(), 

315 "brainpoolP512r1": BrainpoolP512R1(), 

316} 

317 

318 

319class ECDSA(EllipticCurveSignatureAlgorithm): 

320 def __init__( 

321 self, 

322 algorithm: asym_utils.Prehashed | hashes.HashAlgorithm, 

323 deterministic_signing: bool = False, 

324 ): 

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

326 

327 if ( 

328 deterministic_signing 

329 and not backend.ecdsa_deterministic_supported() 

330 ): 

331 raise UnsupportedAlgorithm( 

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

333 "supported by this version of OpenSSL.", 

334 _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM, 

335 ) 

336 self._algorithm = algorithm 

337 self._deterministic_signing = deterministic_signing 

338 

339 @property 

340 def algorithm( 

341 self, 

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

343 return self._algorithm 

344 

345 @property 

346 def deterministic_signing( 

347 self, 

348 ) -> bool: 

349 return self._deterministic_signing 

350 

351 

352generate_private_key = rust_openssl.ec.generate_private_key 

353 

354 

355def derive_private_key( 

356 private_value: int, 

357 curve: EllipticCurve, 

358 backend: typing.Any = None, 

359) -> EllipticCurvePrivateKey: 

360 if not isinstance(private_value, int): 

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

362 

363 if private_value <= 0: 

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

365 

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

367 

368 

369class ECDH: 

370 pass 

371 

372 

373_OID_TO_CURVE = { 

374 EllipticCurveOID.SECP192R1: SECP192R1, 

375 EllipticCurveOID.SECP224R1: SECP224R1, 

376 EllipticCurveOID.SECP256K1: SECP256K1, 

377 EllipticCurveOID.SECP256R1: SECP256R1, 

378 EllipticCurveOID.SECP384R1: SECP384R1, 

379 EllipticCurveOID.SECP521R1: SECP521R1, 

380 EllipticCurveOID.BRAINPOOLP256R1: BrainpoolP256R1, 

381 EllipticCurveOID.BRAINPOOLP384R1: BrainpoolP384R1, 

382 EllipticCurveOID.BRAINPOOLP512R1: BrainpoolP512R1, 

383 EllipticCurveOID.SECT163K1: SECT163K1, 

384 EllipticCurveOID.SECT163R2: SECT163R2, 

385 EllipticCurveOID.SECT233K1: SECT233K1, 

386 EllipticCurveOID.SECT233R1: SECT233R1, 

387 EllipticCurveOID.SECT283K1: SECT283K1, 

388 EllipticCurveOID.SECT283R1: SECT283R1, 

389 EllipticCurveOID.SECT409K1: SECT409K1, 

390 EllipticCurveOID.SECT409R1: SECT409R1, 

391 EllipticCurveOID.SECT571K1: SECT571K1, 

392 EllipticCurveOID.SECT571R1: SECT571R1, 

393} 

394 

395 

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

397 try: 

398 return _OID_TO_CURVE[oid] 

399 except KeyError: 

400 raise LookupError( 

401 "The provided object identifier has no matching elliptic " 

402 "curve class" 

403 )