Skip to content

Commit 51625ae

Browse files
committed
Add authenticated encrypion beginnings
Get the constants put in place for Crypto box features Add the public and secret key generator functions for the crypto_box functions Add crypto_box_easy Add crypto_box_open_easy
1 parent ad26f5c commit 51625ae

File tree

6 files changed

+360
-0
lines changed

6 files changed

+360
-0
lines changed

Changes

+13
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,19 @@
11
Change history for Sodium-FFI
22

33
{{$NEXT}}
4+
- Added crypto_box_easy
5+
- Added crypto_box_keypair
6+
- Added crypto_box_open_easy
7+
- Added crypto_box_seed_keypair
8+
- Added crypto_scalarmult_base
9+
- Added constants:
10+
crypto_box_SEALBYTES
11+
crypto_box_PUBLICKEYBYTES
12+
crypto_box_SECRETKEYBYTES
13+
crypto_box_MACBYTES
14+
crypto_box_NONCEBYTES
15+
crypto_box_SEEDBYTES
16+
crypto_box_BEFORENMBYTES
417

518
0.006 2022-03-06
619
- Added crypto_sign_keypair

README.md

+73
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,79 @@ my $key = randombytes_buf(crypto_aead_chacha20poly1305_IETF_KEYBYTES);
323323
The [crypto\_aead\_chacha20poly1305\_ietf\_keygen](https://doc.libsodium.org/secret-key_cryptography/aead/chacha20-poly1305/ietf_chacha20-poly1305_construction#detached-mode)
324324
function returns a byte string of `crypto_aead_chacha20poly1305_IETF_KEYBYTES` bytes.
325325

326+
# Public Key Cryptography - Crypto Boxes
327+
328+
LibSodium provides a few
329+
[Public Key Authenticated Encryption](https://doc.libsodium.org/public-key_cryptography/authenticated_encryption)
330+
and
331+
[Sealed Box Encryption](https://doc.libsodium.org/public-key_cryptography/sealed_boxes)
332+
functions to allow sending messages using authenticated encryption.
333+
334+
## crypto\_box\_easy
335+
336+
```perl
337+
use Sodium::FFI qw(crypto_box_keypair crypto_box_easy randombytes_buf crypto_box_NONCEBYTES);
338+
my $nonce = randombytes_buf(crypto_box_NONCEBYTES);
339+
my ($public_key, $secret_key) = crypto_box_keypair();
340+
my $msg = "test";
341+
my $cipher_text = crypto_box_easy($msg, $nonce, $public_key, $secret_key);
342+
```
343+
344+
The [crypto\_box\_easy](https://doc.libsodium.org/public-key_cryptography/authenticated_encryption#combined-mode)
345+
function encrypts a message using the recipient's public key, the sender's secret key, and a nonce.
346+
347+
## crypto\_box\_keypair
348+
349+
```perl
350+
use Sodium::FFI qw(crypto_box_keypair);
351+
my ($public_key, $secret_key) = crypto_box_keypair();
352+
```
353+
354+
The [crypto\_box\_keypair](https://doc.libsodium.org/public-key_cryptography/authenticated_encryption#key-pair-generation)
355+
function randomly generates a secret key and a corresponding public key.
356+
357+
## crypto\_box\_open\_easy
358+
359+
```perl
360+
use Sodium::FFI qw(crypto_box_keypair crypto_box_easy crypto_box_open_easy randombytes_buf crypto_box_NONCEBYTES);
361+
my $nonce = randombytes_buf(crypto_box_NONCEBYTES);
362+
my ($public_key, $secret_key) = crypto_box_keypair();
363+
my $msg = "test";
364+
my $cipher_text = crypto_box_easy($msg, $nonce, $public_key, $secret_key);
365+
my $decrypted = crypto_box_open_easy($cipher_text, $nonce, $public_key, $secret_key);
366+
if ($decrypted eq $msg) {
367+
say "Yay!";
368+
}
369+
```
370+
371+
The [crypto\_box\_open\_easy](https://doc.libsodium.org/public-key_cryptography/authenticated_encryption#combined-mode)
372+
function decrypts a cipher text produced by [crypto\_box\_easy](https://metacpan.org/pod/crypto_box_easy).
373+
374+
## crypto\_box\_seed\_keypair
375+
376+
```perl
377+
use Sodium::FFI qw(crypto_box_seed_keypair crypto_sign_SEEDBYTES randombytes_buf);
378+
my $seed = randombytes_buf(crypto_sign_SEEDBYTES);
379+
my ($public_key, $secret_key) = crypto_box_seed_keypair($seed);
380+
```
381+
382+
The [crypto\_box\_seed\_keypair](https://doc.libsodium.org/public-key_cryptography/authenticated_encryption#key-pair-generation)
383+
function randomly generates a secret key deterministically derived from a single key seed.
384+
385+
## crypto\_scalarmult\_base
386+
387+
```perl
388+
use Sodium::FFI qw(crypto_box_keypair crypto_scalarmult_base);
389+
my ($public_key, $secret_key) = crypto_box_keypair();
390+
my $computed_public = crypto_scalarmult_base($secret_key);
391+
if ($public_key eq $computed_public) {
392+
say "Yay!";
393+
}
394+
```
395+
396+
The [crypto\_scalarmult\_base](https://doc.libsodium.org/public-key_cryptography/authenticated_encryption#key-pair-generation)
397+
function can be used to compute the public key given a secret key previously generated with [crypto\_box\_keypair](https://metacpan.org/pod/crypto_box_keypair).
398+
326399
# Public Key Cryptography - Public Key Signatures
327400

328401
LibSodium provides a few

dist.ini

+1
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ stopword = unpadded
5858
stopword = Crypto
5959
stopword = GCM
6060
stopword = decrypt
61+
stopword = decrypts
6162
stopword = chacha
6263
stopword = Auth
6364
stopword = deterministically

ffi/ffi.c

+9
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,15 @@ ffi_pl_bundle_constant(const char* package, ffi_platypus_constant_t* c)
6565
_uint(crypto_sign_SECRETKEYBYTES);
6666
_uint(crypto_sign_BYTES);
6767
_uint(crypto_sign_SEEDBYTES);
68+
69+
/* crypto box */
70+
_uint(crypto_box_SEALBYTES);
71+
_uint(crypto_box_PUBLICKEYBYTES);
72+
_uint(crypto_box_SECRETKEYBYTES);
73+
_uint(crypto_box_MACBYTES);
74+
_uint(crypto_box_NONCEBYTES);
75+
_uint(crypto_box_SEEDBYTES);
76+
_uint(crypto_box_BEFORENMBYTES);
6877
}
6978

7079
void

lib/Sodium/FFI.pm

+191
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ push @EXPORT_OK, qw(
3434
crypto_aead_chacha20poly1305_IETF_KEYBYTES crypto_aead_chacha20poly1305_IETF_NPUBBYTES
3535
crypto_aead_chacha20poly1305_IETF_ABYTES
3636
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
3739
);
3840

3941
our $ffi;
@@ -401,6 +403,132 @@ our %function = (
401403
}
402404
],
403405

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+
404532
# int
405533
# crypto_sign_keypair(unsigned char *pk, unsigned char *sk);
406534
'crypto_sign_keypair' => [
@@ -1198,6 +1326,69 @@ as a string of bytes.
11981326
The L<crypto_aead_chacha20poly1305_ietf_keygen|https://doc.libsodium.org/secret-key_cryptography/aead/chacha20-poly1305/ietf_chacha20-poly1305_construction#detached-mode>
11991327
function returns a byte string of C<crypto_aead_chacha20poly1305_IETF_KEYBYTES> bytes.
12001328
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+
12011392
=head1 Public Key Cryptography - Public Key Signatures
12021393
12031394
LibSodium provides a few

0 commit comments

Comments
 (0)