x25519 added
commit
cef2847326
|
@ -0,0 +1,3 @@
|
|||
[submodule "cppcodec"]
|
||||
path = cppcodec
|
||||
url = https://github.com/tplgy/cppcodec
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 9838f9eaf077e42121cb42361e9a1613901fc5e8
|
|
@ -0,0 +1,158 @@
|
|||
/*
|
||||
* Based on
|
||||
* 1. OpenSSL lib
|
||||
* 2. PurpleI2P source code
|
||||
* 3. cppcodec lib
|
||||
*
|
||||
* PUBLIC DOMAIN C++ WRAPPER
|
||||
* acetone, 2022
|
||||
*/
|
||||
|
||||
#include "x25519.h"
|
||||
#include "cppcodec/base64_default_rfc4648.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
|
||||
namespace cppcrypto {
|
||||
|
||||
X25519Keys::X25519Keys()
|
||||
{
|
||||
m_Ctx = EVP_PKEY_CTX_new_id (NID_X25519, NULL);
|
||||
m_Pkey = nullptr;
|
||||
}
|
||||
|
||||
X25519Keys::X25519Keys (const std::array<uint8_t, 32> &priv, const std::array<uint8_t, 32> &pub)
|
||||
{
|
||||
m_Pkey = EVP_PKEY_new_raw_private_key (EVP_PKEY_X25519, NULL, priv.data(), 32);
|
||||
m_Ctx = EVP_PKEY_CTX_new (m_Pkey, NULL);
|
||||
if (not pub.empty())
|
||||
{
|
||||
memcpy (m_publicKey.data(), pub.data(), 32);
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t len = 32;
|
||||
EVP_PKEY_get_raw_public_key (m_Pkey, m_publicKey.data(), &len);
|
||||
}
|
||||
}
|
||||
|
||||
X25519Keys::~X25519Keys()
|
||||
{
|
||||
EVP_PKEY_CTX_free (m_Ctx);
|
||||
if (m_Pkey) EVP_PKEY_free (m_Pkey);
|
||||
}
|
||||
|
||||
void X25519Keys::generateKeys() noexcept
|
||||
{
|
||||
if (m_Pkey)
|
||||
{
|
||||
EVP_PKEY_free (m_Pkey);
|
||||
m_Pkey = nullptr;
|
||||
}
|
||||
EVP_PKEY_keygen_init (m_Ctx);
|
||||
EVP_PKEY_keygen (m_Ctx, &m_Pkey);
|
||||
EVP_PKEY_CTX_free (m_Ctx);
|
||||
m_Ctx = EVP_PKEY_CTX_new (m_Pkey, NULL);
|
||||
size_t len = 32;
|
||||
EVP_PKEY_get_raw_public_key (m_Pkey, m_publicKey.data(), &len);
|
||||
}
|
||||
|
||||
const std::array<uint8_t, 32> X25519Keys::getPublicKey() const noexcept
|
||||
{
|
||||
return m_publicKey;
|
||||
}
|
||||
|
||||
const std::array<uint8_t, 32> X25519Keys::getSecretKey() const noexcept
|
||||
{
|
||||
std::array<uint8_t, 32> priv;
|
||||
size_t len = 32;
|
||||
EVP_PKEY_get_raw_private_key (m_Pkey, priv.data(), &len);
|
||||
return priv;
|
||||
}
|
||||
|
||||
const std::array<uint8_t, 32> X25519Keys::agree (const std::array<uint8_t, 32> &pub) const noexcept
|
||||
{
|
||||
std::array<uint8_t, 32> shared;
|
||||
if (pub.size() < 32 or (pub[31] & 0x80)) return shared; // not x25519 key
|
||||
|
||||
EVP_PKEY_derive_init (m_Ctx);
|
||||
auto pkey = EVP_PKEY_new_raw_public_key (EVP_PKEY_X25519, NULL, pub.data(), 32);
|
||||
if (!pkey) return shared;
|
||||
EVP_PKEY_derive_set_peer (m_Ctx, pkey);
|
||||
size_t len = 32;
|
||||
EVP_PKEY_derive (m_Ctx, shared.data(), &len);
|
||||
EVP_PKEY_free (pkey);
|
||||
return shared;
|
||||
}
|
||||
|
||||
const std::array<uint8_t, 32> X25519Keys::agree (const std::string &pub) const noexcept
|
||||
{
|
||||
std::vector<uint8_t> bytes;
|
||||
try {
|
||||
bytes = cppcodec::base64_rfc4648::decode(pub);
|
||||
} catch (...) {
|
||||
return std::array<uint8_t, 32>();
|
||||
}
|
||||
return agree (bytes.data(), bytes.size());
|
||||
}
|
||||
|
||||
const std::array<uint8_t, 32> X25519Keys::agree (const uint8_t *pub, size_t size) const noexcept
|
||||
{
|
||||
if (size != 32)
|
||||
{
|
||||
return std::array<uint8_t, 32>();
|
||||
}
|
||||
|
||||
std::array<uint8_t, 32> key;
|
||||
for (int i = 0; i < 32; i++)
|
||||
{
|
||||
key[i] = pub[i];
|
||||
}
|
||||
return agree(key);
|
||||
}
|
||||
|
||||
void X25519Keys::setSecretKey (const uint8_t * priv, bool calculatePublic) noexcept
|
||||
{
|
||||
if (m_Ctx) EVP_PKEY_CTX_free (m_Ctx);
|
||||
if (m_Pkey) EVP_PKEY_free (m_Pkey);
|
||||
m_Pkey = EVP_PKEY_new_raw_private_key (EVP_PKEY_X25519, NULL, priv, 32);
|
||||
m_Ctx = EVP_PKEY_CTX_new (m_Pkey, NULL);
|
||||
if (calculatePublic)
|
||||
{
|
||||
size_t len = 32;
|
||||
EVP_PKEY_get_raw_public_key (m_Pkey, m_publicKey.data(), &len);
|
||||
}
|
||||
}
|
||||
|
||||
void X25519Keys::setSecretKey (const std::string &priv, bool calculatePublic)
|
||||
{
|
||||
std::vector<uint8_t> keyBytes = cppcodec::base64_rfc4648::decode(priv);
|
||||
setSecretKey (keyBytes, calculatePublic);
|
||||
}
|
||||
|
||||
void X25519Keys::setSecretKey (const std::vector<uint8_t>& priv, bool calculatePublic)
|
||||
{
|
||||
if (priv.size() != 32)
|
||||
{
|
||||
throw std::runtime_error ("X25519Keys::setPrivateKey priv array size != 32");
|
||||
}
|
||||
setSecretKey (priv.data(), calculatePublic);
|
||||
}
|
||||
|
||||
void X25519Keys::setSecretKey (const std::array<uint8_t, 32> &priv, bool calculatePublic)
|
||||
{
|
||||
setSecretKey (priv.data(), calculatePublic);
|
||||
}
|
||||
|
||||
std::string X25519Keys::getPublicKeyBase64String() const noexcept
|
||||
{
|
||||
return cppcodec::base64_rfc4648::encode (getPublicKey().data(), getPublicKey().size());
|
||||
}
|
||||
|
||||
std::string X25519Keys::getSecretKeyBase64String() const noexcept
|
||||
{
|
||||
return cppcodec::base64_rfc4648::encode (getSecretKey().data(), getSecretKey().size());
|
||||
}
|
||||
|
||||
} // namespace
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Based on
|
||||
* 1. OpenSSL lib
|
||||
* 2. PurpleI2P source code
|
||||
* 3. cppcodec lib
|
||||
*
|
||||
* PUBLIC DOMAIN C++ WRAPPER
|
||||
* acetone, 2022
|
||||
*/
|
||||
|
||||
#ifndef X25519_H
|
||||
#define X25519_H
|
||||
|
||||
#include <string>
|
||||
#include <array>
|
||||
#include <vector>
|
||||
#include <openssl/evp.h>
|
||||
|
||||
namespace cppcrypto {
|
||||
|
||||
class X25519Keys
|
||||
{
|
||||
public:
|
||||
X25519Keys (const std::array<uint8_t, 32>& priv, const std::array<uint8_t, 32>& pub);
|
||||
X25519Keys();
|
||||
~X25519Keys();
|
||||
|
||||
void generateKeys() noexcept;
|
||||
void setSecretKey (const uint8_t * priv, bool calculatePublic = false) noexcept;
|
||||
void setSecretKey (const std::vector<uint8_t>& priv, bool calculatePublic = false) ;
|
||||
void setSecretKey (const std::array<uint8_t, 32>& priv, bool calculatePublic = false) ;
|
||||
void setSecretKey (const std::string& priv, bool calculatePublic = false) ;
|
||||
const std::array<uint8_t, 32> getPublicKey() const noexcept;
|
||||
const std::array<uint8_t, 32> getSecretKey() const noexcept;
|
||||
const std::array<uint8_t, 32> agree (const std::array<uint8_t, 32>& pub) const noexcept;
|
||||
const std::array<uint8_t, 32> agree (const std::string& pub) const noexcept;
|
||||
const std::array<uint8_t, 32> agree (const uint8_t* pub, size_t size = 32) const noexcept;
|
||||
|
||||
std::string getPublicKeyBase64String() const noexcept;
|
||||
std::string getSecretKeyBase64String() const noexcept;
|
||||
|
||||
private:
|
||||
std::array<uint8_t, 32> m_publicKey;
|
||||
EVP_PKEY_CTX * m_Ctx;
|
||||
EVP_PKEY * m_Pkey;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif // X25519_H
|
Loading…
Reference in New Issue