Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/PyNaCl-1.6.2-py3.11-linux-x86_64.egg/nacl/bindings/crypto_core.py: 27%

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

81 statements  

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 

20has_crypto_core_ed25519 = bool(lib.PYNACL_HAS_CRYPTO_CORE_ED25519) 

21 

22crypto_core_ed25519_BYTES = 0 

23crypto_core_ed25519_SCALARBYTES = 0 

24crypto_core_ed25519_NONREDUCEDSCALARBYTES = 0 

25 

26if has_crypto_core_ed25519: 

27 crypto_core_ed25519_BYTES = lib.crypto_core_ed25519_bytes() 

28 crypto_core_ed25519_SCALARBYTES = lib.crypto_core_ed25519_scalarbytes() 

29 crypto_core_ed25519_NONREDUCEDSCALARBYTES = ( 

30 lib.crypto_core_ed25519_nonreducedscalarbytes() 

31 ) 

32 

33 

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

35 """ 

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

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

38 

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

40 representing a point on the edwards25519 curve 

41 :type p: bytes 

42 :return: point validity 

43 :rtype: bool 

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

45 minimal build of libsodium. 

46 """ 

47 ensure( 

48 has_crypto_core_ed25519, 

49 "Not available in minimal build", 

50 raising=exc.UnavailableError, 

51 ) 

52 

53 ensure( 

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

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

56 raising=exc.TypeError, 

57 ) 

58 

59 rc = lib.crypto_core_ed25519_is_valid_point(p) 

60 return rc == 1 

61 

62 

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

64 """ 

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

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

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

68 

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

70 sequence representing arbitrary data 

71 :type r: bytes 

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

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

74 :rtype: bytes 

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

76 minimal build of libsodium. 

77 """ 

78 ensure( 

79 has_crypto_core_ed25519, 

80 "Not available in minimal build", 

81 raising=exc.UnavailableError, 

82 ) 

83 

84 ensure( 

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

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

87 "crypto_core_ed25519_BYTES" 

88 ), 

89 raising=exc.TypeError, 

90 ) 

91 

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

93 

94 rc = lib.crypto_core_ed25519_from_uniform(p, r) 

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

96 

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

98 

99 

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

101 """ 

102 Add two points on the edwards25519 curve. 

103 

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

105 representing a point on the edwards25519 curve 

106 :type p: bytes 

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

108 representing a point on the edwards25519 curve 

109 :type q: bytes 

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

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

112 :rtype: bytes 

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

114 minimal build of libsodium. 

115 """ 

116 ensure( 

117 has_crypto_core_ed25519, 

118 "Not available in minimal build", 

119 raising=exc.UnavailableError, 

120 ) 

121 

122 ensure( 

123 isinstance(p, bytes) 

124 and isinstance(q, bytes) 

125 and len(p) == crypto_core_ed25519_BYTES 

126 and len(q) == crypto_core_ed25519_BYTES, 

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

128 "crypto_core_ed25519_BYTES" 

129 ), 

130 raising=exc.TypeError, 

131 ) 

132 

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

134 

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

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

137 

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

139 

140 

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

142 """ 

143 Subtract a point from another on the edwards25519 curve. 

144 

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

146 representing a point on the edwards25519 curve 

147 :type p: bytes 

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

149 representing a point on the edwards25519 curve 

150 :type q: bytes 

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

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

153 :rtype: bytes 

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

155 minimal build of libsodium. 

156 """ 

157 ensure( 

158 has_crypto_core_ed25519, 

159 "Not available in minimal build", 

160 raising=exc.UnavailableError, 

161 ) 

162 

163 ensure( 

164 isinstance(p, bytes) 

165 and isinstance(q, bytes) 

166 and len(p) == crypto_core_ed25519_BYTES 

167 and len(q) == crypto_core_ed25519_BYTES, 

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

169 "crypto_core_ed25519_BYTES" 

170 ), 

171 raising=exc.TypeError, 

172 ) 

173 

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

175 

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

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

178 

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

180 

181 

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

183 """ 

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

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

186 is the order of the main subgroup. 

187 

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

189 

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

191 long bytes sequence representing an integer 

192 :type s: bytes 

193 :return: an integer represented as a 

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

195 :rtype: bytes 

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

197 minimal build of libsodium. 

198 """ 

199 ensure( 

200 has_crypto_core_ed25519, 

201 "Not available in minimal build", 

202 raising=exc.UnavailableError, 

203 ) 

204 

205 ensure( 

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

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

208 "crypto_core_ed25519_SCALARBYTES" 

209 ), 

210 raising=exc.TypeError, 

211 ) 

212 

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

214 

215 rc = lib.crypto_core_ed25519_scalar_invert(r, s) 

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

217 

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

219 

220 

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

222 """ 

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

224 is the order of the main subgroup. 

225 

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

227 long bytes sequence representing an integer 

228 :type s: bytes 

229 :return: an integer represented as a 

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

231 :rtype: bytes 

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

233 minimal build of libsodium. 

234 """ 

