diff options
author | Adam Ierymenko <adam.ierymenko@gmail.com> | 2013-10-05 05:26:38 -0400 |
---|---|---|
committer | Adam Ierymenko <adam.ierymenko@gmail.com> | 2013-10-05 05:26:38 -0400 |
commit | 588a47be893cf8b3b720bb41fac3bc0b75573e26 (patch) | |
tree | df4a30657bb1ea2152ed9e80600b918858adb6a8 /node | |
parent | ea4e1136dd8b8d7830f770b4dff92f4946a998dd (diff) | |
download | infinitytier-588a47be893cf8b3b720bb41fac3bc0b75573e26.tar.gz infinitytier-588a47be893cf8b3b720bb41fac3bc0b75573e26.zip |
Some API improvements to C25519 in preparation for that thing I woke up thinking about at 4am.
Diffstat (limited to 'node')
-rw-r--r-- | node/C25519.cpp | 62 | ||||
-rw-r--r-- | node/C25519.hpp | 53 |
2 files changed, 80 insertions, 35 deletions
diff --git a/node/C25519.cpp b/node/C25519.cpp index 7b933e23..c9f72362 100644 --- a/node/C25519.cpp +++ b/node/C25519.cpp @@ -31,7 +31,6 @@ #include "Constants.hpp" #include "C25519.hpp" -#include "Utils.hpp" #include "SHA512.hpp" #include "Buffer.hpp" @@ -2288,37 +2287,6 @@ static int crypto_sign_open( ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// -C25519::Pair C25519::generate() - throw() -{ - unsigned char extsk[64]; - sc25519 scsk; - ge25519 gepk; - Pair kp; - - Utils::getSecureRandom(kp.priv.data,kp.priv.size()); - - // First 32 bytes of pub and priv are the keys for C25519 key - // agreement. This generates the public portion from the private. - crypto_scalarmult_base(kp.pub.data,kp.priv.data); - - // Second 32 bytes of pub and priv are the keys for ed25519 - // signing and verification. - SHA512::hash(extsk,kp.priv.data + 32,32); - extsk[0] &= 248; - extsk[31] &= 127; - extsk[31] |= 64; - sc25519_from32bytes(&scsk,extsk); - ge25519_scalarmult_base(&gepk,&scsk); - ge25519_pack(kp.pub.data + 32,&gepk); - // In NaCl, the public key is crammed into the next 32 bytes - // of the private key for signing since both keys are required - // to sign. In this case we just get it from public, so we - // leave that out of private. - - return kp; -} - void C25519::agree(const C25519::Private &mine,const C25519::Public &their,void *keybuf,unsigned int keylen) throw() { @@ -2417,4 +2385,34 @@ bool C25519::verify(const C25519::Public &their,const void *msg,unsigned int len return Utils::secureEq(sig,t2,32); } +void C25519::_calcPubDH(C25519::Pair &kp) + throw() +{ + // First 32 bytes of pub and priv are the keys for ECDH key + // agreement. This generates the public portion from the private. + crypto_scalarmult_base(kp.pub.data,kp.priv.data); +} + +void C25519::_calcPubED(C25519::Pair &kp) + throw() +{ + unsigned char extsk[64]; + sc25519 scsk; + ge25519 gepk; + + // Second 32 bytes of pub and priv are the keys for ed25519 + // signing and verification. + SHA512::hash(extsk,kp.priv.data + 32,32); + extsk[0] &= 248; + extsk[31] &= 127; + extsk[31] |= 64; + sc25519_from32bytes(&scsk,extsk); + ge25519_scalarmult_base(&gepk,&scsk); + ge25519_pack(kp.pub.data + 32,&gepk); + // In NaCl, the public key is crammed into the next 32 bytes + // of the private key for signing since both keys are required + // to sign. In this version we just get it from kp.pub, so we + // leave that out of private. +} + } // namespace ZeroTier diff --git a/node/C25519.hpp b/node/C25519.hpp index 9ce098ca..8d6a58ba 100644 --- a/node/C25519.hpp +++ b/node/C25519.hpp @@ -29,6 +29,7 @@ #define _ZT_C25519_HPP #include "Array.hpp" +#include "Utils.hpp" namespace ZeroTier { @@ -37,7 +38,7 @@ namespace ZeroTier { #define ZT_C25519_SIGNATURE_LEN 96 /** - * C25519 elliptic curve key agreement and signing + * A combined Curve25519 ECDH and Ed25519 signature engine */ class C25519 { @@ -68,8 +69,43 @@ public: /** * Generate a C25519 elliptic curve key pair */ - static Pair generate() - throw(); + static inline Pair generate() + throw() + { + Pair kp; + Utils::getSecureRandom(kp.priv.data,kp.priv.size()); + _calcPubDH(kp); + _calcPubED(kp); + return kp; + } + + /** + * Generate a key pair satisfying a condition + * + * This begins with a random keypair from a random secret key and then + * iteratively increments the random secret until cond(kp) returns true. + * This is used to compute key pairs in which the public key, its hash + * or some other aspect of it satisfies some condition, such as for a + * hashcash criteria. + * + * @param cond Condition function or function object + * @return Key pair where cond(kp) returns true + * @tparam F Type of 'cond' + */ + template<typename F> + static inline Pair generateSatisfying(F cond) + throw() + { + Pair kp; + void *const priv = (void *)kp.priv.data; + Utils::getSecureRandom(priv,kp.priv.size()); + _calcPubED(kp); // do Ed25519 key -- bytes 32-63 of pub and priv + do { + ++*((uint64_t *)priv); + _calcPubDH(kp); // keep regenerating bytes 0-31 until satisfied + } while (!cond(kp)); + return kp; + } /** * Perform C25519 ECC key agreement @@ -167,6 +203,17 @@ public: { return verify(their,msg,len,signature.data); } + +private: + // derive first 32 bytes of kp.pub from first 32 bytes of kp.priv + // this is the ECDH key + static void _calcPubDH(Pair &kp) + throw(); + + // derive 2nd 32 bytes of kp.pub from 2nd 32 bytes of kp.priv + // this is the Ed25519 sign/verify key + static void _calcPubED(Pair &kp) + throw(); }; } // namespace ZeroTier |