Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/PyNaCl-1.6.0.dev1-py3.8-linux-x86_64.egg/nacl/bindings/crypto_core.py: 28%

80 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2023-06-06 06:06 +0000

1# Copyright 2018 Donald Stufft and individual contributors 

2# 

3# Licensed under the Apache License, Version 2.0 (the "License"); 

4# you may not use this file except in compliance with the License. 

5# You may obtain a copy of the License at 

6# 

7# http://www.apache.org/licenses/LICENSE-2.0 

8# 

9# Unless required by applicable law or agreed to in writing, software 

10# distributed under the License is distributed on an "AS IS" BASIS, 

11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 

12# See the License for the specific language governing permissions and 

13# limitations under the License. 

14 

15 

16from nacl import exceptions as exc 

17from nacl._sodium import ffi, lib 

18from nacl.exceptions import ensure 

19 

20 

21has_crypto_core_ed25519 = bool(lib.PYNACL_HAS_CRYPTO_CORE_ED25519) 

22 

23crypto_core_ed25519_BYTES = 0 

24crypto_core_ed25519_SCALARBYTES = 0 

25crypto_core_ed25519_NONREDUCEDSCALARBYTES = 0 

26 

27if has_crypto_core_ed25519: 

28 crypto_core_ed25519_BYTES = lib.crypto_core_ed25519_bytes() 

29 crypto_core_ed25519_SCALARBYTES = lib.crypto_core_ed25519_scalarbytes() 

30 crypto_core_ed25519_NONREDUCEDSCALARBYTES = ( 

31 lib.crypto_core_ed25519_nonreducedscalarbytes() 

32 ) 

33 

34 

35def crypto_core_ed25519_is_valid_point(p: bytes) -> bool: 

36 """ 

37 Check if ``p`` represents a point on the edwards25519 curve, in canonical 

38 form, on the main subgroup, and that the point doesn't have a small order. 

39 

40 :param p: a :py:data:`.crypto_core_ed25519_BYTES` long bytes sequence 

41 representing a point on the edwards25519 curve 

42 :type p: bytes 

43 :return: point validity 

44 :rtype: bool 

45 :raises nacl.exceptions.UnavailableError: If called when using a 

46 minimal build of libsodium. 

47 """ 

48 ensure( 

49 has_crypto_core_ed25519, 

50 "Not available in minimal build", 

51 raising=exc.UnavailableError, 

52 ) 

53 

54 ensure( 

55 isinstance(p, bytes) and len(p) == crypto_core_ed25519_BYTES, 

56 "Point must be a crypto_core_ed25519_BYTES long bytes sequence", 

57 raising=exc.TypeError, 

58 ) 

59 

60 rc = lib.crypto_core_ed25519_is_valid_point(p) 

61 return rc == 1 

62 

63 

64def crypto_core_ed25519_from_uniform(r: bytes) -> bytes: 

65 """ 

66 Maps a 32 bytes vector ``r`` to a point. The point is guaranteed to be on the main subgroup. 

67 This function directly exposes the Elligator 2 map, uses the high bit to set 

68 the sign of the X coordinate, and the resulting point is multiplied by the cofactor. 

69 

70 :param r: a :py:data:`.crypto_core_ed25519_BYTES` long bytes 

71 sequence representing arbitrary data 

72 :type r: bytes 

73 :return: a point on the edwards25519 curve main order subgroup, represented as a 

74 :py:data:`.crypto_core_ed25519_BYTES` long bytes sequence 

75 :rtype: bytes 

76 :raises nacl.exceptions.UnavailableError: If called when using a 

77 minimal build of libsodium. 

78 """ 

79 ensure( 

80 has_crypto_core_ed25519, 

81 "Not available in minimal build", 

82 raising=exc.UnavailableError, 

83 ) 

84 

