The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Crypt::NaCl::Sodium::box - Public-key authenticated encryption (Curve25519/XSalsa20/Poly1305 MAC)

VERSION

version 1.0.8.0

SYNOPSIS

    use Crypt::NaCl::Sodium qw( :utils );

    my $crypto_box = Crypt::NaCl::Sodium->box();

    my ($a_skey, $a_pkey, $a_key, $b_skey,
        $b_pkey, $b_key,
        $a_precal_key, $b_precal_key,
        $nonce, $decrypted_msg, $msg, $secret);

    ## Alice
    ########

    # Alice generates secret keypair
    ($a_pkey, $a_skey) = $crypto_box->keypair();

    # ... and shares the public key with Bob
    send_to( Bob => { public_key => $a_pkey } );

    ## Bob
    ########

    # Bob generates his secret keypair
    ($b_pkey, $b_skey) = $crypto_box->keypair();

    # Bob receives the public key from Alice
    $a_key = receive_for( Bob => 'public_key' );

    # ... and shares his public key with Alice
    send_to( Alice => { public_key => $b_pkey } );

    # now Alice and Bob can start communicating

    ## Alice
    ########

    # Alice receives the public key from Bob
    $b_key = receive_for( Alice => 'public_key' );

    # Alice generates random nonce
    $nonce = $crypto_box->nonce();

    send_to( Bob => { nonce => $nonce } );

    # Alice's message to Bob
    $msg = "Hi Bob!";

    # encrypts using combined mode
    $secret = $crypto_box->encrypt( $msg, $nonce, $b_key, $a_skey );

    # message is ready for Bob
    send_to( Bob => { secret => $secret } );

    ## Bob
    ########

    # Bob receives the random nonce
    $nonce = receive_for( Bob => 'nonce' );

    # and is now ready to receive first message from Alice
    $secret = receive_for( Bob => 'secret' );

    # since Bob already has Alice's public key we have all information required to decrypt message
    $decrypted_msg = $crypto_box->decrypt( $secret, $nonce, $a_key, $b_skey );

    # Bob is going to send a lot of messages to Alice, so we speed up the
    # encryption and decryption by pre-calculating the shared key
    $b_precal_key = $crypto_box->beforenm( $a_key, $b_skey );

    # now it is time to reply
    $msg = "Hello Alice!";

    # generates new nonce
    $nonce = $crypto_box->nonce();

    # this time we use detached mode using precalculated key
    ($mac, $secret) = $crypto_box->encrypt_afternm( $msg, $nonce, $b_precal_key );

    # Alice needs all pieces to verify and decrypt Bob's message
    send_to( Alice => { nonce => $nonce } );
    send_to( Alice => { mac => $mac } );
    send_to( Alice => { secret => $secret } );

    ## Alice
    ########

    # Bob used the detached mode
    $nonce  = receive_for( Alice => 'nonce' );
    $mac    = receive_for( Alice => 'mac' );
    $secret = receive_for( Alice => 'secret' );

    # Alice also pre-calculates the shared key
    $a_precal_key = $crypto_box->beforenm( $b_key, $a_skey );

    # we have now all information required to decrypt message
    $decrypted_msg = $crypto_box->decrypt_detached_afternm( $mac, $secret, $nonce, $a_precal_key );

    # NOTE: send_to() and receive_for() and user functions providing transport of
    # messages

DESCRIPTION

crypto_box function is designed to meet the standard notions of privacy and third-party unforgeability for a public-key authenticated-encryption scheme using nonces.

The crypto_box function is not meant to provide non-repudiation. On the contrary: the crypto_box function guarantees repudiability. A receiver can freely modify a boxed message, and therefore cannot convince third parties that this particular message came from the sender. The sender and receiver are nevertheless protected against forgeries by other parties. crypto_box uses public-key authenticators rather than public-key signatures.

Users who want public verifiability (or receiver-assisted public verifiability) should instead use Crypt::NaCl::Sodium::sign.

Using public-key authenticated encryption, parties involved can encrypt a confidential message using their public keys, while keeping their secret keys confidential.

Using the sender's public key, only the receiver can verify that the encrypted message was actually created by the sender and was not tampered with, before eventually decrypting it. This bidirectional guarantee around identity is known as mutual authentication.

The same keypair can be used with multiple other users, without the need of generating a distinct set of keys.

Nonce (number used once) does not have to be protected, but it is crucial that the same nonce has not been ever reused with the same {sender, receiver} set.

METHODS

keypair

    my ($public_key, $secret_key) = $crypto_box->keypair();

    # or deterministically derived from a single key seed
    my ($public_key, $secret_key) = $crypto_box->keypair( $seed );

Helper method to generate a random secret key and corresponding public key to be used by $crypto_box.

See "seed" for more details when generating key pair using given $seed.

The length of the $public_key equals "PUBLICKEYBYTES".

The length of the $secret_key equals "SECRETKEYBYTES".

NOTE: keep the secret key confidential.

Returns Data::BytesLocker objects.

public_key

    my $public_key = $crypto_box->public_key( $secret_key );

Computes the public key for given secret key.

The length of the $public_key equals "PUBLICKEYBYTES".

Returns Data::BytesLocker objects.

seed

    my $seed = $crypto_box->seed();

    my ($public_key, $secret_key) = $crypto_box->keypair( $seed );

Helper method to generate a random seed, that can be used to deterministically compute the key pair derived from it.

The length of the $seed equals "SEEDBYTES".

