2018-12-11 21:17:56 +00:00
|
|
|
// xed25519_32.cpp - written and placed in public domain by Jeffrey Walton
|
|
|
|
// Crypto++ specific implementation wrapped around Adam
|
|
|
|
// Langley's curve25519-donna.
|
|
|
|
|
|
|
|
#include "pch.h"
|
|
|
|
|
|
|
|
#include "cryptlib.h"
|
|
|
|
#include "asn.h"
|
|
|
|
#include "integer.h"
|
|
|
|
#include "filters.h"
|
|
|
|
|
|
|
|
#include "xed25519.h"
|
|
|
|
#include "donna.h"
|
|
|
|
|
|
|
|
NAMESPACE_BEGIN(CryptoPP)
|
|
|
|
|
|
|
|
x25519::x25519(const byte y[32], const byte x[32])
|
|
|
|
{
|
|
|
|
std::memcpy(m_pk, y, 32);
|
|
|
|
std::memcpy(m_sk, x, 32);
|
|
|
|
}
|
|
|
|
|
2018-12-11 22:32:28 +00:00
|
|
|
x25519::x25519(const byte x[32])
|
|
|
|
{
|
|
|
|
std::memcpy(m_sk, x, 32);
|
|
|
|
GeneratePublicKey(NullRNG(), m_sk, m_pk);
|
|
|
|
}
|
|
|
|
|
2018-12-11 21:17:56 +00:00
|
|
|
x25519::x25519(const Integer &y, const Integer &x)
|
|
|
|
{
|
|
|
|
ArraySink ys(m_pk, 32);
|
|
|
|
y.Encode(ys, 32);
|
|
|
|
|
|
|
|
ArraySink xs(m_sk, 32);
|
|
|
|
x.Encode(xs, 32);
|
|
|
|
}
|
|
|
|
|
2018-12-11 22:32:28 +00:00
|
|
|
x25519::x25519(const Integer &x)
|
|
|
|
{
|
|
|
|
ArraySink xs(m_sk, 32);
|
|
|
|
x.Encode(xs, 32);
|
|
|
|
GeneratePublicKey(NullRNG(), m_sk, m_pk);
|
|
|
|
}
|
|
|
|
|
2018-12-11 21:17:56 +00:00
|
|
|
x25519::x25519(RandomNumberGenerator &rng)
|
|
|
|
{
|
|
|
|
GeneratePrivateKey(rng, m_sk);
|
|
|
|
GeneratePublicKey(NullRNG(), m_sk, m_pk);
|
|
|
|
}
|
|
|
|
|
|
|
|
x25519::x25519(BufferedTransformation ¶ms)
|
|
|
|
{
|
|
|
|
// TODO: Fix the on-disk format once we know what it is.
|
|
|
|
BERSequenceDecoder seq(params);
|
|
|
|
|
|
|
|
BERGeneralDecoder x(seq, BIT_STRING);
|
|
|
|
if (!x.IsDefiniteLength() || x.MaxRetrievable() < 32)
|
|
|
|
BERDecodeError();
|
|
|
|
x.Get(m_sk, 32);
|
|
|
|
x.MessageEnd();
|
|
|
|
|
|
|
|
BERGeneralDecoder y(seq, OCTET_STRING);
|
|
|
|
if (!y.IsDefiniteLength() || y.MaxRetrievable() < 32)
|
|
|
|
BERDecodeError();
|
|
|
|
y.Get(m_pk, 32);
|
|
|
|
y.MessageEnd();
|
|
|
|
|
|
|
|
seq.MessageEnd();
|
|
|
|
}
|
|
|
|
|
|
|
|
void x25519::DEREncode(BufferedTransformation ¶ms) const
|
|
|
|
{
|
|
|
|
// TODO: Fix the on-disk format once we know what it is.
|
|
|
|
DERSequenceEncoder seq(params);
|
|
|
|
|
|
|
|
DERSequenceEncoder x(seq, BIT_STRING);
|
|
|
|
x.Put(m_sk, 32);
|
|
|
|
x.MessageEnd();
|
|
|
|
|
|
|
|
DERSequenceEncoder y(seq, OCTET_STRING);
|
|
|
|
y.Put(m_pk, 32);
|
|
|
|
y.MessageEnd();
|
|
|
|
|
|
|
|
seq.MessageEnd();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool x25519::Validate(RandomNumberGenerator &rng, unsigned int level) const
|
|
|
|
{
|
|
|
|
CRYPTOPP_UNUSED(rng);
|
|
|
|
CRYPTOPP_UNUSED(level);
|
|
|
|
|
|
|
|
// TODO: add weak keys test
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool x25519::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
|
|
|
|
{
|
|
|
|
if (valueType == typeid(ConstByteArrayParameter))
|
|
|
|
{
|
|
|
|
if (std::strcmp(name, "SecretKey") == 0)
|
|
|
|
{
|
|
|
|
std::memcpy(pValue, m_sk, 32);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else if (std::strcmp(name, "PublicKey") == 0)
|
|
|
|
{
|
|
|
|
std::memcpy(pValue, m_pk, 32);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void x25519::AssignFrom(const NameValuePairs &source)
|
|
|
|
{
|
|
|
|
ConstByteArrayParameter val;
|
|
|
|
if (source.GetValue("SecretKey", val))
|
|
|
|
{
|
|
|
|
std::memcpy(m_sk, val.begin(), 32);
|
|
|
|
}
|
|
|
|
else if (source.GetValue("PublicKey", val))
|
|
|
|
{
|
|
|
|
std::memcpy(m_pk, val.begin(), 32);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void x25519::GeneratePrivateKey(RandomNumberGenerator &rng, byte *privateKey) const
|
|
|
|
{
|
|
|
|
rng.GenerateBlock(privateKey, 32);
|
|
|
|
|
|
|
|
privateKey[0] &= 248;
|
|
|
|
privateKey[31] &= 127;
|
|
|
|
privateKey[31] |= 64;
|
|
|
|
}
|
|
|
|
|
|
|
|
void x25519::GeneratePublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const
|
|
|
|
{
|
|
|
|
CRYPTOPP_UNUSED(rng);
|
|
|
|
|
|
|
|
const byte base[32] = {9};
|
|
|
|
(void)Donna::curve25519(publicKey, privateKey, base);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool x25519::Agree(byte *agreedValue, const byte *privateKey, const byte *otherPublicKey, bool validateOtherPublicKey) const
|
|
|
|
{
|
|
|
|
CRYPTOPP_ASSERT(agreedValue != NULLPTR);
|
|
|
|
CRYPTOPP_ASSERT(otherPublicKey != NULLPTR);
|
|
|
|
|
|
|
|
if (validateOtherPublicKey && Validate(NullRNG(), 3) == false)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return Donna::curve25519(agreedValue, privateKey, otherPublicKey) == 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
NAMESPACE_END // CryptoPP
|