85 ensure( 

86 isinstance(r, bytes) and len(r) == crypto_core_ed25519_BYTES, 

87 "Integer r must be a {} long bytes sequence".format( 

88 "crypto_core_ed25519_BYTES" 

89 ), 

90 raising=exc.TypeError, 

91 ) 

92 

93 p = ffi.new("unsigned char[]", crypto_core_ed25519_BYTES) 

94 

95 rc = lib.crypto_core_ed25519_from_uniform(p, r) 

96 ensure(rc == 0, "Unexpected library error", raising=exc.RuntimeError) 

97 

98 return ffi.buffer(p, crypto_core_ed25519_BYTES)[:] 

99 

100 

101def crypto_core_ed25519_add(p: bytes, q: bytes) -> bytes: 

102 """ 

103 Add two points on the edwards25519 curve. 

104 

105 :param p: a :py:data:`.crypto_core_ed25519_BYTES` long bytes sequence 

106 representing a point on the edwards25519 curve 

107 :type p: bytes 

108 :param q: a :py:data:`.crypto_core_ed25519_BYTES` long bytes sequence 

109 representing a point on the edwards25519 curve 

110 :type q: bytes 

111 :return: a point on the edwards25519 curve represented as 

112 a :py:data:`.crypto_core_ed25519_BYTES` long bytes sequence 

113 :rtype: bytes 

114 :raises nacl.exceptions.UnavailableError: If called when using a 

115 minimal build of libsodium. 

116 """ 

117 ensure( 

118 has_crypto_core_ed25519, 

119 "Not available in minimal build", 

120 raising=exc.UnavailableError, 

121 ) 

122 

123 ensure( 

124 isinstance(p, bytes) 

125 and isinstance(q, bytes) 

126 and len(p) == crypto_core_ed25519_BYTES 

127 and len(q) == crypto_core_ed25519_BYTES, 

128 "Each point must be a {} long bytes sequence".format( 

129 "crypto_core_ed25519_BYTES" 

130 ), 

131 raising=exc.TypeError, 

132 ) 

133 

134 r = ffi.new("unsigned char[]", crypto_core_ed25519_BYTES) 

135 

136 rc = lib.crypto_core_ed25519_add(r, p, q) 

137 ensure(rc == 0, "Unexpected library error", raising=exc.RuntimeError) 

138 

139 return ffi.buffer(r, crypto_core_ed25519_BYTES)[:] 

140 

141 

142def crypto_core_ed25519_sub(p: bytes, q: bytes) -> bytes: 

143 """ 

144 Subtract a point from another on the edwards25519 curve. 

145 

146 :param p: a :py:data:`.crypto_core_ed25519_BYTES` long bytes sequence 

147 representing a point on the edwards25519 curve 

148 :type p: bytes 

149 :param q: a :py:data:`.crypto_core_ed25519_BYTES` long bytes sequence 

150 representing a point on the edwards25519 curve 

151 :type q: bytes 

152 :return: a point on the edwards25519 curve represented as 

153 a :py:data:`.crypto_core_ed25519_BYTES` long bytes sequence 

154 :rtype: bytes 

155 :raises nacl.exceptions.UnavailableError: If called when using a 

156 minimal build of libsodium. 

157 """ 

158 ensure( 

159 has_crypto_core_ed25519, 

160 "Not available in minimal build", 

161 raising=exc.UnavailableError, 

162 ) 

163 

164 ensure( 

165 isinstance(p, bytes) 

166 and isinstance(q, bytes) 

167 and len(p) == crypto_core_ed25519_BYTES 

168 and len(q) == crypto_core_ed25519_BYTES, 

169 "Each point must be a {} long bytes sequence".format( 

170 "crypto_core_ed25519_BYTES" 

171 ), 

172 raising=exc.TypeError, 

173 ) 

174 

175 r = ffi.new("unsigned char[]", crypto_core_ed25519_BYTES) 

176 

177 rc = lib.crypto_core_ed25519_sub(r, p, q) 