235 ensure( 

236 has_crypto_core_ed25519, 

237 "Not available in minimal build", 

238 raising=exc.UnavailableError, 

239 ) 

240 

241 ensure( 

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

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

244 "crypto_core_ed25519_SCALARBYTES" 

245 ), 

246 raising=exc.TypeError, 

247 ) 

248 

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

250 

251 lib.crypto_core_ed25519_scalar_negate(r, s) 

252 

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

254 

255 

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

257 """ 

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

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

260 the main subgroup. 

261 

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

263 long bytes sequence representing an integer 

264 :type s: bytes 

265 :return: an integer represented as a 

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

267 :rtype: bytes 

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

269 minimal build of libsodium. 

270 """ 

271 ensure( 

272 has_crypto_core_ed25519, 

273 "Not available in minimal build", 

274 raising=exc.UnavailableError, 

275 ) 

276 

277 ensure( 

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

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

280 "crypto_core_ed25519_SCALARBYTES" 

281 ), 

282 raising=exc.TypeError, 

283 ) 

284 

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

286 

287 lib.crypto_core_ed25519_scalar_complement(r, s) 

288 

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

290 

291 

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

293 """ 

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

295 the main subgroup. 

296 

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

298 long bytes sequence representing an integer 

299 :type p: bytes 

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

301 long bytes sequence representing an integer 

302 :type q: bytes 

303 :return: an integer represented as a 

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

305 :rtype: bytes 

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

307 minimal build of libsodium. 

308 """ 

309 ensure( 

310 has_crypto_core_ed25519, 

311 "Not available in minimal build", 

312 raising=exc.UnavailableError, 

313 ) 

314 

315 ensure( 

316 isinstance(p, bytes) 

317 and isinstance(q, bytes) 

318 and len(p) == crypto_core_ed25519_SCALARBYTES 

319 and len(q) == crypto_core_ed25519_SCALARBYTES, 

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

321 "crypto_core_ed25519_SCALARBYTES" 

322 ), 

323 raising=exc.TypeError, 

324 ) 

325 

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

327 

328 lib.crypto_core_ed25519_scalar_add(r, p, q) 

329 

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

331 

332 

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

334 """ 

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

336 order of the main subgroup. 

337 

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

339 long bytes sequence representing an integer 

340 :type p: bytes 

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

342 long bytes sequence representing an integer 

343 :type q: bytes 

344 :return: an integer represented as a 

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

346 :rtype: bytes 

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

348 minimal build of libsodium. 

349 """ 

350 ensure( 

351 has_crypto_core_ed25519, 

352 "Not available in minimal build", 

353 raising=exc.UnavailableError, 

354 ) 

355 

356 ensure( 

357 isinstance(p, bytes) 

358 and isinstance(q, bytes) 

359 and len(p) == crypto_core_ed25519_SCALARBYTES 

360 and len(q) == crypto_core_ed25519_SCALARBYTES, 

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

362 "crypto_core_ed25519_SCALARBYTES" 

363 ), 

364 raising=exc.TypeError, 

365 ) 

366 

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

368 

369 lib.crypto_core_ed25519_scalar_sub(r, p, q) 

370 

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

372 

373 

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

375 """ 

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

377 order of the main subgroup. 

378 

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

380 long bytes sequence representing an integer 

381 :type p: bytes 

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

383 long bytes sequence representing an integer 

384 :type q: bytes 

385 :return: an integer represented as a 

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

387 :rtype: bytes 

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

389 minimal build of libsodium. 

390 """ 

391 ensure( 

392 has_crypto_core_ed25519, 

393 "Not available in minimal build", 

394 raising=exc.UnavailableError, 

395 ) 

396 

397 ensure( 

398 isinstance(p, bytes) 

399 and isinstance(q, bytes) 

400 and len(p) == crypto_core_ed25519_SCALARBYTES 

401 and len(q) == crypto_core_ed25519_SCALARBYTES, 

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

403 "crypto_core_ed25519_SCALARBYTES" 

404 ), 

405 raising=exc.TypeError, 

406 ) 

407 

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

409 

410 lib.crypto_core_ed25519_scalar_mul(r, p, q) 

411 

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

413 

414 

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

416 """ 

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

418 of the main subgroup. 

419 

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

421 long bytes sequence representing an integer 

422 :type s: bytes 

423 :return: an integer represented as a 

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

425 :rtype: bytes 

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

427 minimal build of libsodium. 

428 """ 

429 ensure( 

430 has_crypto_core_ed25519, 

431 "Not available in minimal build", 

432 raising=exc.UnavailableError, 

433 ) 

434 

435 ensure( 

436 isinstance(s, bytes) 

437 and len(s) == crypto_core_ed25519_NONREDUCEDSCALARBYTES, 

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

439 "crypto_core_ed25519_NONREDUCEDSCALARBYTES" 

440 ), 

441 raising=exc.TypeError, 

442 ) 

443 

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

445 

446 lib.crypto_core_ed25519_scalar_reduce(r, s) 

447 

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