@@ -34,6 +34,8 @@ push @EXPORT_OK, qw(
34
34
crypto_aead_chacha20poly1305_IETF_KEYBYTES crypto_aead_chacha20poly1305_IETF_NPUBBYTES
35
35
crypto_aead_chacha20poly1305_IETF_ABYTES
36
36
crypto_sign_SEEDBYTES crypto_sign_BYTES crypto_sign_SECRETKEYBYTES crypto_sign_PUBLICKEYBYTES
37
+ crypto_box_SEALBYTES crypto_box_PUBLICKEYBYTES crypto_box_SECRETKEYBYTES
38
+ crypto_box_MACBYTES crypto_box_NONCEBYTES crypto_box_SEEDBYTES crypto_box_BEFORENMBYTES
37
39
) ;
38
40
39
41
our $ffi ;
@@ -401,6 +403,132 @@ our %function = (
401
403
}
402
404
],
403
405
406
+ # int
407
+ # crypto_box_easy(unsigned char *c, const unsigned char *m,
408
+ # unsigned long long mlen, const unsigned char *n,
409
+ # const unsigned char *pk, const unsigned char *sk);
410
+ ' crypto_box_easy' => [
411
+ [' string' , ' string' , ' size_t' , ' string' , ' string' , ' string' ] => ' int' ,
412
+ sub {
413
+ my ($xsub , $msg , $nonce , $pk , $sk ) = @_ ;
414
+ my $msg_len = length ($msg );
415
+ my $nonce_len = length ($nonce );
416
+ my $pk_len = length ($pk );
417
+ my $sk_len = length ($sk );
418
+ my $SIZE_MAX = Sodium::FFI::SIZE_MAX;
419
+ if ($nonce_len != Sodium::FFI::crypto_box_NONCEBYTES) {
420
+ croak(" The nonce must be crypto_box_NONCEBYTES in length" );
421
+ }
422
+ if ($pk_len != Sodium::FFI::crypto_box_PUBLICKEYBYTES) {
423
+ croak(" The public key must be crypto_box_PUBLICKEYBYTES in length" );
424
+ }
425
+ if ($sk_len != Sodium::FFI::crypto_box_SECRETKEYBYTES) {
426
+ croak(" The secret key must be crypto_box_SECRETKEYBYTES in length" );
427
+ }
428
+ if ($SIZE_MAX - $msg_len <= Sodium::FFI::crypto_box_MACBYTES) {
429
+ croak(" Arithmetic overflow" );
430
+ }
431
+ my $cipher_len = Sodium::FFI::crypto_box_MACBYTES + $msg_len ;
432
+ my $cipher_text = " \0 " x $cipher_len ;
433
+ my $ret = $xsub -> ($cipher_text , $msg , $msg_len , $nonce , $pk , $sk );
434
+ if ($ret != 0) {
435
+ croak(" Some internal error happened" );
436
+ }
437
+ return $cipher_text ;
438
+ }
439
+ ],
440
+
441
+ # int
442
+ # crypto_box_keypair(unsigned char *pk, unsigned char *sk);
443
+ ' crypto_box_keypair' => [
444
+ [' string' , ' string' ] => ' int' ,
445
+ sub {
446
+ my ($xsub ) = @_ ;
447
+ my $pubkey = " \0 " x Sodium::FFI::crypto_box_PUBLICKEYBYTES ;
448
+ my $seckey = " \0 " x Sodium::FFI::crypto_box_SECRETKEYBYTES;
449
+ my $ret = $xsub -> ($pubkey , $seckey );
450
+ if ($ret != 0) {
451
+ croak(" Some internal error happened" );
452
+ }
453
+ return ($pubkey , $seckey );
454
+ }
455
+ ],
456
+
457
+ # int
458
+ # crypto_box_open_easy(unsigned char *m, const unsigned char *c,
459
+ # unsigned long long clen, const unsigned char *n,
460
+ # const unsigned char *pk, const unsigned char *sk);
461
+ ' crypto_box_open_easy' => [
462
+ [' string' , ' string' , ' size_t' , ' string' , ' string' , ' string' ] => ' int' ,
463
+ sub {
464
+ my ($xsub , $cipher_text , $nonce , $pk , $sk ) = @_ ;
465
+ my $cipher_len = length ($cipher_text );
466
+ my $nonce_len = length ($nonce );
467
+ my $pk_len = length ($pk );
468
+ my $sk_len = length ($sk );
469
+ my $SIZE_MAX = Sodium::FFI::SIZE_MAX;
470
+ if ($nonce_len != Sodium::FFI::crypto_box_NONCEBYTES) {
471
+ croak(" The nonce must be crypto_box_NONCEBYTES in length" );
472
+ }
473
+ if ($pk_len != Sodium::FFI::crypto_box_PUBLICKEYBYTES) {
474
+ croak(" The public key must be crypto_box_PUBLICKEYBYTES in length" );
475
+ }
476
+ if ($sk_len != Sodium::FFI::crypto_box_SECRETKEYBYTES) {
477
+ croak(" The secret key must be crypto_box_SECRETKEYBYTES in length" );
478
+ }
479
+ if ($cipher_len <= Sodium::FFI::crypto_box_MACBYTES) {
480
+ croak(" The cipher text should be larger than crypto_box_MACBYTES bytes" );
481
+ }
482
+
483
+ my $msg_len = $cipher_len - Sodium::FFI::crypto_box_MACBYTES;
484
+ my $msg = " \0 " x $msg_len ;
485
+ my $ret = $xsub -> ($msg , $cipher_text , $cipher_len , $nonce , $pk , $sk );
486
+ if ($ret != 0) {
487
+ croak(" Some internal error happened" );
488
+ }
489
+ return $msg ;
490
+ }
491
+ ],
492
+
493
+ # int
494
+ # crypto_box_seed_keypair(unsigned char *pk, unsigned char *sk, const unsigned char *seed);
495
+ ' crypto_box_seed_keypair' => [
496
+ [' string' , ' string' , ' string' ] => ' int' ,
497
+ sub {
498
+ my ($xsub , $seed ) = @_ ;
499
+ my $seed_len = length ($seed );
500
+ unless ($seed_len == Sodium::FFI::crypto_box_SEEDBYTES) {
501
+ croak(" Seed length must be crypto_box_SEEDBYTES in length" );
502
+ }
503
+ my $pubkey = " \0 " x Sodium::FFI::crypto_box_PUBLICKEYBYTES;
504
+ my $seckey = " \0 " x Sodium::FFI::crypto_box_SECRETKEYBYTES;
505
+ my $ret = $xsub -> ($pubkey , $seckey , $seed );
506
+ if ($ret != 0) {
507
+ croak(" Some internal error happened" );
508
+ }
509
+ return ($pubkey , $seckey );
510
+ }
511
+ ],
512
+
513
+ # int
514
+ # crypto_scalarmult_base(unsigned char *q, const unsigned char *n);
515
+ ' crypto_scalarmult_base' => [
516
+ [' string' , ' string' ] => ' int' ,
517
+ sub {
518
+ my ($xsub , $secret_key ) = @_ ;
519
+ my $sk_len = length ($secret_key );
520
+ unless ($sk_len == Sodium::FFI::crypto_box_SECRETKEYBYTES) {
521
+ croak(" Secret Key length must be crypto_box_SECRETKEYBYTES in length" );
522
+ }
523
+ my $pubkey = " \0 " x Sodium::FFI::crypto_box_PUBLICKEYBYTES;
524
+ my $ret = $xsub -> ($pubkey , $secret_key );
525
+ if ($ret != 0) {
526
+ croak(" Some internal error happened" );
527
+ }
528
+ return $pubkey ;
529
+ }
530
+ ],
531
+
404
532
# int
405
533
# crypto_sign_keypair(unsigned char *pk, unsigned char *sk);
406
534
' crypto_sign_keypair' => [
@@ -1198,6 +1326,69 @@ as a string of bytes.
1198
1326
The L<crypto_aead_chacha20poly1305_ietf_keygen|https://doc.libsodium.org/secret-key_cryptography/aead/chacha20-poly1305/ietf_chacha20-poly1305_construction#detached-mode>
1199
1327
function returns a byte string of C<crypto_aead_chacha20poly1305_IETF_KEYBYTES > bytes.
1200
1328
1329
+ =head1 Public Key Cryptography - Crypto Boxes
1330
+
1331
+ LibSodium provides a few
1332
+ L<Public Key Authenticated Encryption|https://doc.libsodium.org/public-key_cryptography/authenticated_encryption>
1333
+ and
1334
+ L<Sealed Box Encryption|https://doc.libsodium.org/public-key_cryptography/sealed_boxes>
1335
+ functions to allow sending messages using authenticated encryption.
1336
+
1337
+ =head2 crypto_box_easy
1338
+
1339
+ use Sodium::FFI qw(crypto_box_keypair crypto_box_easy randombytes_buf crypto_box_NONCEBYTES);
1340
+ my $nonce = randombytes_buf(crypto_box_NONCEBYTES);
1341
+ my ($public_key, $secret_key) = crypto_box_keypair();
1342
+ my $msg = "test";
1343
+ my $cipher_text = crypto_box_easy($msg, $nonce, $public_key, $secret_key);
1344
+
1345
+ The L<crypto_box_easy|https://doc.libsodium.org/public-key_cryptography/authenticated_encryption#combined-mode>
1346
+ function encrypts a message using the recipient's public key, the sender's secret key, and a nonce.
1347
+
1348
+ =head2 crypto_box_keypair
1349
+
1350
+ use Sodium::FFI qw(crypto_box_keypair);
1351
+ my ($public_key, $secret_key) = crypto_box_keypair();
1352
+
1353
+ The L<crypto_box_keypair|https://doc.libsodium.org/public-key_cryptography/authenticated_encryption#key-pair-generation>
1354
+ function randomly generates a secret key and a corresponding public key.
1355
+
1356
+ =head2 crypto_box_open_easy
1357
+
1358
+ use Sodium::FFI qw(crypto_box_keypair crypto_box_easy crypto_box_open_easy randombytes_buf crypto_box_NONCEBYTES);
1359
+ my $nonce = randombytes_buf(crypto_box_NONCEBYTES);
1360
+ my ($public_key, $secret_key) = crypto_box_keypair();
1361
+ my $msg = "test";
1362
+ my $cipher_text = crypto_box_easy($msg, $nonce, $public_key, $secret_key);
1363
+ my $decrypted = crypto_box_open_easy($cipher_text, $nonce, $public_key, $secret_key);
1364
+ if ($decrypted eq $msg) {
1365
+ say "Yay!";
1366
+ }
1367
+
1368
+ The L<crypto_box_open_easy|https://doc.libsodium.org/public-key_cryptography/authenticated_encryption#combined-mode>
1369
+ function decrypts a cipher text produced by L<crypto_box_easy> .
1370
+
1371
+ =head2 crypto_box_seed_keypair
1372
+
1373
+ use Sodium::FFI qw(crypto_box_seed_keypair crypto_sign_SEEDBYTES randombytes_buf);
1374
+ my $seed = randombytes_buf(crypto_sign_SEEDBYTES);
1375
+ my ($public_key, $secret_key) = crypto_box_seed_keypair($seed);
1376
+
1377
+ The L<crypto_box_seed_keypair|https://doc.libsodium.org/public-key_cryptography/authenticated_encryption#key-pair-generation>
1378
+ function randomly generates a secret key deterministically derived from a single key seed.
1379
+
1380
+ =head2 crypto_scalarmult_base
1381
+
1382
+ use Sodium::FFI qw(crypto_box_keypair crypto_scalarmult_base);
1383
+ my ($public_key, $secret_key) = crypto_box_keypair();
1384
+ my $computed_public = crypto_scalarmult_base($secret_key);
1385
+ if ($public_key eq $computed_public) {
1386
+ say "Yay!";
1387
+ }
1388
+
1389
+ The L<crypto_scalarmult_base|https://doc.libsodium.org/public-key_cryptography/authenticated_encryption#key-pair-generation>
1390
+ function can be used to compute the public key given a secret key previously generated with L<crypto_box_keypair> .
1391
+
1201
1392
=head1 Public Key Cryptography - Public Key Signatures
1202
1393
1203
1394
LibSodium provides a few
0 commit comments