178 ensure(rc == 0, "Unexpected library error", raising=exc.RuntimeError) 

179 

180 return ffi.buffer(r, crypto_core_ed25519_BYTES)[:] 

181 

182 

183def crypto_core_ed25519_scalar_invert(s: bytes) -> bytes: 

184 """ 

185 Return the multiplicative inverse of integer ``s`` modulo ``L``, 

186 i.e an integer ``i`` such that ``s * i = 1 (mod L)``, where ``L`` 

187 is the order of the main subgroup. 

188 

189 Raises a ``exc.RuntimeError`` if ``s`` is the integer zero. 

190 

191 :param s: a :py:data:`.crypto_core_ed25519_SCALARBYTES` 

192 long bytes sequence representing an integer 

193 :type s: bytes 

194 :return: an integer represented as a 

195 :py:data:`.crypto_core_ed25519_SCALARBYTES` long bytes sequence 

196 :rtype: bytes 

197 :raises nacl.exceptions.UnavailableError: If called when using a 

198 minimal build of libsodium. 

199 """ 

200 ensure( 

201 has_crypto_core_ed25519, 

202 "Not available in minimal build", 

203 raising=exc.UnavailableError, 

204 ) 

205 

206 ensure( 

207 isinstance(s, bytes) and len(s) == crypto_core_ed25519_SCALARBYTES, 

208 "Integer s must be a {} long bytes sequence".format( 

209 "crypto_core_ed25519_SCALARBYTES" 

210 ), 

211 raising=exc.TypeError, 

212 ) 

213 

214 r = ffi.new("unsigned char[]", crypto_core_ed25519_SCALARBYTES) 

215 

216 rc = lib.crypto_core_ed25519_scalar_invert(r, s) 

217 ensure(rc == 0, "Unexpected library error", raising=exc.RuntimeError) 

218 

219 return ffi.buffer(r, crypto_core_ed25519_SCALARBYTES)[:] 

220 

221 

222def crypto_core_ed25519_scalar_negate(s: bytes) -> bytes: 

223 """ 

224 Return the integer ``n`` such that ``s + n = 0 (mod L)``, where ``L`` 

225 is the order of the main subgroup. 

226 

227 :param s: a :py:data:`.crypto_core_ed25519_SCALARBYTES` 

228 long bytes sequence representing an integer 

229 :type s: bytes 

230 :return: an integer represented as a 

231 :py:data:`.crypto_core_ed25519_SCALARBYTES` long bytes sequence 

232 :rtype: bytes 

233 :raises nacl.exceptions.UnavailableError: If called when using a 

234 minimal build of libsodium. 

235 """ 

236 ensure( 

237 has_crypto_core_ed25519, 

238 "Not available in minimal build", 

239 raising=exc.UnavailableError, 

240 ) 

241 

242 ensure( 

243 isinstance(s, bytes) and len(s) == crypto_core_ed25519_SCALARBYTES, 

244 "Integer s must be a {} long bytes sequence".format( 

245 "crypto_core_ed25519_SCALARBYTES" 

246 ), 

247 raising=exc.TypeError, 

248 ) 

249 

250 r = ffi.new("unsigned char[]", crypto_core_ed25519_SCALARBYTES) 

251 

252 lib.crypto_core_ed25519_scalar_negate(r, s) 

253 

254 return ffi.buffer(r, crypto_core_ed25519_SCALARBYTES)[:] 

255 

256 

257def crypto_core_ed25519_scalar_complement(s: bytes) -> bytes: 

258 """ 

259 Return the complement of integer ``s`` modulo ``L``, i.e. an integer 

260 ``c`` such that ``s + c = 1 (mod L)``, where ``L`` is the order of 

261 the main subgroup. 

262 

263 :param s: a :py:data:`.crypto_core_ed25519_SCALARBYTES` 

264 long bytes sequence representing an integer 

265 :type s: bytes 

266 :return: an integer represented as a 

267 :py:data:`.crypto_core_ed25519_SCALARBYTES` long bytes sequence 

268 :rtype: bytes 

269 :raises nacl.exceptions.UnavailableError: If called when using a 

270 minimal build of libsodium. 

271 """ 

