mirror of
https://github.com/markqvist/reticulum-cpp.git
synced 2025-08-12 00:00:48 -04:00
WIP update
Implemented X25519.
This commit is contained in:
parent
1b919a9489
commit
4b062aa485
22 changed files with 490 additions and 165 deletions
|
@ -39,27 +39,6 @@ int8_t Bytes::compare(const Bytes &bytes) const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
char const hex_upper_chars[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
|
|
||||||
char const hex_lower_chars[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
|
|
||||||
|
|
||||||
std::string Bytes::toHex(bool upper /*= true*/) const {
|
|
||||||
if (!_data) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
std::string hex;
|
|
||||||
for (uint8_t byte : *_data) {
|
|
||||||
if (upper) {
|
|
||||||
hex += hex_upper_chars[ (byte & 0xF0) >> 4];
|
|
||||||
hex += hex_upper_chars[ (byte & 0x0F) >> 0];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
hex += hex_lower_chars[ (byte & 0xF0) >> 4];
|
|
||||||
hex += hex_lower_chars[ (byte & 0x0F) >> 0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return hex;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Bytes::assignHex(const char* hex) {
|
void Bytes::assignHex(const char* hex) {
|
||||||
// if assignment is empty then clear data and don't bother creating new
|
// if assignment is empty then clear data and don't bother creating new
|
||||||
if (hex == nullptr || hex[0] == 0) {
|
if (hex == nullptr || hex[0] == 0) {
|
||||||
|
@ -86,3 +65,34 @@ void Bytes::appendHex(const char* hex) {
|
||||||
_data->push_back(byte);
|
_data->push_back(byte);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char const hex_upper_chars[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
|
||||||
|
char const hex_lower_chars[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
|
||||||
|
|
||||||
|
std::string Bytes::toHex(bool upper /*= true*/) const {
|
||||||
|
if (!_data) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
std::string hex;
|
||||||
|
for (uint8_t byte : *_data) {
|
||||||
|
if (upper) {
|
||||||
|
hex += hex_upper_chars[ (byte & 0xF0) >> 4];
|
||||||
|
hex += hex_upper_chars[ (byte & 0x0F) >> 0];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
hex += hex_lower_chars[ (byte & 0xF0) >> 4];
|
||||||
|
hex += hex_lower_chars[ (byte & 0x0F) >> 0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hex;
|
||||||
|
}
|
||||||
|
|
||||||
|
Bytes Bytes::mid(size_t pos, size_t len) const {
|
||||||
|
if (!_data || pos >= size()) {
|
||||||
|
return NONE;
|
||||||
|
}
|
||||||
|
if ((pos + len) >= size()) {
|
||||||
|
len = (size() - pos);
|
||||||
|
}
|
||||||
|
return {data() + pos, len};
|
||||||
|
}
|
||||||
|
|
42
src/Bytes.h
42
src/Bytes.h
|
@ -12,6 +12,8 @@
|
||||||
|
|
||||||
namespace RNS {
|
namespace RNS {
|
||||||
|
|
||||||
|
#define COW
|
||||||
|
|
||||||
class Bytes {
|
class Bytes {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -34,8 +36,7 @@ namespace RNS {
|
||||||
}
|
}
|
||||||
Bytes(const Bytes &bytes) {
|
Bytes(const Bytes &bytes) {
|
||||||
//extreme("Bytes is using shared data");
|
//extreme("Bytes is using shared data");
|
||||||
_data = bytes.shareData();
|
assign(bytes);
|
||||||
_owner = false;
|
|
||||||
//extreme("Bytes object copy created from bytes \"" + toString() + "\", this: " + std::to_string((ulong)this) + ", data: " + std::to_string((ulong)_data.get()));
|
//extreme("Bytes object copy created from bytes \"" + toString() + "\", this: " + std::to_string((ulong)this) + ", data: " + std::to_string((ulong)_data.get()));
|
||||||
}
|
}
|
||||||
Bytes(const uint8_t *chunk, size_t size) {
|
Bytes(const uint8_t *chunk, size_t size) {
|
||||||
|
@ -103,21 +104,11 @@ namespace RNS {
|
||||||
void ownData();
|
void ownData();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
int8_t compare(const Bytes &bytes) const;
|
|
||||||
inline size_t size() const { if (!_data) return 0; return _data->size(); }
|
|
||||||
inline bool empty() const { if (!_data) return true; return _data->empty(); }
|
|
||||||
inline size_t capacity() const { if (!_data) return 0; return _data->capacity(); }
|
|
||||||
inline const uint8_t *data() const { if (!_data) return nullptr; return _data->data(); }
|
|
||||||
|
|
||||||
inline std::string toString() const { if (!_data) return ""; return {(const char*)data(), size()}; }
|
|
||||||
std::string toHex(bool upper = true) const;
|
|
||||||
|
|
||||||
inline uint8_t *writable(size_t size) {
|
|
||||||
newData(size);
|
|
||||||
return _data->data();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void assign(const Bytes& bytes) {
|
inline void assign(const Bytes& bytes) {
|
||||||
|
#ifdef COW
|
||||||
|
_data = bytes.shareData();
|
||||||
|
_owner = false;
|
||||||
|
#else
|
||||||
// if assignment is empty then clear data and don't bother creating new
|
// if assignment is empty then clear data and don't bother creating new
|
||||||
if (bytes.size() <= 0) {
|
if (bytes.size() <= 0) {
|
||||||
_data = nullptr;
|
_data = nullptr;
|
||||||
|
@ -125,6 +116,7 @@ namespace RNS {
|
||||||
}
|
}
|
||||||
newData();
|
newData();
|
||||||
_data->insert(_data->begin(), bytes._data->begin(), bytes._data->end());
|
_data->insert(_data->begin(), bytes._data->begin(), bytes._data->end());
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
inline void assign(const uint8_t *chunk, size_t size) {
|
inline void assign(const uint8_t *chunk, size_t size) {
|
||||||
// if assignment is empty then clear data and don't bother creating new
|
// if assignment is empty then clear data and don't bother creating new
|
||||||
|
@ -178,6 +170,24 @@ namespace RNS {
|
||||||
}
|
}
|
||||||
void appendHex(const char* hex);
|
void appendHex(const char* hex);
|
||||||
|
|
||||||
|
public:
|
||||||
|
int8_t compare(const Bytes &bytes) const;
|
||||||
|
inline size_t size() const { if (!_data) return 0; return _data->size(); }
|
||||||
|
inline bool empty() const { if (!_data) return true; return _data->empty(); }
|
||||||
|
inline size_t capacity() const { if (!_data) return 0; return _data->capacity(); }
|
||||||
|
inline const uint8_t *data() const { if (!_data) return nullptr; return _data->data(); }
|
||||||
|
|
||||||
|
inline std::string toString() const { if (!_data) return ""; return {(const char*)data(), size()}; }
|
||||||
|
std::string toHex(bool upper = true) const;
|
||||||
|
Bytes mid(size_t pos, size_t len) const;
|
||||||
|
inline Bytes left(size_t len) const { if (!_data) return NONE; if (len > size()) len = size(); return {data(), len}; }
|
||||||
|
inline Bytes right(size_t len) const { if (!_data) return NONE; if (len > size()) len = size(); return {data() + (size() - len), len}; }
|
||||||
|
|
||||||
|
inline uint8_t *writable(size_t size) {
|
||||||
|
newData(size);
|
||||||
|
return _data->data();
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SharedData _data;
|
SharedData _data;
|
||||||
mutable bool _owner = true;
|
mutable bool _owner = true;
|
||||||
|
|
|
@ -55,6 +55,7 @@ namespace RNS { namespace Cryptography {
|
||||||
// create random private key
|
// create random private key
|
||||||
Ed25519::generatePrivateKey(_privateKey.writable(32));
|
Ed25519::generatePrivateKey(_privateKey.writable(32));
|
||||||
}
|
}
|
||||||
|
// derive public key from private key
|
||||||
Ed25519::derivePublicKey(_publicKey.writable(32), _privateKey.data());
|
Ed25519::derivePublicKey(_publicKey.writable(32), _privateKey.data());
|
||||||
}
|
}
|
||||||
~Ed25519PrivateKey() {}
|
~Ed25519PrivateKey() {}
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
#include "Hashes.h"
|
#include "Hashes.h"
|
||||||
|
|
||||||
#include "../Log.h"
|
#include "../Log.h"
|
||||||
|
#include "../Bytes.h"
|
||||||
|
|
||||||
#include <SHA256.h>
|
#include <SHA256.h>
|
||||||
#include <SHA512.h>
|
#include <SHA512.h>
|
||||||
|
|
||||||
using namespace RNS::Cryptography;
|
using namespace RNS;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The SHA primitives are abstracted here to allow platform-
|
The SHA primitives are abstracted here to allow platform-
|
||||||
|
@ -14,18 +15,23 @@ uses Python's internal SHA-256 implementation. All SHA-256
|
||||||
calls in RNS end up here.
|
calls in RNS end up here.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void RNS::Cryptography::sha256(uint8_t *hash, const uint8_t *data, uint16_t data_len) {
|
Bytes RNS::Cryptography::sha256(const Bytes &data) {
|
||||||
//extreme("Cryptography::sha256: data: " + data.toHex() );
|
//extreme("Cryptography::sha256: data: " + data.toHex() );
|
||||||
SHA256 digest;
|
SHA256 digest;
|
||||||
digest.reset();
|
digest.reset();
|
||||||
digest.update(data, data_len);
|
digest.update(data.data(), data.size());
|
||||||
digest.finalize(hash, 32);
|
Bytes hash;
|
||||||
|
digest.finalize(hash.writable(32), 32);
|
||||||
//extreme("Cryptography::sha256: hash: " + hash.toHex() );
|
//extreme("Cryptography::sha256: hash: " + hash.toHex() );
|
||||||
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RNS::Cryptography::sha512(uint8_t *hash, const uint8_t *data, uint16_t data_len) {
|
Bytes RNS::Cryptography::sha512(const Bytes &data) {
|
||||||
SHA512 digest;
|
SHA512 digest;
|
||||||
digest.reset();
|
digest.reset();
|
||||||
digest.update(data, data_len);
|
digest.update(data.data(), data.size());
|
||||||
digest.finalize(hash, 64);
|
Bytes hash;
|
||||||
|
digest.finalize(hash.writable(64), 64);
|
||||||
|
//extreme("Cryptography::sha512: hash: " + hash.toHex() );
|
||||||
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "../Bytes.h"
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
namespace RNS { namespace Cryptography {
|
namespace RNS { namespace Cryptography {
|
||||||
|
|
||||||
void sha256(uint8_t *hash, const uint8_t *data, uint16_t data_len);
|
Bytes sha256(const Bytes &data);
|
||||||
void sha512(uint8_t *hash, const uint8_t *data, uint16_t data_len);
|
Bytes sha512(const Bytes &data);
|
||||||
|
|
||||||
} }
|
} }
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
#include "Bytes.h"
|
#include "Bytes.h"
|
||||||
|
|
||||||
|
#include <Curve25519.h>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
@ -10,29 +12,41 @@ namespace RNS { namespace Cryptography {
|
||||||
class X25519PublicKey {
|
class X25519PublicKey {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
/*
|
||||||
X25519PublicKey(const Bytes &x) {
|
X25519PublicKey(const Bytes &x) {
|
||||||
_x = x;
|
_x = x;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
X25519PublicKey(const Bytes &publicKey) {
|
||||||
|
_publicKey = publicKey;
|
||||||
|
}
|
||||||
~X25519PublicKey() {}
|
~X25519PublicKey() {}
|
||||||
|
|
||||||
using Ptr = std::shared_ptr<X25519PublicKey>;
|
using Ptr = std::shared_ptr<X25519PublicKey>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// creates a new instance with specified seed
|
// creates a new instance with specified seed
|
||||||
|
/*
|
||||||
static inline Ptr from_public_bytes(const Bytes &data) {
|
static inline Ptr from_public_bytes(const Bytes &data) {
|
||||||
//return Ptr(new X25519PublicKey(_unpack_number(data)));
|
return Ptr(new X25519PublicKey(_unpack_number(data)));
|
||||||
// MOCK
|
}
|
||||||
return Ptr(new X25519PublicKey(nullptr));
|
*/
|
||||||
|
static inline Ptr from_public_bytes(const Bytes &publicKey) {
|
||||||
|
return Ptr(new X25519PublicKey(publicKey));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
Bytes public_bytes() {
|
Bytes public_bytes() {
|
||||||
//return _pack_number(_x);
|
return _pack_number(_x);
|
||||||
// MOCK
|
}
|
||||||
return nullptr;
|
*/
|
||||||
|
Bytes public_bytes() {
|
||||||
|
return _publicKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Bytes _x;
|
//Bytes _x;
|
||||||
|
Bytes _publicKey;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -47,43 +61,74 @@ namespace RNS { namespace Cryptography {
|
||||||
const uint8_t T_MAX = 0;
|
const uint8_t T_MAX = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
/*
|
||||||
X25519PrivateKey(const Bytes &a) {
|
X25519PrivateKey(const Bytes &a) {
|
||||||
_a = a;
|
_a = a;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
X25519PrivateKey(const Bytes &privateKey) {
|
||||||
|
if (privateKey) {
|
||||||
|
// use specified private key
|
||||||
|
_privateKey = privateKey;
|
||||||
|
// similar to derive public key from private key
|
||||||
|
// second param "f" is secret
|
||||||
|
//eval(uint8_t result[32], const uint8_t s[32], const uint8_t x[32])
|
||||||
|
// derive public key from private key
|
||||||
|
Curve25519::eval(_publicKey.writable(32), _privateKey.data(), 0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// create random private key and derive public key
|
||||||
|
// second param "f" is secret
|
||||||
|
//dh1(uint8_t k[32], uint8_t f[32])
|
||||||
|
Curve25519::dh1(_publicKey.writable(32), _privateKey.writable(32));
|
||||||
|
}
|
||||||
|
}
|
||||||
~X25519PrivateKey() {}
|
~X25519PrivateKey() {}
|
||||||
|
|
||||||
using Ptr = std::shared_ptr<X25519PrivateKey>;
|
using Ptr = std::shared_ptr<X25519PrivateKey>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// creates a new instance with a random seed
|
// creates a new instance with a random seed
|
||||||
|
/*
|
||||||
static inline Ptr generate() {
|
static inline Ptr generate() {
|
||||||
//return from_private_bytes(os.urandom(32));
|
return from_private_bytes(os.urandom(32));
|
||||||
// MOCK
|
}
|
||||||
return from_private_bytes(nullptr);
|
*/
|
||||||
|
static inline Ptr generate() {
|
||||||
|
return from_private_bytes(Bytes::NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// creates a new instance with specified seed
|
// creates a new instance with specified seed
|
||||||
|
/*
|
||||||
static inline Ptr from_private_bytes(const Bytes &data) {
|
static inline Ptr from_private_bytes(const Bytes &data) {
|
||||||
//return Ptr(new X25519PrivateKey(_fix_secret(_unpack_number(data))));
|
return Ptr(new X25519PrivateKey(_fix_secret(_unpack_number(data))));
|
||||||
// MOCK
|
}
|
||||||
return Ptr(new X25519PrivateKey(nullptr));
|
*/
|
||||||
|
static inline Ptr from_private_bytes(const Bytes &privateKey) {
|
||||||
|
return Ptr(new X25519PrivateKey(privateKey));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
inline Bytes private_bytes() {
|
inline Bytes private_bytes() {
|
||||||
//return _pack_number(_a);
|
return _pack_number(_a);
|
||||||
// MOCK
|
}
|
||||||
return nullptr;
|
*/
|
||||||
|
inline Bytes private_bytes() {
|
||||||
|
return _privateKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
// creates a new instance of public key for this private key
|
// creates a new instance of public key for this private key
|
||||||
|
/*
|
||||||
inline X25519PublicKey::Ptr public_key() {
|
inline X25519PublicKey::Ptr public_key() {
|
||||||
//return X25519PublicKey::from_public_bytes(_pack_number(_raw_curve25519(9, _a)));
|
return X25519PublicKey::from_public_bytes(_pack_number(_raw_curve25519(9, _a)));
|
||||||
// MOCK
|
}
|
||||||
return X25519PublicKey::from_public_bytes(nullptr);
|
*/
|
||||||
|
inline X25519PublicKey::Ptr public_key() {
|
||||||
|
return X25519PublicKey::from_public_bytes(_publicKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Bytes exchange(const Bytes &peer_public_key) {
|
|
||||||
/*
|
/*
|
||||||
|
inline Bytes exchange(const Bytes &peer_public_key) {
|
||||||
if isinstance(peer_public_key, bytes):
|
if isinstance(peer_public_key, bytes):
|
||||||
peer_public_key = X25519PublicKey.from_public_bytes(peer_public_key)
|
peer_public_key = X25519PublicKey.from_public_bytes(peer_public_key)
|
||||||
|
|
||||||
|
@ -119,12 +164,18 @@ namespace RNS { namespace Cryptography {
|
||||||
X25519PrivateKey.T_MAX = duration
|
X25519PrivateKey.T_MAX = duration
|
||||||
|
|
||||||
return shared
|
return shared
|
||||||
|
}
|
||||||
*/
|
*/
|
||||||
return nullptr;
|
inline Bytes exchange(const Bytes &peer_public_key) {
|
||||||
|
Bytes sharedKey(peer_public_key);
|
||||||
|
Curve25519::dh2(sharedKey.writable(32), _privateKey.writable(32));
|
||||||
|
return sharedKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Bytes _a;
|
//Bytes _a;
|
||||||
|
Bytes _privateKey;
|
||||||
|
Bytes _publicKey;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -272,15 +272,15 @@ Bytes Destination::encrypt(const Bytes &data) {
|
||||||
assert(_object);
|
assert(_object);
|
||||||
debug("Destination::encrypt: encrypting bytes");
|
debug("Destination::encrypt: encrypting bytes");
|
||||||
|
|
||||||
/*
|
|
||||||
if (_object->_type == Destination::PLAIN) {
|
if (_object->_type == Destination::PLAIN) {
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_object->_type == Destination::SINGLE && _object->_identity) {
|
if (_object->_type == Destination::SINGLE && _object->_identity) {
|
||||||
return _object->_identity.encrypt(data)
|
return _object->_identity.encrypt(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
if (_object->_type == Destination::GROUP {
|
if (_object->_type == Destination::GROUP {
|
||||||
if hasattr(self, "prv") and self.prv != None:
|
if hasattr(self, "prv") and self.prv != None:
|
||||||
try:
|
try:
|
||||||
|
@ -292,9 +292,8 @@ Bytes Destination::encrypt(const Bytes &data) {
|
||||||
raise ValueError("No private key held by GROUP destination. Did you create or load one?")
|
raise ValueError("No private key held by GROUP destination. Did you create or load one?")
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// MOCK
|
// MOCK
|
||||||
return data;
|
return Bytes::NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -307,15 +306,15 @@ Bytes Destination::decrypt(const Bytes &data) {
|
||||||
assert(_object);
|
assert(_object);
|
||||||
debug("Destination::decrypt: decrypting bytes");
|
debug("Destination::decrypt: decrypting bytes");
|
||||||
|
|
||||||
/*
|
|
||||||
if (_object->_type == Destination::PLAIN) {
|
if (_object->_type == Destination::PLAIN) {
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_object->_type == Destination::SINGLE && _object->_identity) {
|
if (_object->_type == Destination::SINGLE && _object->_identity) {
|
||||||
return identity.decrypt(data);
|
return _object->_identity.decrypt(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
if (_object->_type == Destination::GROUP) {
|
if (_object->_type == Destination::GROUP) {
|
||||||
if hasattr(self, "prv") and self.prv != None:
|
if hasattr(self, "prv") and self.prv != None:
|
||||||
try:
|
try:
|
||||||
|
@ -327,9 +326,8 @@ Bytes Destination::decrypt(const Bytes &data) {
|
||||||
raise ValueError("No private key held by GROUP destination. Did you create or load one?")
|
raise ValueError("No private key held by GROUP destination. Did you create or load one?")
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// MOCK
|
// MOCK
|
||||||
return data;
|
return Bytes::NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -343,5 +341,5 @@ Bytes Destination::sign(const Bytes &message) {
|
||||||
if (_object->_type == Destination::SINGLE && _object->_identity) {
|
if (_object->_type == Destination::SINGLE && _object->_identity) {
|
||||||
return _object->_identity.sign(message);
|
return _object->_identity.sign(message);
|
||||||
}
|
}
|
||||||
return nullptr;
|
return Bytes::NONE;
|
||||||
}
|
}
|
||||||
|
|
173
src/Identity.cpp
173
src/Identity.cpp
|
@ -1,7 +1,10 @@
|
||||||
#include "Identity.h"
|
#include "Identity.h"
|
||||||
|
|
||||||
|
#include "Reticulum.h"
|
||||||
|
#include "Packet.h"
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
#include "Cryptography/Hashes.h"
|
#include "Cryptography/Hashes.h"
|
||||||
|
#include "Cryptography/X25519.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
@ -20,7 +23,7 @@ void Identity::createKeys() {
|
||||||
|
|
||||||
_object->_prv = Cryptography::X25519PrivateKey::generate();
|
_object->_prv = Cryptography::X25519PrivateKey::generate();
|
||||||
_object->_prv_bytes = _object->_prv->private_bytes();
|
_object->_prv_bytes = _object->_prv->private_bytes();
|
||||||
debug("Identity::createKeys: prv bytes: " + _object->_prv_bytes.toHex());
|
debug("Identity::createKeys: prv bytes: " + _object->_prv_bytes.toHex());
|
||||||
|
|
||||||
_object->_sig_prv = Cryptography::Ed25519PrivateKey::generate();
|
_object->_sig_prv = Cryptography::Ed25519PrivateKey::generate();
|
||||||
_object->_sig_prv_bytes = _object->_sig_prv->private_bytes();
|
_object->_sig_prv_bytes = _object->_sig_prv->private_bytes();
|
||||||
|
@ -28,7 +31,7 @@ void Identity::createKeys() {
|
||||||
|
|
||||||
_object->_pub = _object->_prv->public_key();
|
_object->_pub = _object->_prv->public_key();
|
||||||
_object->_pub_bytes = _object->_pub->public_bytes();
|
_object->_pub_bytes = _object->_pub->public_bytes();
|
||||||
debug("Identity::createKeys: pub bytes: " + _object->_pub_bytes.toHex());
|
debug("Identity::createKeys: pub bytes: " + _object->_pub_bytes.toHex());
|
||||||
|
|
||||||
_object->_sig_pub = _object->_sig_prv->public_key();
|
_object->_sig_pub = _object->_sig_prv->public_key();
|
||||||
_object->_sig_pub_bytes = _object->_sig_pub->public_bytes();
|
_object->_sig_pub_bytes = _object->_sig_pub->public_bytes();
|
||||||
|
@ -45,18 +48,122 @@ void Identity::createKeys() {
|
||||||
Bytes Identity::get_public_key() {
|
Bytes Identity::get_public_key() {
|
||||||
assert(_object);
|
assert(_object);
|
||||||
return _object->_pub_bytes + _object->_sig_pub_bytes;
|
return _object->_pub_bytes + _object->_sig_pub_bytes;
|
||||||
// MOCK
|
|
||||||
return "abc123";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Identity::update_hashes() {
|
void Identity::update_hashes() {
|
||||||
assert(_object);
|
assert(_object);
|
||||||
_object->_hash = truncated_hash(get_public_key());
|
_object->_hash = truncated_hash(get_public_key());
|
||||||
debug("Identity::update_hashes: hash: " + _object->_hash.toHex());
|
debug("Identity::update_hashes: hash: " + _object->_hash.toHex());
|
||||||
_object->_hexhash = _object->_hash.toHex();
|
_object->_hexhash = _object->_hash.toHex();
|
||||||
debug("Identity::update_hashes: hexhash: " + _object->_hexhash);
|
debug("Identity::update_hashes: hexhash: " + _object->_hexhash);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Get a SHA-256 hash of passed data.
|
||||||
|
|
||||||
|
:param data: Data to be hashed as *bytes*.
|
||||||
|
:returns: SHA-256 hash as *bytes*
|
||||||
|
*/
|
||||||
|
/*static*/ Bytes Identity::full_hash(const Bytes &data) {
|
||||||
|
return Cryptography::sha256(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Get a truncated SHA-256 hash of passed data.
|
||||||
|
|
||||||
|
:param data: Data to be hashed as *bytes*.
|
||||||
|
:returns: Truncated SHA-256 hash as *bytes*
|
||||||
|
*/
|
||||||
|
/*static*/ Bytes Identity::truncated_hash(const Bytes &data) {
|
||||||
|
return full_hash(data).right(TRUNCATED_HASHLENGTH/8);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Encrypts information for the identity.
|
||||||
|
|
||||||
|
:param plaintext: The plaintext to be encrypted as *bytes*.
|
||||||
|
:returns: Ciphertext token as *bytes*.
|
||||||
|
:raises: *KeyError* if the instance does not hold a public key.
|
||||||
|
*/
|
||||||
|
Bytes Identity::encrypt(const Bytes &plaintext) {
|
||||||
|
assert(_object);
|
||||||
|
if (_object->_pub) {
|
||||||
|
Cryptography::X25519PrivateKey::Ptr ephemeral_key = Cryptography::X25519PrivateKey::generate();
|
||||||
|
Bytes ephemeral_pub_bytes = ephemeral_key->public_key()->public_bytes();
|
||||||
|
|
||||||
|
/*
|
||||||
|
Bytes shared_key = ephemeral_key->exchange(_object->_pub);
|
||||||
|
|
||||||
|
Bytes derived_key = RNS.Cryptography.hkdf(
|
||||||
|
length=32,
|
||||||
|
derive_from=shared_key,
|
||||||
|
salt=get_salt(),
|
||||||
|
context=get_context(),
|
||||||
|
)
|
||||||
|
|
||||||
|
fernet = Fernet(derived_key)
|
||||||
|
ciphertext = fernet.encrypt(plaintext)
|
||||||
|
|
||||||
|
return ephemeral_pub_bytes + ciphertext;
|
||||||
|
*/
|
||||||
|
// MOCK
|
||||||
|
return Bytes::NONE;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw std::runtime_error("Encryption failed because identity does not hold a public key");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Decrypts information for the identity.
|
||||||
|
|
||||||
|
:param ciphertext: The ciphertext to be decrypted as *bytes*.
|
||||||
|
:returns: Plaintext as *bytes*, or *None* if decryption fails.
|
||||||
|
:raises: *KeyError* if the instance does not hold a private key.
|
||||||
|
*/
|
||||||
|
Bytes Identity::decrypt(const Bytes &ciphertext_token) {
|
||||||
|
assert(_object);
|
||||||
|
if (_object->_prv) {
|
||||||
|
if (ciphertext_token.size() > Identity::KEYSIZE/8/2) {
|
||||||
|
Bytes plaintext;
|
||||||
|
try {
|
||||||
|
Bytes peer_pub_bytes = ciphertext_token.right(Identity::KEYSIZE/8/2);
|
||||||
|
Cryptography::X25519PublicKey::Ptr peer_pub = Cryptography::X25519PublicKey::from_public_bytes(peer_pub_bytes);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Bytes shared_key = _object->_prv->exchange(peer_pub);
|
||||||
|
|
||||||
|
Bytes derived_key = RNS.Cryptography.hkdf(
|
||||||
|
length=32,
|
||||||
|
derive_from=shared_key,
|
||||||
|
salt=get_salt(),
|
||||||
|
context=get_context(),
|
||||||
|
)
|
||||||
|
|
||||||
|
fernet = Fernet(derived_key)
|
||||||
|
ciphertext = ciphertext_token[Identity.KEYSIZE//8//2:]
|
||||||
|
plaintext = fernet.decrypt(ciphertext)
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
catch (std::exception &e) {
|
||||||
|
debug("Decryption by " + _object->_hash.toHex() + " failed: " + e.what());
|
||||||
|
}
|
||||||
|
|
||||||
|
return plaintext;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
debug("Decryption failed because the token size was invalid.");
|
||||||
|
return Bytes::NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw std::runtime_error("Decryption failed because identity does not hold a private key");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Signs information by the identity.
|
Signs information by the identity.
|
||||||
|
|
||||||
|
@ -70,7 +177,7 @@ Bytes Identity::sign(const Bytes &message) {
|
||||||
try {
|
try {
|
||||||
return _object->_sig_prv->sign(message);
|
return _object->_sig_prv->sign(message);
|
||||||
}
|
}
|
||||||
catch (std::exception e) {
|
catch (std::exception &e) {
|
||||||
error("The identity " + toString() + " could not sign the requested message. The contained exception was: " + e.what());
|
error("The identity " + toString() + " could not sign the requested message. The contained exception was: " + e.what());
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
|
@ -80,29 +187,45 @@ Bytes Identity::sign(const Bytes &message) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Get a SHA-256 hash of passed data.
|
Validates the signature of a signed message.
|
||||||
|
|
||||||
:param data: Data to be hashed as *bytes*.
|
:param signature: The signature to be validated as *bytes*.
|
||||||
:returns: SHA-256 hash as *bytes*
|
:param message: The message to be validated as *bytes*.
|
||||||
|
:returns: True if the signature is valid, otherwise False.
|
||||||
|
:raises: *KeyError* if the instance does not hold a public key.
|
||||||
*/
|
*/
|
||||||
/*static*/ Bytes Identity::full_hash(const Bytes &data) {
|
bool Identity::validate(const Bytes &signature, const Bytes &message) {
|
||||||
Bytes hash;
|
assert(_object);
|
||||||
Cryptography::sha256(hash.writable(HASHLENGTH/8), data.data(), data.size());
|
if (_object->_pub) {
|
||||||
//debug("Identity::full_hash: hash: " + hash.toHex());
|
try {
|
||||||
return hash;
|
_object->_sig_pub->verify(signature, message);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (std::exception &e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw std::runtime_error("Signature validation failed because identity does not hold a public key");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
void Identity::prove(const Packet &packet, const Destination &destination /*= Destination::NONE*/) {
|
||||||
Get a truncated SHA-256 hash of passed data.
|
assert(_object);
|
||||||
|
Bytes signature(sign(packet._packet_hash));
|
||||||
|
Bytes proof_data;
|
||||||
|
if (RNS::Reticulum::should_use_implicit_proof()) {
|
||||||
|
proof_data = signature;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
proof_data = packet._packet_hash + signature;
|
||||||
|
}
|
||||||
|
|
||||||
:param data: Data to be hashed as *bytes*.
|
//zif (!destination) {
|
||||||
:returns: Truncated SHA-256 hash as *bytes*
|
//z destination = packet.generate_proof_destination();
|
||||||
*/
|
//z}
|
||||||
/*static*/ Bytes Identity::truncated_hash(const Bytes &data) {
|
|
||||||
Bytes hash = full_hash(data);
|
Packet proof(destination, packet.receiving_interface(), proof_data, RNS::Packet::PROOF);
|
||||||
//Bytes truncated_hash(hash.data() + (TRUNCATED_HASHLENGTH/8), TRUNCATED_HASHLENGTH/8);
|
proof.send();
|
||||||
//debug("Identity::truncated_hash: truncated hash: " + truncated_hash.toHex());
|
|
||||||
return Bytes(hash.data() + (TRUNCATED_HASHLENGTH/8), TRUNCATED_HASHLENGTH/8);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Reticulum.h"
|
#include "Reticulum.h"
|
||||||
|
// CBA TODO determine why including Destination.h here causes build errors
|
||||||
|
//#include "Destination.h"
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
#include "Bytes.h"
|
#include "Bytes.h"
|
||||||
#include "Cryptography/Fernet.h"
|
#include "Cryptography/Fernet.h"
|
||||||
|
@ -13,6 +15,9 @@
|
||||||
|
|
||||||
namespace RNS {
|
namespace RNS {
|
||||||
|
|
||||||
|
class Destination;
|
||||||
|
class Packet;
|
||||||
|
|
||||||
class Identity {
|
class Identity {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -66,8 +71,15 @@ namespace RNS {
|
||||||
|
|
||||||
static Bytes full_hash(const Bytes &data);
|
static Bytes full_hash(const Bytes &data);
|
||||||
static Bytes truncated_hash(const Bytes &data);
|
static Bytes truncated_hash(const Bytes &data);
|
||||||
Bytes sign(const Bytes &message);
|
|
||||||
|
|
||||||
|
Bytes encrypt(const Bytes &plaintext);
|
||||||
|
Bytes decrypt(const Bytes &ciphertext_token);
|
||||||
|
Bytes sign(const Bytes &message);
|
||||||
|
bool validate(const Bytes &signature, const Bytes &message);
|
||||||
|
//void prove(const Packet &packet, const Destination &destination = Destination::NONE);
|
||||||
|
void prove(const Packet &packet, const Destination &destination);
|
||||||
|
|
||||||
|
// getters/setters
|
||||||
inline Bytes encryptionPrivateKey() const { assert(_object); return _object->_prv_bytes; }
|
inline Bytes encryptionPrivateKey() const { assert(_object); return _object->_prv_bytes; }
|
||||||
inline Bytes signingPrivateKey() const { assert(_object); return _object->_sig_prv_bytes; }
|
inline Bytes signingPrivateKey() const { assert(_object); return _object->_sig_prv_bytes; }
|
||||||
inline Bytes encryptionPublicKey() const { assert(_object); return _object->_prv_bytes; }
|
inline Bytes encryptionPublicKey() const { assert(_object); return _object->_prv_bytes; }
|
||||||
|
|
|
@ -5,10 +5,10 @@
|
||||||
using namespace RNS;
|
using namespace RNS;
|
||||||
|
|
||||||
Interface::Interface() {
|
Interface::Interface() {
|
||||||
log("Interface object created", LOG_EXTREME);
|
extreme("Interface object created");
|
||||||
}
|
}
|
||||||
|
|
||||||
Interface::~Interface() {
|
Interface::~Interface() {
|
||||||
log("Interface object destroyed", LOG_EXTREME);
|
extreme("Interface object destroyed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,18 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
//#include <Arduino.h>
|
#include "../Log.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
namespace RNS {
|
namespace RNS {
|
||||||
|
|
||||||
class Interface {
|
class Interface {
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum NoneConstructor {
|
||||||
|
NONE
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Interface mode definitions
|
// Interface mode definitions
|
||||||
enum modes {
|
enum modes {
|
||||||
|
@ -22,9 +29,33 @@ namespace RNS {
|
||||||
//zDISCOVER_PATHS_FOR = [MODE_ACCESS_POINT, MODE_GATEWAY]
|
//zDISCOVER_PATHS_FOR = [MODE_ACCESS_POINT, MODE_GATEWAY]
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
Interface(NoneConstructor none) {
|
||||||
|
extreme("Interface object NONE created");
|
||||||
|
}
|
||||||
|
Interface(const Interface &interface) : _object(interface._object) {
|
||||||
|
extreme("Interface object copy created");
|
||||||
|
}
|
||||||
Interface();
|
Interface();
|
||||||
~Interface();
|
~Interface();
|
||||||
|
|
||||||
|
inline Interface& operator = (const Interface &interface) {
|
||||||
|
_object = interface._object;
|
||||||
|
extreme("Interface object copy created by assignment, this: " + std::to_string((ulong)this) + ", data: " + std::to_string((uint32_t)_object.get()));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
inline operator bool() const {
|
||||||
|
return _object.get() != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
class Object {
|
||||||
|
private:
|
||||||
|
|
||||||
|
|
||||||
|
friend class Interface;
|
||||||
|
};
|
||||||
|
std::shared_ptr<Object> _object;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
|
@ -8,8 +8,8 @@
|
||||||
|
|
||||||
using namespace RNS;
|
using namespace RNS;
|
||||||
|
|
||||||
Packet::Packet(const Destination &destination, const Bytes &data, types packet_type, context_types context, Transport::types transport_type, header_types header_type, const uint8_t *transport_id, Interface *attached_interface, bool create_receipt) : _object(new Object(destination)) {
|
//Packet::Packet(const Destination &destination, const Bytes &data, types packet_type, context_types context, Transport::types transport_type, header_types header_type, const uint8_t *transport_id, Interface *attached_interface, bool create_receipt) : _object(new Object(destination)) {
|
||||||
assert(_object);
|
Packet::Packet(const Destination &destination, const Interface &attached_interface, const Bytes &data, types packet_type /*= DATA*/, context_types context /*= CONTEXT_NONE*/, Transport::types transport_type /*= Transport::BROADCAST*/, header_types header_type /*= HEADER_1*/, const uint8_t *transport_id /*= nullptr*/, bool create_receipt /*= true*/) : _object(new Object(destination, attached_interface)) {
|
||||||
|
|
||||||
if (_object->_destination) {
|
if (_object->_destination) {
|
||||||
// CBA TODO handle NONE
|
// CBA TODO handle NONE
|
||||||
|
@ -52,7 +52,6 @@ Packet::Packet(const Destination &destination, const Bytes &data, types packet_t
|
||||||
_fromPacked = true;
|
_fromPacked = true;
|
||||||
_create_receipt = false;
|
_create_receipt = false;
|
||||||
}
|
}
|
||||||
_attached_interface = attached_interface;
|
|
||||||
extreme("Packet object created");
|
extreme("Packet object created");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -427,8 +426,8 @@ bool Packet::unpack() {
|
||||||
_packed = false;
|
_packed = false;
|
||||||
update_hash();
|
update_hash();
|
||||||
}
|
}
|
||||||
catch (std::exception& ex) {
|
catch (std::exception& e) {
|
||||||
log(std::string("Received malformed packet, dropping it. The contained exception was: ") + ex.what(), LOG_EXTREME);
|
error(std::string("Received malformed packet, dropping it. The contained exception was: ") + e.what());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -530,3 +529,10 @@ Bytes Packet::get_hashable_part() {
|
||||||
hashable_part.append(_data-Reticulum::DESTINATION_LENGTH-1, _data_len+Reticulum::DESTINATION_LENGTH+1);
|
hashable_part.append(_data-Reticulum::DESTINATION_LENGTH-1, _data_len+Reticulum::DESTINATION_LENGTH+1);
|
||||||
return hashable_part;
|
return hashable_part;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Generates a special destination that allows Reticulum
|
||||||
|
// to direct the proof back to the proved packet's sender
|
||||||
|
//ProofDestination &Packet::generate_proof_destination() {
|
||||||
|
// return ProofDestination();
|
||||||
|
//}
|
||||||
|
|
||||||
|
|
39
src/Packet.h
39
src/Packet.h
|
@ -14,6 +14,7 @@ namespace RNS {
|
||||||
|
|
||||||
class Packet;
|
class Packet;
|
||||||
class PacketProof;
|
class PacketProof;
|
||||||
|
class ProofDestination;
|
||||||
class PacketReceipt;
|
class PacketReceipt;
|
||||||
class PacketReceiptCallbacks;
|
class PacketReceiptCallbacks;
|
||||||
|
|
||||||
|
@ -84,7 +85,9 @@ namespace RNS {
|
||||||
uint8_t EMPTY_DESTINATION[Reticulum::DESTINATION_LENGTH] = {0};
|
uint8_t EMPTY_DESTINATION[Reticulum::DESTINATION_LENGTH] = {0};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Packet(const Destination &destination, const Bytes &data, types packet_type = DATA, context_types context = CONTEXT_NONE, Transport::types transport_type = Transport::BROADCAST, header_types header_type = HEADER_1, const uint8_t *transport_id = nullptr, Interface *attached_interface = nullptr, bool create_receipt = true);
|
Packet(const Destination &destination, const Interface &attached_interface, const Bytes &data, types packet_type = DATA, context_types context = CONTEXT_NONE, Transport::types transport_type = Transport::BROADCAST, header_types header_type = HEADER_1, const uint8_t *transport_id = nullptr, bool create_receipt = true);
|
||||||
|
Packet(const Destination &destination, const Bytes &data, types packet_type = DATA, context_types context = CONTEXT_NONE, Transport::types transport_type = Transport::BROADCAST, header_types header_type = HEADER_1, const uint8_t *transport_id = nullptr, bool create_receipt = true) : Packet(destination, Interface::NONE, data, DATA, CONTEXT_NONE, Transport::BROADCAST, HEADER_1, nullptr, create_receipt) {
|
||||||
|
}
|
||||||
Packet(NoneConstructor none) {
|
Packet(NoneConstructor none) {
|
||||||
extreme("Packet NONE object created");
|
extreme("Packet NONE object created");
|
||||||
}
|
}
|
||||||
|
@ -110,16 +113,6 @@ namespace RNS {
|
||||||
void setData(const uint8_t* rata, uint16_t len);
|
void setData(const uint8_t* rata, uint16_t len);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
private:
|
|
||||||
class Object {
|
|
||||||
public:
|
|
||||||
Object(const Destination &destination) : _destination(destination) {}
|
|
||||||
private:
|
|
||||||
Destination _destination;
|
|
||||||
friend class Packet;
|
|
||||||
};
|
|
||||||
std::shared_ptr<Object> _object;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
uint8_t get_packed_flags();
|
uint8_t get_packed_flags();
|
||||||
void pack();
|
void pack();
|
||||||
|
@ -130,8 +123,12 @@ namespace RNS {
|
||||||
Bytes get_hash();
|
Bytes get_hash();
|
||||||
Bytes getTruncatedHash();
|
Bytes getTruncatedHash();
|
||||||
Bytes get_hashable_part();
|
Bytes get_hashable_part();
|
||||||
|
//zProofDestination &generate_proof_destination();
|
||||||
|
|
||||||
private:
|
// getters/setters
|
||||||
|
inline const Interface& receiving_interface() const { assert(_object); return _object->_receiving_interface; }
|
||||||
|
|
||||||
|
public:
|
||||||
types _packet_type;
|
types _packet_type;
|
||||||
header_types _header_type;
|
header_types _header_type;
|
||||||
context_types _context;
|
context_types _context;
|
||||||
|
@ -151,9 +148,6 @@ namespace RNS {
|
||||||
uint16_t _mtu = Reticulum::MTU;
|
uint16_t _mtu = Reticulum::MTU;
|
||||||
time_t _sent_at = 0;
|
time_t _sent_at = 0;
|
||||||
|
|
||||||
Interface *_attached_interface = nullptr;
|
|
||||||
Interface *_receiving_interface = nullptr;
|
|
||||||
|
|
||||||
float _rssi = 0.0;
|
float _rssi = 0.0;
|
||||||
float _snr = 0.0;
|
float _snr = 0.0;
|
||||||
|
|
||||||
|
@ -166,6 +160,21 @@ namespace RNS {
|
||||||
uint8_t _header[Reticulum::HEADER_MAXSIZE];
|
uint8_t _header[Reticulum::HEADER_MAXSIZE];
|
||||||
uint8_t *_data = _raw + Reticulum::HEADER_MAXSIZE;
|
uint8_t *_data = _raw + Reticulum::HEADER_MAXSIZE;
|
||||||
uint16_t _data_len = 0;
|
uint16_t _data_len = 0;
|
||||||
|
|
||||||
|
private:
|
||||||
|
class Object {
|
||||||
|
public:
|
||||||
|
Object(const Destination &destination, const Interface &attached_interface) : _destination(destination), _attached_interface(attached_interface) {}
|
||||||
|
private:
|
||||||
|
|
||||||
|
Destination _destination;
|
||||||
|
|
||||||
|
Interface _attached_interface;
|
||||||
|
Interface _receiving_interface;
|
||||||
|
|
||||||
|
friend class Packet;
|
||||||
|
};
|
||||||
|
std::shared_ptr<Object> _object;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,15 @@ Reticulum::~Reticulum() {
|
||||||
extreme("Reticulum object destroyed");
|
extreme("Reticulum object destroyed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Returns whether proofs sent are explicit or implicit.
|
||||||
|
|
||||||
|
:returns: True if the current running configuration specifies to use implicit proofs. False if not.
|
||||||
|
*/
|
||||||
|
/*static*/ bool Reticulum::should_use_implicit_proof() {
|
||||||
|
return __use_implicit_proof;
|
||||||
|
}
|
||||||
|
|
||||||
void Reticulum::loop() {
|
void Reticulum::loop() {
|
||||||
// Perform random number gnerator housekeeping
|
// Perform random number gnerator housekeeping
|
||||||
RNG.loop();
|
RNG.loop();
|
||||||
|
|
|
@ -10,12 +10,6 @@ namespace RNS {
|
||||||
|
|
||||||
class Reticulum {
|
class Reticulum {
|
||||||
|
|
||||||
private:
|
|
||||||
class Object {
|
|
||||||
private:
|
|
||||||
friend class Reticulum;
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum NoneConstructor {
|
enum NoneConstructor {
|
||||||
NONE
|
NONE
|
||||||
|
@ -85,6 +79,12 @@ namespace RNS {
|
||||||
|
|
||||||
static const uint8_t DESTINATION_LENGTH = TRUNCATED_HASHLENGTH/8; // In bytes
|
static const uint8_t DESTINATION_LENGTH = TRUNCATED_HASHLENGTH/8; // In bytes
|
||||||
|
|
||||||
|
static const bool __transport_enabled = false;
|
||||||
|
static const bool __use_implicit_proof = true;
|
||||||
|
static const bool __allow_probes = false;
|
||||||
|
|
||||||
|
static const bool panic_on_interface_error = false;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Reticulum();
|
Reticulum();
|
||||||
Reticulum(NoneConstructor none) {
|
Reticulum(NoneConstructor none) {
|
||||||
|
@ -105,9 +105,14 @@ namespace RNS {
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
static bool should_use_implicit_proof();
|
||||||
void loop();
|
void loop();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
class Object {
|
||||||
|
private:
|
||||||
|
friend class Reticulum;
|
||||||
|
};
|
||||||
std::shared_ptr<Object> _object;
|
std::shared_ptr<Object> _object;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -10,7 +10,6 @@ void test() {
|
||||||
testMap();
|
testMap();
|
||||||
testBytes();
|
testBytes();
|
||||||
testCowBytes();
|
testCowBytes();
|
||||||
testObjects();
|
|
||||||
testBytesConversion();
|
testBytesConversion();
|
||||||
|
|
||||||
testReference();
|
testReference();
|
||||||
|
|
|
@ -6,8 +6,6 @@ void testBytes();
|
||||||
void testCowBytes();
|
void testCowBytes();
|
||||||
void testBytesConversion();
|
void testBytesConversion();
|
||||||
|
|
||||||
void testObjects();
|
|
||||||
|
|
||||||
void testReference();
|
void testReference();
|
||||||
|
|
||||||
void testCrypto();
|
void testCrypto();
|
||||||
|
|
|
@ -105,6 +105,56 @@ void testBytes() {
|
||||||
assert(bytes.size() == 11);
|
assert(bytes.size() == 11);
|
||||||
assert(memcmp(bytes.data(), "Hello World", bytes.size()) == 0);
|
assert(memcmp(bytes.data(), "Hello World", bytes.size()) == 0);
|
||||||
|
|
||||||
|
// test left in range
|
||||||
|
{
|
||||||
|
RNS::Bytes left(bytes.left(5));
|
||||||
|
RNS::extreme("left: " + left.toString());
|
||||||
|
assert(left.size() == 5);
|
||||||
|
assert(memcmp(left.data(), "Hello", left.size()) == 0);
|
||||||
|
}
|
||||||
|
// test left oob
|
||||||
|
{
|
||||||
|
RNS::Bytes left(bytes.left(20));
|
||||||
|
RNS::extreme("oob left: " + left.toString());
|
||||||
|
assert(left.size() == 11);
|
||||||
|
assert(memcmp(left.data(), "Hello World", left.size()) == 0);
|
||||||
|
}
|
||||||
|
// test right in range
|
||||||
|
{
|
||||||
|
RNS::Bytes right(bytes.right(5));
|
||||||
|
RNS::extreme("right: " + right.toString());
|
||||||
|
assert(right.size() == 5);
|
||||||
|
assert(memcmp(right.data(), "World", right.size()) == 0);
|
||||||
|
}
|
||||||
|
// test right oob
|
||||||
|
{
|
||||||
|
RNS::Bytes right(bytes.right(20));
|
||||||
|
RNS::extreme("oob right: " + right.toString());
|
||||||
|
assert(right.size() == 11);
|
||||||
|
assert(memcmp(right.data(), "Hello World", right.size()) == 0);
|
||||||
|
}
|
||||||
|
// test mid in range
|
||||||
|
{
|
||||||
|
RNS::Bytes mid(bytes.mid(3, 5));
|
||||||
|
RNS::extreme("mid: " + mid.toString());
|
||||||
|
assert(mid.size() == 5);
|
||||||
|
assert(memcmp(mid.data(), "lo Wo", mid.size()) == 0);
|
||||||
|
}
|
||||||
|
// test mid oob pos
|
||||||
|
{
|
||||||
|
RNS::Bytes mid(bytes.mid(20, 5));
|
||||||
|
RNS::extreme("oob pos mid: " + mid.toString());
|
||||||
|
assert(!mid);
|
||||||
|
assert(mid.size() == 0);
|
||||||
|
}
|
||||||
|
// test mid oob pos
|
||||||
|
{
|
||||||
|
RNS::Bytes mid(bytes.mid(3, 20));
|
||||||
|
RNS::extreme("oob len mid: " + mid.toString());
|
||||||
|
assert(mid.size() == 8);
|
||||||
|
assert(memcmp(mid.data(), "lo World", mid.size()) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
// stream into empty bytes
|
// stream into empty bytes
|
||||||
{
|
{
|
||||||
RNS::Bytes strmbuf;
|
RNS::Bytes strmbuf;
|
||||||
|
|
|
@ -25,7 +25,7 @@ void testCrypto() {
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
UNITY_BEGIN();
|
UNITY_BEGIN();
|
||||||
RUN_TEST(testObjects);
|
RUN_TEST(testCrypto);
|
||||||
return UNITY_END();
|
return UNITY_END();
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -23,7 +23,7 @@ void testReference() {
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
UNITY_BEGIN();
|
UNITY_BEGIN();
|
||||||
RUN_TEST(testObjects);
|
RUN_TEST(testReference);
|
||||||
return UNITY_END();
|
return UNITY_END();
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -38,6 +38,6 @@ Transport::~Transport() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/*static*/ bool Transport::outbound(const Packet &packet) {
|
/*static*/ bool Transport::outbound(const Packet &packet) {
|
||||||
// mock
|
// MOCK
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
57
src/main.cpp
57
src/main.cpp
|
@ -39,45 +39,50 @@ void setup() {
|
||||||
Serial.print("Hello from T-Beam on PlatformIO!\n");
|
Serial.print("Hello from T-Beam on PlatformIO!\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
//RNS::loglevel(RNS::LOG_WARNING);
|
RNS::loglevel(RNS::LOG_WARNING);
|
||||||
RNS::loglevel(RNS::LOG_EXTREME);
|
//RNS::loglevel(RNS::LOG_EXTREME);
|
||||||
//test();
|
test();
|
||||||
testCrypto();
|
|
||||||
return;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//std::stringstream test;
|
//std::stringstream test;
|
||||||
// !!! just adding this single stringstream alone (not even using it) adds a whopping 17.1% !!!
|
// !!! just adding this single stringstream alone (not even using it) adds a whopping 17.1% !!!
|
||||||
// !!! JUST SAY NO TO STRINGSTREAM !!!
|
// !!! JUST SAY NO TO STRINGSTREAM !!!
|
||||||
|
|
||||||
RNS::loglevel(RNS::LOG_EXTREME);
|
RNS::loglevel(RNS::LOG_EXTREME);
|
||||||
|
|
||||||
// 18.5% completely empty program
|
// 18.5% completely empty program
|
||||||
|
|
||||||
// 21.8% baseline here with serial
|
// 21.8% baseline here with serial
|
||||||
|
|
||||||
RNS::Reticulum reticulum;
|
RNS::Reticulum reticulum;
|
||||||
// 21.9% (+0.1%)
|
// 21.9% (+0.1%)
|
||||||
|
|
||||||
RNS::Identity identity;
|
RNS::Identity identity;
|
||||||
// 22.6% (+0.7%)
|
// 22.6% (+0.7%)
|
||||||
|
|
||||||
RNS::Destination destination(identity, RNS::Destination::IN, RNS::Destination::SINGLE, "test", "context");
|
RNS::Destination destination(identity, RNS::Destination::IN, RNS::Destination::SINGLE, "test", "context");
|
||||||
// 23.0% (+0.4%)
|
// 23.0% (+0.4%)
|
||||||
|
|
||||||
//destination.announce(RNS::bytesFromString(fruits[rand() % 7]));
|
//destination.announce(RNS::bytesFromString(fruits[rand() % 7]));
|
||||||
// test path
|
// test path
|
||||||
destination.announce(RNS::bytesFromString(fruits[rand() % 7]), true, nullptr, RNS::bytesFromString("test_tag"));
|
destination.announce(RNS::bytesFromString(fruits[rand() % 7]), true, nullptr, RNS::bytesFromString("test_tag"));
|
||||||
// 23.9% (+0.8%)
|
// 23.9% (+0.8%)
|
||||||
|
|
||||||
//zdestination.set_proof_strategy(RNS::Destination::PROVE_ALL);
|
//zdestination.set_proof_strategy(RNS::Destination::PROVE_ALL);
|
||||||
|
|
||||||
//zannounce_handler = ExampleAnnounceHandler(
|
//zannounce_handler = ExampleAnnounceHandler(
|
||||||
//z aspect_filter="example_utilities.announcesample.fruits";
|
//z aspect_filter="example_utilities.announcesample.fruits";
|
||||||
//z)
|
//z)
|
||||||
|
|
||||||
//zRNS::Transport.register_announce_handler(announce_handler);
|
//zRNS::Transport.register_announce_handler(announce_handler);
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (std::exception& e) {
|
||||||
|
RNS::error(std::string("!!! Exception in main: ") + e.what() + " !!!");
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef NATIVE
|
#ifndef NATIVE
|
||||||
Serial.print("Goodbye from T-Beam on PlatformIO!\n");
|
Serial.print("Goodbye from T-Beam on PlatformIO!\n");
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue