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_aead.py: 21%

132 statements  

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

1# Copyright 2017 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. 

14from typing import Optional 

15 

16from nacl import exceptions as exc 

17from nacl._sodium import ffi, lib 

18from nacl.exceptions import ensure 

19 

20""" 

21Implementations of authenticated encription with associated data (*AEAD*) 

22constructions building on the chacha20 stream cipher and the poly1305 

23authenticator 

24""" 

25 

26crypto_aead_chacha20poly1305_ietf_KEYBYTES: int = ( 

27 lib.crypto_aead_chacha20poly1305_ietf_keybytes() 

28) 

29crypto_aead_chacha20poly1305_ietf_NSECBYTES: int = ( 

30 lib.crypto_aead_chacha20poly1305_ietf_nsecbytes() 

31) 

32crypto_aead_chacha20poly1305_ietf_NPUBBYTES: int = ( 

33 lib.crypto_aead_chacha20poly1305_ietf_npubbytes() 

34) 

35crypto_aead_chacha20poly1305_ietf_ABYTES: int = ( 

36 lib.crypto_aead_chacha20poly1305_ietf_abytes() 

37) 

38crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX: int = ( 

39 lib.crypto_aead_chacha20poly1305_ietf_messagebytes_max() 

40) 

41_aead_chacha20poly1305_ietf_CRYPTBYTES_MAX = ( 

42 crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX 

43 + crypto_aead_chacha20poly1305_ietf_ABYTES 

44) 

45 

46crypto_aead_chacha20poly1305_KEYBYTES: int = ( 

47 lib.crypto_aead_chacha20poly1305_keybytes() 

48) 

49crypto_aead_chacha20poly1305_NSECBYTES: int = ( 

50 lib.crypto_aead_chacha20poly1305_nsecbytes() 

51) 

52crypto_aead_chacha20poly1305_NPUBBYTES: int = ( 

53 lib.crypto_aead_chacha20poly1305_npubbytes() 

54) 

55crypto_aead_chacha20poly1305_ABYTES: int = ( 

56 lib.crypto_aead_chacha20poly1305_abytes() 

57) 

58crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX: int = ( 

59 lib.crypto_aead_chacha20poly1305_messagebytes_max() 

60) 

61_aead_chacha20poly1305_CRYPTBYTES_MAX = ( 

62 crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX 

63 + crypto_aead_chacha20poly1305_ABYTES 

64) 

65 

66crypto_aead_xchacha20poly1305_ietf_KEYBYTES: int = ( 

67 lib.crypto_aead_xchacha20poly1305_ietf_keybytes() 

68) 

69crypto_aead_xchacha20poly1305_ietf_NSECBYTES: int = ( 

70 lib.crypto_aead_xchacha20poly1305_ietf_nsecbytes() 

71) 

72crypto_aead_xchacha20poly1305_ietf_NPUBBYTES: int = ( 

73 lib.crypto_aead_xchacha20poly1305_ietf_npubbytes() 

74) 

75crypto_aead_xchacha20poly1305_ietf_ABYTES: int = ( 

76 lib.crypto_aead_xchacha20poly1305_ietf_abytes() 

77) 

78crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX: int = ( 

79 lib.crypto_aead_xchacha20poly1305_ietf_messagebytes_max() 

80) 

81_aead_xchacha20poly1305_ietf_CRYPTBYTES_MAX = ( 

82 crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX 

83 + crypto_aead_xchacha20poly1305_ietf_ABYTES 

84) 

85 

86 

87def crypto_aead_chacha20poly1305_ietf_encrypt( 

88 message: bytes, aad: Optional[bytes], nonce: bytes, key: bytes 

89) -> bytes: 

90 """ 

91 Encrypt the given ``message`` using the IETF ratified chacha20poly1305 

92 construction described in RFC7539. 

93 

94 :param message: 

95 :type message: bytes 

96 :param aad: 

97 :type aad: Optional[bytes] 

98 :param nonce: 

99 :type nonce: bytes 

100 :param key: 

101 :type key: bytes 

102 :return: authenticated ciphertext 

103 :rtype: bytes 

104 """ 