Returns Data::BytesLocker objects.

beforenm

    my $shared_key = $crypto_box->beforenm( $public_key, $secret_key );

Applications that send several messages to the same receiver or receive several messages from the same sender can gain speed by calculating the shared key only once, and reusing it in subsequent operations.

The length of the $shared_key equals "BEFORENMBYTES".

Returns Data::BytesLocker objects.

nonce

    my $nonce = $crypto_box->nonce();

Helper method to generate a random nonce to be used by $crypto_box.

The length of the nonce equals "NONCEBYTES".

If initial value has been passed as the argument, it will then padded with null bytes.

    my $counter = 121;
    my $nonce = $crypto_box->nonce($counter);
    $nonce =~ /^121\0+$/ or die;

NOTE: nonce does not have to be random nor confidential, but it must never be reused with the same {sender, receiver} set.

If random nonce is being used it needs to be provided to the other party to allow decryption.

If counter is being used store it alongside the recipient's public key to avoid accidental reuse on the next session. In connection-oriented protocols counter-based nonce could help rejecting duplicate messages.

Returns Data::BytesLocker object.

encrypt

    # combined mode - MAC and encrypted message stored together
    my $secret = $crypto_box->encrypt($msg, $nonce,
        $recipient_public_key, $sender_secret_key);

    # detached mode - MAC and encrypted message returned separate
    my ($mac, $ciphertext) = $crypto_box->encrypt($msg, $nonce,
        $recipient_public_key, $sender_secret_key);

Encrypts the plaintext message using given $nonce, $recipient_public_key and $sender_secret_key.

In scalar context works in combined mode, where MAC and encrypted message are stored together. The length of the $secret equals the length of $msg + "MACBYTES".

In list context the $mac and $ciphertext are returned separately. The length of the $ciphertext equals the length of $msg, while length of $mac is "MACBYTES".

Returns Data::BytesLocker object.

encrypt_afternm

    # combined mode - MAC and encrypted message stored together
    my $secret = $crypto_box->encrypt_afternm($msg, $nonce,
        $shared_key);

    # detached mode - MAC and encrypted message returned separate
    my ($mac, $ciphertext) = $crypto_box->encrypt_afternm($msg, $nonce,
        $shared_key);

Same as above but encrypts using pre-calculated $shared_key (as returned by "beforenm").

decrypt

    my $msg;
    eval {
        $msg = $crypto_box->decrypt($secret, $nonce,
            $sender_public_key, $recipient_secret_key);
    };
    if ( $@ ) {
        warn "Message forged!";
    } else {
        print "Decrypted message: $msg\n";
    }

Verify and decrypt the secret message using given $nonce, $sender_public_key and $recipient_secret_key.

Function croaks if the verification fails. Otherwise returns the decrypted message.

The length of the $msg equals the length of $secret - "MACBYTES".

Returns Data::BytesLocker object.

decrypt_afternm

    my $msg;
    eval {
        $msg = $crypto_box->decrypt_afternm($secret, $nonce,
            $shared_key);
    };
    if ( $@ ) {
        warn "Message forged!";
    } else {
        print "Decrypted message: $msg\n";
    }

Same as above but decrypts using pre-calculated $shared_key (as returned by "beforenm").

decrypt_detached

    my $msg;
    eval {
        $msg = $crypto_box->decrypt_detached($mac, $ciphertext, $nonce,
            $sender_public_key, $recipient_secret_key);
    };
    if ( $@ ) {
        warn "Message forged!";
    } else {
        print "Decrypted message: $msg\n";
    }

Verify and decrypt the secret message $ciphertext authenticated with $mac using given $nonce, $sender_public_key and $recipient_secret_key.

Function croaks if the verification fails. Otherwise returns the decrypted message.

The length of the $msg equals the length of $ciphertext.

Returns Data::BytesLocker object.

decrypt_detached_afternm

    my $msg;
    eval {
        $msg = $crypto_box->decrypt_detached_afternm($mac, $ciphertext, $nonce,
            $shared_key);
    };
    if ( $@ ) {
        warn "Message forged!";
    } else {
        print "Decrypted message: $msg\n";
    }

Same as above but decrypts using pre-calculated $shared_key (as returned by "beforenm").

CONSTANTS

NONCEBYTES

    my $nonce_length = $crypto_box->NONCEBYTES;

Returns the length of nonce.

SECRETKEYBYTES

    my $skey_length = $crypto_box->SECRETKEYBYTES;

Returns the length of secret key.

PUBLICKEYBYTES

    my $pkey_length = $crypto_box->PUBLICKEYBYTES;

Returns the length of public key.

SEEDBYTES

    my $seed_length = $crypto_box->SEEDBYTES;

Returns the length of seed key.

BEFORENMBYTES

    my $shared_key_length = $crypto_box->BEFORENMBYTES;

Returns the length of pre-calculated shared key.

MACBYTES

    my $mac_length = $crypto_box->MACBYTES;

Returns the length of MAC.

ALGORITHM DETAILS

crypto_box for encryption uses XSalsa20 stream cipher (which is based on Salsa20, but with much longer nonce) and Poly1305 MAC for authentication, for key exchange Curve25519 is used.

SEE ALSO

AUTHOR

Alex J. G. Burzyński <ajgb@cpan.org>

COPYRIGHT AND LICENSE

This software is copyright (c) 2015 by Alex J. G. Burzyński <ajgb@cpan.org>.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.