272 ensure( 

273 has_crypto_core_ed25519, 

274 "Not available in minimal build", 

275 raising=exc.UnavailableError, 

276 ) 

277 

278 ensure( 

279 isinstance(s, bytes) and len(s) == crypto_core_ed25519_SCALARBYTES, 

280 "Integer s must be a {} long bytes sequence".format( 

281 "crypto_core_ed25519_SCALARBYTES" 

282 ), 

283 raising=exc.TypeError, 

284 ) 

285 

286 r = ffi.new("unsigned char[]", crypto_core_ed25519_SCALARBYTES) 

287 

288 lib.crypto_core_ed25519_scalar_complement(r, s) 

289 

290 return ffi.buffer(r, crypto_core_ed25519_SCALARBYTES)[:] 

291 

292 

293def crypto_core_ed25519_scalar_add(p: bytes, q: bytes) -> bytes: 

294 """ 

295 Add integers ``p`` and ``q`` modulo ``L``, where ``L`` is the order of 

296 the main subgroup. 

297 

298 :param p: a :py:data:`.crypto_core_ed25519_SCALARBYTES` 

299 long bytes sequence representing an integer 

300 :type p: bytes 

301 :param q: a :py:data:`.crypto_core_ed25519_SCALARBYTES` 

302 long bytes sequence representing an integer 

303 :type q: bytes 

304 :return: an integer represented as a 

305 :py:data:`.crypto_core_ed25519_SCALARBYTES` long bytes sequence 

306 :rtype: bytes 

307 :raises nacl.exceptions.UnavailableError: If called when using a 

308 minimal build of libsodium. 

309 """ 

310 ensure( 

311 has_crypto_core_ed25519, 

312 "Not available in minimal build", 

313 raising=exc.UnavailableError, 

314 ) 

315 

316 ensure( 

317 isinstance(p, bytes) 

318 and isinstance(q, bytes) 

319 and len(p) == crypto_core_ed25519_SCALARBYTES 

320 and len(q) == crypto_core_ed25519_SCALARBYTES, 

321 "Each integer must be a {} long bytes sequence".format( 

322 "crypto_core_ed25519_SCALARBYTES" 

323 ), 

324 raising=exc.TypeError, 

325 ) 

326 

327 r = ffi.new("unsigned char[]", crypto_core_ed25519_SCALARBYTES) 

328 

329 lib.crypto_core_ed25519_scalar_add(r, p, q) 

330 

331 return ffi.buffer(r, crypto_core_ed25519_SCALARBYTES)[:] 

332 

333 

334def crypto_core_ed25519_scalar_sub(p: bytes, q: bytes) -> bytes: 

335 """ 

336 Subtract integers ``p`` and ``q`` modulo ``L``, where ``L`` is the 

337 order of the main subgroup. 

338 

339 :param p: a :py:data:`.crypto_core_ed25519_SCALARBYTES` 

340 long bytes sequence representing an integer 

341 :type p: bytes 

342 :param q: a :py:data:`.crypto_core_ed25519_SCALARBYTES` 

343 long bytes sequence representing an integer 

344 :type q: bytes 

345 :return: an integer represented as a 

346 :py:data:`.crypto_core_ed25519_SCALARBYTES` long bytes sequence 

347 :rtype: bytes 

348 :raises nacl.exceptions.UnavailableError: If called when using a 

349 minimal build of libsodium. 

350 """ 

351 ensure( 

352 has_crypto_core_ed25519, 

353 "Not available in minimal build", 

354 raising=exc.UnavailableError, 

355 ) 

356 