105 ensure( 

106 isinstance(message, bytes), 

107 "Input message type must be bytes", 

108 raising=exc.TypeError, 

109 ) 

110 

111 mlen = len(message) 

112 

113 ensure( 

114 mlen <= crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX, 

115 "Message must be at most {} bytes long".format( 

116 crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX 

117 ), 

118 raising=exc.ValueError, 

119 ) 

120 

121 ensure( 

122 isinstance(aad, bytes) or (aad is None), 

123 "Additional data must be bytes or None", 

124 raising=exc.TypeError, 

125 ) 

126 

127 ensure( 

128 isinstance(nonce, bytes) 

129 and len(nonce) == crypto_aead_chacha20poly1305_ietf_NPUBBYTES, 

130 "Nonce must be a {} bytes long bytes sequence".format( 

131 crypto_aead_chacha20poly1305_ietf_NPUBBYTES 

132 ), 

133 raising=exc.TypeError, 

134 ) 

135 

136 ensure( 

137 isinstance(key, bytes) 

138 and len(key) == crypto_aead_chacha20poly1305_ietf_KEYBYTES, 

139 "Key must be a {} bytes long bytes sequence".format( 

140 crypto_aead_chacha20poly1305_ietf_KEYBYTES 

141 ), 

142 raising=exc.TypeError, 

143 ) 

144 

145 if aad: 

146 _aad = aad 

147 aalen = len(aad) 

148 else: 

149 _aad = ffi.NULL 

150 aalen = 0 

151 

152 mxout = mlen + crypto_aead_chacha20poly1305_ietf_ABYTES 

153 

154 clen = ffi.new("unsigned long long *") 

155 

156 ciphertext = ffi.new("unsigned char[]", mxout) 

157 

158 res = lib.crypto_aead_chacha20poly1305_ietf_encrypt( 

159 ciphertext, clen, message, mlen, _aad, aalen, ffi.NULL, nonce, key 

160 ) 

161 

162 ensure(res == 0, "Encryption failed.", raising=exc.CryptoError) 

163 return ffi.buffer(ciphertext, clen[0])[:] 

164 

165 

166def crypto_aead_chacha20poly1305_ietf_decrypt( 

167 ciphertext: bytes, aad: Optional[bytes], nonce: bytes, key: bytes 

168) -> bytes: 

169 """ 

170 Decrypt the given ``ciphertext`` using the IETF ratified chacha20poly1305 

171 construction described in RFC7539. 

172 

173 :param ciphertext: 

174 :type ciphertext: bytes 

175 :param aad: 

176 :type aad: Optional[bytes] 

177 :param nonce: 

178 :type nonce: bytes 

179 :param key: 

180 :type key: bytes 

181 :return: message 

182 :rtype: bytes 

183 """ 

184 ensure( 

185 isinstance(ciphertext, bytes), 

186 "Input ciphertext type must be bytes", 

187 raising=exc.TypeError, 

188 ) 

189 

190 clen = len(ciphertext) 

191 

192 ensure( 

193 clen <= _aead_chacha20poly1305_ietf_CRYPTBYTES_MAX, 

194 "Ciphertext must be at most {} bytes long".format( 

195 _aead_chacha20poly1305_ietf_CRYPTBYTES_MAX 

196 ), 

197 raising=exc.ValueError, 

198 ) 

199 

200 ensure( 

201 isinstance(aad, bytes) or (aad is None), 

202 "Additional data must be bytes or None", 

203 raising=exc.TypeError, 

204 ) 

205 

206 ensure( 

207 isinstance(nonce, bytes) 

208 and len(nonce) == crypto_aead_chacha20poly1305_ietf_NPUBBYTES, 

209 "Nonce must be a {} bytes long bytes sequence".format( 

210 crypto_aead_chacha20poly1305_ietf_NPUBBYTES 

211 ), 

212 raising=exc.TypeError, 

213 ) 

214 

215 ensure( 

216 isinstance(key, bytes) 

217 and len(key) == crypto_aead_chacha20poly1305_ietf_KEYBYTES, 

218 "Key must be a {} bytes long bytes sequence".format( 

219 crypto_aead_chacha20poly1305_ietf_KEYBYTES 

220 ), 

221 raising=exc.TypeError, 

222 ) 

223 

224 mxout = clen - crypto_aead_chacha20poly1305_ietf_ABYTES 

225 

226 mlen = ffi.new("unsigned long long *") 

227 message = ffi.new("unsigned char[]", mxout) 

228 

229 if aad: 

230 _aad = aad 

231 aalen = len(aad) 

232 else: 

233 _aad = ffi.NULL 

234 aalen = 0 

235 

236 res = lib.crypto_aead_chacha20poly1305_ietf_decrypt( 

237 message, mlen, ffi.NULL, ciphertext, clen, _aad, aalen, nonce, key 

238 ) 

239 

240 ensure(res == 0, "Decryption failed.", raising=exc.CryptoError) 

241 

242 return ffi.buffer(message, mlen[0])[:] 

243 

244 

245def crypto_aead_chacha20poly1305_encrypt( 

246 message: bytes, aad: Optional[bytes], nonce: bytes, key: bytes 

247) -> bytes: 

248 """ 

249 Encrypt the given ``message`` using the "legacy" construction 

250 described in draft-agl-tls-chacha20poly1305. 

251 

252 :param message: 

253 :type message: bytes 

254 :param aad: 

255 :type aad: Optional[bytes] 

256 :param nonce: 

257 :type nonce: bytes 

258 :param key: 

259 :type key: bytes 

260 :return: authenticated ciphertext 

261 :rtype: bytes 

262 """ 

263 ensure( 

264 isinstance(message, bytes), 

265 "Input message type must be bytes", 

266 raising=exc.TypeError, 

267 ) 

268 

269 mlen = len(message) 

270 

271 ensure( 

272 mlen <= crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX, 

273 "Message must be at most {} bytes long".format( 

274 crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX 

275 ), 

276 raising=exc.ValueError, 

277 ) 

278 

279 ensure( 

280 isinstance(aad, bytes) or (aad is None), 

281 "Additional data must be bytes or None", 

282 raising=exc.TypeError, 

283 ) 

284 

285 ensure( 

286 isinstance(nonce, bytes) 

287 and len(nonce) == crypto_aead_chacha20poly1305_NPUBBYTES, 

288 "Nonce must be a {} bytes long bytes sequence".format( 

289 crypto_aead_chacha20poly1305_NPUBBYTES 

290 ), 

291 raising=exc.TypeError, 

292 ) 

293 

294 ensure( 

295 isinstance(key, bytes) 

296 and len(key) == crypto_aead_chacha20poly1305_KEYBYTES, 

297 "Key must be a {} bytes long bytes sequence".format( 

298 crypto_aead_chacha20poly1305_KEYBYTES 

299 ), 

300 raising=exc.TypeError, 

301 ) 

302 

303 if aad: 

304 _aad = aad 

305 aalen = len(aad) 

306 else: 

307 _aad = ffi.NULL 

308 aalen = 0 

309 

310 mlen = len(message) 

311 mxout = mlen + crypto_aead_chacha20poly1305_ietf_ABYTES 

312 

313 clen = ffi.new("unsigned long long *") 

314 

315 ciphertext = ffi.new("unsigned char[]", mxout) 

316 

317 res = lib.crypto_aead_chacha20poly1305_encrypt( 

318 ciphertext, clen, message, mlen, _aad, aalen, ffi.NULL, nonce, key 

319 ) 

320 

321 ensure(res == 0, "Encryption failed.", raising=exc.CryptoError) 

322 return ffi.buffer(ciphertext, clen[0])[:] 

323 

324 

325def crypto_aead_chacha20poly1305_decrypt( 

326 ciphertext: bytes, aad: Optional[bytes], nonce: bytes, key: bytes 

327) -> bytes: 

