Crypt-Ed25519
view release on metacpan or search on metacpan
$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
=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
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:
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
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
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 )