Crypt-Ed25519

 view release on metacpan or  search on metacpan

Ed25519.xs  view on Meta::CPAN

  #include <inttypes.h>
#endif
#define FIXEDINT_H_INCLUDED
#include "ed25519/src/fixedint.h"

#include "ed25519/src/ed25519.h"

/*#include "ed25519/src/add_scalar.c"*/
#include "ed25519/src/fixedint.h"
#include "ed25519/src/keypair.c"
#include "ed25519/src/key_exchange.c"
#include "ed25519/src/seed.c"
#include "ed25519/src/sha512.c"
#include "ed25519/src/sha512.h"
#include "ed25519/src/sign.c"
#include "ed25519/src/verify.c"

#define select(a,b,c) ed25519_select (a, b, c)
#include "ed25519/src/ge.c"

#include "ed25519/src/fe.c"
#define load_3(x) sc_load_3(x)
#define load_4(x) sc_load_4(x)
#include "ed25519/src/sc.c"

MODULE = Crypt::Ed25519		PACKAGE = Crypt::Ed25519

PROTOTYPES: ENABLE

BOOT:
	perlmulticore_support ();

SV *
eddsa_secret_key ()
	CODE:
{
        unsigned char seed[32];

        perlinterp_release ();
        int err = ed25519_create_seed (seed);
        perlinterp_acquire ();

        if (err)
          croak ("Crypt::Ed25519::eddsa_secret_key: ed25519_create_seed failed");

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

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:
        eddsa_verify       = 0
        verify_croak       = 1
        eddsa_verify_croak = 1
	CODE:
{
        STRLEN signature_l ; char *signature_p  = SvPVbyte (signature , signature_l );
        STRLEN message_l   ; char *message_p    = SvPVbyte (message   , message_l   );
        STRLEN public_key_l; char *public_key_p = SvPVbyte (public_key, public_key_l);

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

        perlinterp_release ();
        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



( run in 0.553 second using v1.01-cache-2.11-cpan-85f18b9d64f )