Crypt-Ed25519

 view release on metacpan or  search on metacpan

Ed25519.pm  view on Meta::CPAN

   $VERSION = 1.05;

   require XSLoader;
   XSLoader::load Crypt::Ed25519::, $VERSION;
}

=head1 Ed25519 API

=over 4

=item ($public_key, $private_key) = Crypt::Ed25519::generate_keypair

Creates and returns a new random public and private key pair. The public
key is always 32 octets, the private key is always 64 octets long.

=item ($public_key, $private_key) = Crypt::Ed25519::generate_keypair $secret_key

Instead of generating a random keypair, generate them from the given
C<$secret_key> (e.g. as returned by C<Crypt::Ed25519::eddsa_secret_key>.
The derivation is deterministic, i.e. a specific C<$secret_key> will
always result in the same keypair.

A secret key is simply a random bit string, so if you have a good source
of key material, you can simply generate 32 octets from it and use this as
your secret key.

=item $signature = Crypt::Ed25519::sign $message, $public_key, $private_key

Generates a signature for the given message using the public and private
keys. The signature is always 64 octets long and deterministic, i.e. it is
always the same for a specific combination of C<$message>, C<$public_key>
and C<$private_key>, i.e. no external source of randomness is required for
signing.

=item $valid = Crypt::Ed25519::verify $message, $public_key, $signature

Checks whether the C<$signature> is valid for the C<$message> and C<$public_ke>.

=item Crypt::Ed25519::verify_croak $message, $public_key, $signature

Same as C<Crypt::Ed25519::verify>, but instead of returning a boolean,
simply croaks with an error message when the signature isn't valid, so you

Ed25519.pm  view on Meta::CPAN


=head1 CONVERTING BETWEEN Ed25519 and EdDSA

The Ed25519 and EdDSA compatible APIs handle keys slightly
differently: The Ed25519 API gives you a public/private key pair, while
EdDSA takes a secret and generates a public key from it.

You can convert an EdDSA secret to an Ed25519 private/public key pair
using C<Crypt::Ed25519::generate_keypair>:

   ($public_key, $private_key) = Crypt::Ed25519::generate_keypair $secret

As such, the EdDSA-style API allows you to store only the secret key and
derive the public key as needed. On the other hand, signing using the
private key is faster than using the secret key, so converting the secret
key to a public/private key pair allows you to sign a small message, or
many messages, faster.

=head1 Key Exchange

As an extension to Ed25519, this module implements a key exchange similar
(But not identical) to Curve25519. For this, both sides generate a keypair
and send their public key to the other side. Then both sides can generate
the same shared secret using this function:

=over

=item $shared_secret = Crypt::Ed25519::key_exchange $other_public_key, $own_private_key

Return the 32 octet shared secret generated from the given public and
private key. See SYNOPSIS for an actual example.

=back

=head1 SUPPORT FOR THE PERL MULTICORE SPECIFICATION
        
This module supports the perl multicore specification
(L<http://perlmulticore.schmorp.de/>) for all operations, although it

Ed25519.xs  view on Meta::CPAN

void
generate_keypair (SV *secret = 0)
	ALIAS:
        eddsa_public_key = 1
	PPCODE:
{
        STRLEN secret_l; char *secret_p;

        unsigned char seed[32];
        unsigned char public_key[32];
        unsigned char private_key[64];

	if (secret)
          {
            secret_p = SvPVbyte (secret, secret_l);

            if (secret_l != 32)
              croak ("Crypt::Ed25519::eddsa_public_key: secret has wrong length (!= 32)");

            perlinterp_release ();
            ed25519_create_keypair (public_key, private_key, secret_p);
            perlinterp_acquire ();
          }
        else
          {
            perlinterp_release ();

            if (ed25519_create_seed (seed))
              {
                perlinterp_acquire ();
                croak ("Crypt::Ed25519::generate_keypair: ed25519_create_seed failed");
              }

            secret_p = seed;

            ed25519_create_keypair (public_key, private_key, secret_p);

            perlinterp_acquire ();
          }

        EXTEND (SP, 2);
        PUSHs (sv_2mortal (newSVpvn (public_key, sizeof public_key)));

        if (!ix)
          PUSHs (sv_2mortal (newSVpvn (private_key, sizeof private_key)));
}

SV *
sign (SV *message, SV *public_key, SV *private_key)
	ALIAS:
        eddsa_sign = 1
	CODE:
{
	unsigned char hash[64]; /* result of sha512 */
	unsigned char signature[64];

        STRLEN message_l    ; char *message_p     = SvPVbyte (message    , message_l    );
        STRLEN public_key_l ; char *public_key_p  = SvPVbyte (public_key , public_key_l );
        STRLEN private_key_l; char *private_key_p = SvPVbyte (private_key, private_key_l);

        if (public_key_l != 32)
          croak ("Crypt::Ed25519::sign: public key has wrong length (!= 32)");

        if (ix)
          {
            if (private_key_l != 32)
              croak ("Crypt::Ed25519::eddsa_sign: secret key has wrong length (!= 32)");

            sha512 (private_key_p, 32, hash);

            hash[ 0] &= 248;
            hash[31] &= 63;
            hash[31] |= 64;

            private_key_p = hash;
          }
        else
          {
            if (private_key_l != 64)
              croak ("Crypt::Ed25519::sign: private key has wrong length (!= 64)");
          }

        perlinterp_release ();
        ed25519_sign (signature, message_p, message_l, public_key_p, private_key_p);
        perlinterp_acquire ();

        RETVAL = newSVpvn (signature, sizeof signature);
}
	OUTPUT:
        RETVAL

bool
verify (SV *message, SV *public_key, SV *signature)
	ALIAS:

Ed25519.xs  view on Meta::CPAN

        RETVAL = ed25519_verify (signature_p, message_p, message_l, public_key_p);
        perlinterp_acquire ();

        if (!RETVAL && ix)
          croak ("Crypt::Ed25519::verify_croak: signature verification failed");
}
	OUTPUT:
        RETVAL

SV *
key_exchange (SV *public_key, SV *private_key)
	CODE:
{
        STRLEN public_key_l ; char *public_key_p  = SvPVbyte (public_key , public_key_l );
        STRLEN private_key_l; char *private_key_p = SvPVbyte (private_key, private_key_l);

        if (public_key_l  != 32)
          croak ("Crypt::Ed25519::key_exchange: public key has wrong length (!= 32)");

        if (private_key_l != 64)
          croak ("Crypt::Ed25519::key_exchange: private key has wrong length (!= 64)");

        unsigned char shared_secret[32];

        perlinterp_release ();
        ed25519_key_exchange (shared_secret, public_key_p, private_key_p);
        perlinterp_acquire ();

        RETVAL = newSVpvn (shared_secret, sizeof shared_secret);
}
        OUTPUT:
        RETVAL

README  view on Meta::CPAN

    are doing - even if this module were completely error-free, that still
    doesn't mean that every way of using it is correct. When in doubt, it's
    best not to design your own cryptographic protocol.

CONVENTIONS
    Public/private/secret keys, messages and signatures are all opaque and
    architecture-independent octet strings, and, except for the message,
    have fixed lengths.

Ed25519 API
    ($public_key, $private_key) = Crypt::Ed25519::generate_keypair
        Creates and returns a new random public and private key pair. The
        public key is always 32 octets, the private key is always 64 octets
        long.

    ($public_key, $private_key) = Crypt::Ed25519::generate_keypair
    $secret_key
        Instead of generating a random keypair, generate them from the given
        $secret_key (e.g. as returned by "Crypt::Ed25519::eddsa_secret_key".
        The derivation is deterministic, i.e. a specific $secret_key will
        always result in the same keypair.

        A secret key is simply a random bit string, so if you have a good
        source of key material, you can simply generate 32 octets from it
        and use this as your secret key.

    $signature = Crypt::Ed25519::sign $message, $public_key, $private_key
        Generates a signature for the given message using the public and
        private keys. The signature is always 64 octets long and
        deterministic, i.e. it is always the same for a specific combination
        of $message, $public_key and $private_key, i.e. no external source
        of randomness is required for signing.

    $valid = Crypt::Ed25519::verify $message, $public_key, $signature
        Checks whether the $signature is valid for the $message and
        $public_ke.

    Crypt::Ed25519::verify_croak $message, $public_key, $signature
        Same as "Crypt::Ed25519::verify", but instead of returning a
        boolean, simply croaks with an error message when the signature
        isn't valid, so you don't have to think about what the return value

README  view on Meta::CPAN

        are using EdDSA and not Ed25519 API.

CONVERTING BETWEEN Ed25519 and EdDSA
    The Ed25519 and EdDSA compatible APIs handle keys slightly differently:
    The Ed25519 API gives you a public/private key pair, while EdDSA takes a
    secret and generates a public key from it.

    You can convert an EdDSA secret to an Ed25519 private/public key pair
    using "Crypt::Ed25519::generate_keypair":

       ($public_key, $private_key) = Crypt::Ed25519::generate_keypair $secret

    As such, the EdDSA-style API allows you to store only the secret key and
    derive the public key as needed. On the other hand, signing using the
    private key is faster than using the secret key, so converting the
    secret key to a public/private key pair allows you to sign a small
    message, or many messages, faster.

Key Exchange
    As an extension to Ed25519, this module implements a key exchange
    similar (But not identical) to Curve25519. For this, both sides generate
    a keypair and send their public key to the other side. Then both sides
    can generate the same shared secret using this function:

    $shared_secret = Crypt::Ed25519::key_exchange $other_public_key,
    $own_private_key
        Return the 32 octet shared secret generated from the given public
        and private key. See SYNOPSIS for an actual example.

SUPPORT FOR THE PERL MULTICORE SPECIFICATION
    This module supports the perl multicore specification
    (<http://perlmulticore.schmorp.de/>) for all operations, although it
    makes most sense to use it when signing or verifying longer messages.

IMPLEMENTATION
    This module currently uses "Nightcracker's Ed25519" implementation,

ed25519/src/ed25519.h  view on Meta::CPAN

#ifdef __cplusplus
extern "C" {
#endif

#ifndef ED25519_NO_SEED
static
int ED25519_DECLSPEC ed25519_create_seed(unsigned char *seed);
#endif

static
void ED25519_DECLSPEC ed25519_create_keypair(unsigned char *public_key, unsigned char *private_key, const unsigned char *seed);
static
void ED25519_DECLSPEC ed25519_sign(unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key, const unsigned char *private_key);
static
int ED25519_DECLSPEC ed25519_verify(const unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key);
static
void ED25519_DECLSPEC ed25519_add_scalar(unsigned char *public_key, unsigned char *private_key, const unsigned char *scalar);
static
void ED25519_DECLSPEC ed25519_key_exchange(unsigned char *shared_secret, const unsigned char *public_key, const unsigned char *private_key);


#ifdef __cplusplus
}
#endif

#endif

ed25519/src/key_exchange.c  view on Meta::CPAN

#include "ed25519.h"
#include "fe.h"

static
void ed25519_key_exchange(unsigned char *shared_secret, const unsigned char *public_key, const unsigned char *private_key) {
    unsigned char e[32];
    unsigned int i;
    
    fe x1;
    fe x2;
    fe z2;
    fe x3;
    fe z3;
    fe tmp0;
    fe tmp1;

    int pos;
    unsigned int swap;
    unsigned int b;

    /* copy the private key and make sure it's valid */
    for (i = 0; i < 32; ++i) {
        e[i] = private_key[i];
    }

    e[0] &= 248;
    e[31] &= 63;
    e[31] |= 64;

    /* unpack the public key and convert edwards to montgomery */
    /* due to CodesInChaos: montgomeryX = (edwardsY + 1)*inverse(1 - edwardsY) mod p */
    fe_frombytes(x1, public_key);
    fe_1(tmp1);

ed25519/src/keypair.c  view on Meta::CPAN

#include "ed25519.h"
#include "sha512.h"
#include "ge.h"


void ed25519_create_keypair(unsigned char *public_key, unsigned char *private_key, const unsigned char *seed) {
    ge_p3 A;

    sha512(seed, 32, private_key);
    private_key[0] &= 248;
    private_key[31] &= 63;
    private_key[31] |= 64;

    ge_scalarmult_base(&A, private_key);
    ge_p3_tobytes(public_key, &A);
}

ed25519/src/sign.c  view on Meta::CPAN

#include "ed25519.h"
#include "sha512.h"
#include "ge.h"
#include "sc.h"


void ed25519_sign(unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key, const unsigned char *private_key) {
    sha512_context hash;
    unsigned char hram[64];
    unsigned char r[64];
    ge_p3 R;


    sha512_init(&hash);
    sha512_update(&hash, private_key + 32, 32);
    sha512_update(&hash, message, message_len);
    sha512_final(&hash, r);

    sc_reduce(r);
    ge_scalarmult_base(&R, r);
    ge_p3_tobytes(signature, &R);

    sha512_init(&hash);
    sha512_update(&hash, signature, 32);
    sha512_update(&hash, public_key, 32);
    sha512_update(&hash, message, message_len);
    sha512_final(&hash, hram);

    sc_reduce(hram);
    sc_muladd(signature + 32, hram, private_key, r);
}



( run in 0.766 second using v1.01-cache-2.11-cpan-4d50c553e7e )