357 ensure( 

358 isinstance(p, bytes) 

359 and isinstance(q, bytes) 

360 and len(p) == crypto_core_ed25519_SCALARBYTES 

361 and len(q) == crypto_core_ed25519_SCALARBYTES, 

362 "Each integer must be a {} long bytes sequence".format( 

363 "crypto_core_ed25519_SCALARBYTES" 

364 ), 

365 raising=exc.TypeError, 

366 ) 

367 

368 r = ffi.new("unsigned char[]", crypto_core_ed25519_SCALARBYTES) 

369 

370 lib.crypto_core_ed25519_scalar_sub(r, p, q) 

371 

372 return ffi.buffer(r, crypto_core_ed25519_SCALARBYTES)[:] 

373 

374 

375def crypto_core_ed25519_scalar_mul(p: bytes, q: bytes) -> bytes: 

376 """ 

377 Multiply integers ``p`` and ``q`` modulo ``L``, where ``L`` is the 

378 order of the main subgroup. 

379 

380 :param p: a :py:data:`.crypto_core_ed25519_SCALARBYTES` 

381 long bytes sequence representing an integer 

382 :type p: bytes 

383 :param q: a :py:data:`.crypto_core_ed25519_SCALARBYTES` 

384 long bytes sequence representing an integer 

385 :type q: bytes 

386 :return: an integer represented as a 

387 :py:data:`.crypto_core_ed25519_SCALARBYTES` long bytes sequence 

388 :rtype: bytes 

389 :raises nacl.exceptions.UnavailableError: If called when using a 

390 minimal build of libsodium. 

391 """ 

392 ensure( 

393 has_crypto_core_ed25519, 

394 "Not available in minimal build", 

395 raising=exc.UnavailableError, 

396 ) 

397 

398 ensure( 

399 isinstance(p, bytes) 

400 and isinstance(q, bytes) 

401 and len(p) == crypto_core_ed25519_SCALARBYTES 

402 and len(q) == crypto_core_ed25519_SCALARBYTES, 

403 "Each integer must be a {} long bytes sequence".format( 

404 "crypto_core_ed25519_SCALARBYTES" 

405 ), 

406 raising=exc.TypeError, 

407 ) 

408 

409 r = ffi.new("unsigned char[]", crypto_core_ed25519_SCALARBYTES) 

410 

411 lib.crypto_core_ed25519_scalar_mul(r, p, q) 

412 

413 return ffi.buffer(r, crypto_core_ed25519_SCALARBYTES)[:] 

414 

415 

416def crypto_core_ed25519_scalar_reduce(s: bytes) -> bytes: 

417 """ 

418 Reduce integer ``s`` to ``s`` modulo ``L``, where ``L`` is the order 

419 of the main subgroup. 

420 

421 :param s: a :py:data:`.crypto_core_ed25519_NONREDUCEDSCALARBYTES` 

422 long bytes sequence representing an integer 

423 :type s: bytes 

424 :return: an integer represented as a 

425 :py:data:`.crypto_core_ed25519_SCALARBYTES` long bytes sequence 

426 :rtype: bytes 

427 :raises nacl.exceptions.UnavailableError: If called when using a 

428 minimal build of libsodium. 

429 """ 

430 ensure( 

431 has_crypto_core_ed25519, 

432 "Not available in minimal build", 

433 raising=exc.UnavailableError, 

434 ) 

435 

436 ensure( 

437 isinstance(s, bytes) 

438 and len(s) == crypto_core_ed25519_NONREDUCEDSCALARBYTES, 

439 "Integer s must be a {} long bytes sequence".format( 

440 "crypto_core_ed25519_NONREDUCEDSCALARBYTES" 

441 ), 

442 raising=exc.TypeError, 

443 ) 

444 

445 r = ffi.new("unsigned char[]", crypto_core_ed25519_SCALARBYTES) 

446 

447 lib.crypto_core_ed25519_scalar_reduce(r, s) 

448 

449 return ffi.buffer(r, crypto_core_ed25519_SCALARBYTES)[:]