328 """ 

329 Decrypt the given ``ciphertext`` using the "legacy" construction 

330 described in draft-agl-tls-chacha20poly1305. 

331 

332 :param ciphertext: authenticated ciphertext 

333 :type ciphertext: bytes 

334 :param aad: 

335 :type aad: Optional[bytes] 

336 :param nonce: 

337 :type nonce: bytes 

338 :param key: 

339 :type key: bytes 

340 :return: message 

341 :rtype: bytes 

342 """ 

343 ensure( 

344 isinstance(ciphertext, bytes), 

345 "Input ciphertext type must be bytes", 

346 raising=exc.TypeError, 

347 ) 

348 

349 clen = len(ciphertext) 

350 

351 ensure( 

352 clen <= _aead_chacha20poly1305_CRYPTBYTES_MAX, 

353 "Ciphertext must be at most {} bytes long".format( 

354 _aead_chacha20poly1305_CRYPTBYTES_MAX 

355 ), 

356 raising=exc.ValueError, 

357 ) 

358 

359 ensure( 

360 isinstance(aad, bytes) or (aad is None), 

361 "Additional data must be bytes or None", 

362 raising=exc.TypeError, 

363 ) 

364 

365 ensure( 

366 isinstance(nonce, bytes) 

367 and len(nonce) == crypto_aead_chacha20poly1305_NPUBBYTES, 

368 "Nonce must be a {} bytes long bytes sequence".format( 

369 crypto_aead_chacha20poly1305_NPUBBYTES 

370 ), 

371 raising=exc.TypeError, 

372 ) 

373 

374 ensure( 

375 isinstance(key, bytes) 

376 and len(key) == crypto_aead_chacha20poly1305_KEYBYTES, 

377 "Key must be a {} bytes long bytes sequence".format( 

378 crypto_aead_chacha20poly1305_KEYBYTES 

379 ), 

380 raising=exc.TypeError, 

381 ) 

382 

383 mxout = clen - crypto_aead_chacha20poly1305_ABYTES 

384 

385 mlen = ffi.new("unsigned long long *") 

386 message = ffi.new("unsigned char[]", mxout) 

387 

388 if aad: 

389 _aad = aad 

390 aalen = len(aad) 

391 else: 

392 _aad = ffi.NULL 

393 aalen = 0 

394 

395 res = lib.crypto_aead_chacha20poly1305_decrypt( 

396 message, mlen, ffi.NULL, ciphertext, clen, _aad, aalen, nonce, key 

397 ) 

398 

399 ensure(res == 0, "Decryption failed.", raising=exc.CryptoError) 

400 

401 return ffi.buffer(message, mlen[0])[:] 

402 

403 

404def crypto_aead_xchacha20poly1305_ietf_encrypt( 

405 message: bytes, aad: Optional[bytes], nonce: bytes, key: bytes 

406) -> bytes: 

407 """ 

408 Encrypt the given ``message`` using the long-nonces xchacha20poly1305 

409 construction. 

410 

411 :param message: 

412 :type message: bytes 

413 :param aad: 

414 :type aad: Optional[bytes] 

415 :param nonce: 

416 :type nonce: bytes 

417 :param key: 

418 :type key: bytes 

419 :return: authenticated ciphertext 

420 :rtype: bytes 

421 """ 

422 ensure( 

423 isinstance(message, bytes), 

424 "Input message type must be bytes", 

425 raising=exc.TypeError, 

426 ) 

427 

428 mlen = len(message) 

429 

430 ensure( 

431 mlen <= crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX, 

432 "Message must be at most {} bytes long".format( 

433 crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX 

434 ), 

435 raising=exc.ValueError, 

436 ) 

437 

438 ensure( 

439 isinstance(aad, bytes) or (aad is None), 

440 "Additional data must be bytes or None", 

441 raising=exc.TypeError, 

442 ) 

443 

444 ensure( 

445 isinstance(nonce, bytes) 

446 and len(nonce) == crypto_aead_xchacha20poly1305_ietf_NPUBBYTES, 

447 "Nonce must be a {} bytes long bytes sequence".format( 

448 crypto_aead_xchacha20poly1305_ietf_NPUBBYTES 

449 ), 

450 raising=exc.TypeError, 

451 ) 

452 

