x25519 added

main
const an teen 2022-06-18 10:06:39 +03:00
commit cef2847326
4 changed files with 212 additions and 0 deletions

3
.gitmodules vendored 100644
View File

@ -0,0 +1,3 @@
[submodule "cppcodec"]
path = cppcodec
url = https://github.com/tplgy/cppcodec

1
cppcodec 160000

@ -0,0 +1 @@
Subproject commit 9838f9eaf077e42121cb42361e9a1613901fc5e8

158
x25519.cpp 100644
View File

@ -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

50
x25519.h 100644
View File

@ -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