summaryrefslogtreecommitdiff
path: root/xed25519.cpp
diff options
context:
space:
mode:
authorJeffrey Walton <noloader@gmail.com>2018-12-11 16:17:56 -0500
committerGitHub <noreply@github.com>2018-12-11 16:17:56 -0500
commit77923a291a5c993cca5c11c9b7dc00891d88bd8e (patch)
treeed0ed532c9632b35322ca67ba858eff54c8074a3 /xed25519.cpp
parentc1681148a248c21881511b620106dd7e4386d41e (diff)
downloadcryptopp-git-77923a291a5c993cca5c11c9b7dc00891d88bd8e.tar.gz
Add Langley's curve25519 (GH #761, PR# 762)
Diffstat (limited to 'xed25519.cpp')
-rw-r--r--xed25519.cpp143
1 files changed, 143 insertions, 0 deletions
diff --git a/xed25519.cpp b/xed25519.cpp
new file mode 100644
index 00000000..8ba19531
--- /dev/null
+++ b/xed25519.cpp
@@ -0,0 +1,143 @@
+// 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);
+}
+
+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);
+}
+
+x25519::x25519(RandomNumberGenerator &rng)
+{
+ GeneratePrivateKey(rng, m_sk);
+ GeneratePublicKey(NullRNG(), m_sk, m_pk);
+}
+
+x25519::x25519(BufferedTransformation &params)
+{
+ // 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 &params) 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