453 ensure( 

454 isinstance(key, bytes) 

455 and len(key) == crypto_aead_xchacha20poly1305_ietf_KEYBYTES, 

456 "Key must be a {} bytes long bytes sequence".format( 

457 crypto_aead_xchacha20poly1305_ietf_KEYBYTES 

458 ), 

459 raising=exc.TypeError, 

460 ) 

461 

462 if aad: 

463 _aad = aad 

464 aalen = len(aad) 

465 else: 

466 _aad = ffi.NULL 

467 aalen = 0 

468 

469 mlen = len(message) 

470 mxout = mlen + crypto_aead_xchacha20poly1305_ietf_ABYTES 

471 

472 clen = ffi.new("unsigned long long *") 

473 

474 ciphertext = ffi.new("unsigned char[]", mxout) 

475 

476 res = lib.crypto_aead_xchacha20poly1305_ietf_encrypt( 

477 ciphertext, clen, message, mlen, _aad, aalen, ffi.NULL, nonce, key 

478 ) 

479 

480 ensure(res == 0, "Encryption failed.", raising=exc.CryptoError) 

481 return ffi.buffer(ciphertext, clen[0])[:] 

482 

483 

484def crypto_aead_xchacha20poly1305_ietf_decrypt( 

485 ciphertext: bytes, aad: Optional[bytes], nonce: bytes, key: bytes 

486) -> bytes: 

487 """ 

488 Decrypt the given ``ciphertext`` using the long-nonces xchacha20poly1305 

489 construction. 

490 

491 :param ciphertext: authenticated ciphertext 

492 :type ciphertext: bytes 

493 :param aad: 

494 :type aad: Optional[bytes] 

495 :param nonce: 

496 :type nonce: bytes 

497 :param key: 

498 :type key: bytes 

499 :return: message 

500 :rtype: bytes 

501 """ 

502 ensure( 

503 isinstance(ciphertext, bytes), 

504 "Input ciphertext type must be bytes", 

505 raising=exc.TypeError, 

506 ) 

507 

508 clen = len(ciphertext) 

509 

510 ensure( 

511 clen <= _aead_xchacha20poly1305_ietf_CRYPTBYTES_MAX, 

512 "Ciphertext must be at most {} bytes long".format( 

513 _aead_xchacha20poly1305_ietf_CRYPTBYTES_MAX 

514 ), 

515 raising=exc.ValueError, 

516 ) 

517 

518 ensure( 

519 isinstance(aad, bytes) or (aad is None), 

520 "Additional data must be bytes or None", 

521 raising=exc.TypeError, 

522 ) 

523 

524 ensure( 

525 isinstance(nonce, bytes) 

526 and len(nonce) == crypto_aead_xchacha20poly1305_ietf_NPUBBYTES, 

527 "Nonce must be a {} bytes long bytes sequence".format( 

528 crypto_aead_xchacha20poly1305_ietf_NPUBBYTES 

529 ), 

530 raising=exc.TypeError, 

531 ) 

532 

533 ensure( 

534 isinstance(key, bytes) 

535 and len(key) == crypto_aead_xchacha20poly1305_ietf_KEYBYTES, 

536 "Key must be a {} bytes long bytes sequence".format( 

537 crypto_aead_xchacha20poly1305_ietf_KEYBYTES 

538 ), 

539 raising=exc.TypeError, 

540 ) 

541 

542 mxout = clen - crypto_aead_xchacha20poly1305_ietf_ABYTES 

543 mlen = ffi.new("unsigned long long *") 

544 message = ffi.new("unsigned char[]", mxout) 

545 

546 if aad: 

547 _aad = aad 

548 aalen = len(aad) 

549 else: 

550 _aad = ffi.NULL 

551 aalen = 0 

552 

553 res = lib.crypto_aead_xchacha20poly1305_ietf_decrypt( 

554 message, mlen, ffi.NULL, ciphertext, clen, _aad, aalen, nonce, key 

555 ) 

556 

557 ensure(res == 0, "Decryption failed.", raising=exc.CryptoError) 

558 

559 return ffi.buffer(message, mlen[0])[:]