Successful decrypt of client handshake!
This commit is contained in:
53
crypto.cc
53
crypto.cc
@@ -45,6 +45,9 @@ void CryptoBase::DerivePublicKey(const std::string& secret_key, std::string* pub
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CryptoBase::EncodeEncryptAppend(const std::string& secret_key, const std::string& public_key, const TLVNode& input, TLVNode* container) {
|
void CryptoBase::EncodeEncryptAppend(const std::string& secret_key, const std::string& public_key, const TLVNode& input, TLVNode* container) {
|
||||||
|
assert(secret_key.length() == crypto_box_SECRETKEYBYTES);
|
||||||
|
assert(public_key.length() == crypto_box_PUBLICKEYBYTES);
|
||||||
|
|
||||||
std::string encoded;
|
std::string encoded;
|
||||||
input.Encode(&encoded);
|
input.Encode(&encoded);
|
||||||
|
|
||||||
@@ -56,13 +59,38 @@ void CryptoBase::EncodeEncryptAppend(const std::string& secret_key, const std::s
|
|||||||
unsigned char output[encrypted_bytes];
|
unsigned char output[encrypted_bytes];
|
||||||
assert(!crypto_box_easy(output, (const unsigned char*)encoded.data(), encoded.length(), nonce, (const unsigned char*)public_key.data(), (const unsigned char*)secret_key.data()));
|
assert(!crypto_box_easy(output, (const unsigned char*)encoded.data(), encoded.length(), nonce, (const unsigned char*)public_key.data(), (const unsigned char*)secret_key.data()));
|
||||||
|
|
||||||
TLVNode encrypted(TLV_TYPE_ENCRYPTED);
|
auto encrypted = new TLVNode(TLV_TYPE_ENCRYPTED);
|
||||||
encrypted.AppendChild(TLVNode(TLV_TYPE_NONCE, std::string((char*)nonce, crypto_box_NONCEBYTES)));
|
encrypted->AppendChild(new TLVNode(TLV_TYPE_NONCE, std::string((char*)nonce, crypto_box_NONCEBYTES)));
|
||||||
encrypted.AppendChild(TLVNode(TLV_TYPE_ENCRYPTED_BLOB, std::string((char*)output, encrypted_bytes)));
|
encrypted->AppendChild(new TLVNode(TLV_TYPE_ENCRYPTED_BLOB, std::string((char*)output, encrypted_bytes)));
|
||||||
|
|
||||||
container->AppendChild(encrypted);
|
container->AppendChild(encrypted);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TLVNode* CryptoBase::DecryptDecode(const std::string& secret_key, const std::string& public_key, const TLVNode& input) {
|
||||||
|
assert(secret_key.length() == crypto_box_SECRETKEYBYTES);
|
||||||
|
assert(public_key.length() == crypto_box_PUBLICKEYBYTES);
|
||||||
|
assert(input.GetType() == TLV_TYPE_ENCRYPTED);
|
||||||
|
|
||||||
|
auto nonce = input.FindChild(TLV_TYPE_NONCE);
|
||||||
|
if (!nonce || nonce->GetValue().length() != crypto_box_NONCEBYTES) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
auto encrypted = input.FindChild(TLV_TYPE_ENCRYPTED_BLOB);
|
||||||
|
if (!encrypted || encrypted->GetValue().length() < crypto_box_MACBYTES) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t decrypted_bytes = encrypted->GetValue().length() - crypto_box_MACBYTES;
|
||||||
|
|
||||||
|
unsigned char output[decrypted_bytes];
|
||||||
|
if (crypto_box_open_easy(output, (const unsigned char*)encrypted->GetValue().data(), encrypted->GetValue().length(), (const unsigned char*)nonce->GetValue().data(), (const unsigned char*)public_key.data(), (const unsigned char*)secret_key.data())) {
|
||||||
|
std::cerr << "Decryption failure" << std::endl;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TLVNode::Decode(std::string((char*)output, decrypted_bytes));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
CryptoPubServer::CryptoPubServer(const std::string& secret_key)
|
CryptoPubServer::CryptoPubServer(const std::string& secret_key)
|
||||||
: secret_key_(secret_key),
|
: secret_key_(secret_key),
|
||||||
@@ -132,6 +160,21 @@ void CryptoPubServerConnection::OnReadable() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
std::cerr << "successful decode" << std::endl;
|
std::cerr << "successful decode" << std::endl;
|
||||||
|
auto client_public_key = decoded->FindChild(TLV_TYPE_PUBLIC_KEY);
|
||||||
|
if (!client_public_key || client_public_key->GetValue().length() != crypto_box_PUBLICKEYBYTES) {
|
||||||
|
std::cerr << "Wanted " << crypto_box_PUBLICKEYBYTES << ", got " << client_public_key->GetValue().length() << " bytes" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto encrypted = decoded->FindChild(TLV_TYPE_ENCRYPTED);
|
||||||
|
if (!encrypted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<TLVNode> decrypted(DecryptDecode(secret_key_, client_public_key->GetValue(), *encrypted));
|
||||||
|
if (!decrypted.get()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
std::cerr << "successful decrypt" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CryptoPubServerConnection::OnError_(struct bufferevent* bev, const short what, void* this__) {
|
void CryptoPubServerConnection::OnError_(struct bufferevent* bev, const short what, void* this__) {
|
||||||
@@ -197,9 +240,9 @@ void CryptoPubClient::OnConnect() {
|
|||||||
GenKeyPair(&ephemeral_secret_key_, &ephemeral_public_key);
|
GenKeyPair(&ephemeral_secret_key_, &ephemeral_public_key);
|
||||||
|
|
||||||
TLVNode handshake(TLV_TYPE_CLIENT_HANDSHAKE);
|
TLVNode handshake(TLV_TYPE_CLIENT_HANDSHAKE);
|
||||||
handshake.AppendChild(TLVNode(TLV_TYPE_PUBLIC_KEY, public_key_));
|
handshake.AppendChild(new TLVNode(TLV_TYPE_PUBLIC_KEY, public_key_));
|
||||||
TLVNode secure_handshake(TLV_TYPE_CLIENT_HANDSHAKE_SECURE);
|
TLVNode secure_handshake(TLV_TYPE_CLIENT_HANDSHAKE_SECURE);
|
||||||
secure_handshake.AppendChild(TLVNode(TLV_TYPE_PUBLIC_KEY, ephemeral_public_key));
|
secure_handshake.AppendChild(new TLVNode(TLV_TYPE_PUBLIC_KEY, ephemeral_public_key));
|
||||||
EncodeEncryptAppend(secret_key_, server_public_key_, secure_handshake, &handshake);
|
EncodeEncryptAppend(secret_key_, server_public_key_, secure_handshake, &handshake);
|
||||||
|
|
||||||
std::string out;
|
std::string out;
|
||||||
|
|||||||
1
crypto.h
1
crypto.h
@@ -14,6 +14,7 @@ class CryptoBase {
|
|||||||
static void GenKeyPair(std::string* secret_key, std::string* public_key);
|
static void GenKeyPair(std::string* secret_key, std::string* public_key);
|
||||||
static void DerivePublicKey(const std::string& secret_key, std::string* public_key);
|
static void DerivePublicKey(const std::string& secret_key, std::string* public_key);
|
||||||
static void EncodeEncryptAppend(const std::string& secret_key, const std::string& public_key, const TLVNode& input, TLVNode* container);
|
static void EncodeEncryptAppend(const std::string& secret_key, const std::string& public_key, const TLVNode& input, TLVNode* container);
|
||||||
|
TLVNode *DecryptDecode(const std::string& secret_key, const std::string& public_key, const TLVNode& input);
|
||||||
};
|
};
|
||||||
|
|
||||||
class CryptoPubServerConnection;
|
class CryptoPubServerConnection;
|
||||||
|
|||||||
48
tlv.cc
48
tlv.cc
@@ -15,6 +15,12 @@ TLVNode::TLVNode(const uint16_t type, const std::string value)
|
|||||||
: type_(type),
|
: type_(type),
|
||||||
value_(value) {}
|
value_(value) {}
|
||||||
|
|
||||||
|
TLVNode::~TLVNode() {
|
||||||
|
for (auto child : children_) {
|
||||||
|
delete child;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void TLVNode::Encode(std::string *output) const {
|
void TLVNode::Encode(std::string *output) const {
|
||||||
assert(value_.length() <= UINT16_MAX);
|
assert(value_.length() <= UINT16_MAX);
|
||||||
struct header header = {
|
struct header header = {
|
||||||
@@ -26,7 +32,7 @@ void TLVNode::Encode(std::string *output) const {
|
|||||||
|
|
||||||
if (IsContainer()) {
|
if (IsContainer()) {
|
||||||
for (auto child : children_) {
|
for (auto child : children_) {
|
||||||
child.Encode(output);
|
child->Encode(output);
|
||||||
}
|
}
|
||||||
size_t total_child_length = output->length() - header_start - sizeof(header);
|
size_t total_child_length = output->length() - header_start - sizeof(header);
|
||||||
assert(total_child_length <= UINT16_MAX);
|
assert(total_child_length <= UINT16_MAX);
|
||||||
@@ -39,12 +45,12 @@ void TLVNode::Encode(std::string *output) const {
|
|||||||
|
|
||||||
TLVNode* TLVNode::Decode(const std::string& input) {
|
TLVNode* TLVNode::Decode(const std::string& input) {
|
||||||
if (input.length() < sizeof(struct header)) {
|
if (input.length() < sizeof(struct header)) {
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
auto header = (struct header*)input.data();
|
auto header = (struct header*)input.data();
|
||||||
std::cerr << "[type=" << htons(header->type) << ", value_length=" << htons(header->value_length) << "]" << std::endl;
|
std::cerr << "[type=" << htons(header->type) << ", value_length=" << htons(header->value_length) << "]" << std::endl;
|
||||||
if (input.length() < sizeof(*header) + htons(header->value_length)) {
|
if (input.length() < sizeof(*header) + htons(header->value_length)) {
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (htons(header->type) & 0x8000) {
|
if (htons(header->type) & 0x8000) {
|
||||||
@@ -54,29 +60,49 @@ TLVNode* TLVNode::Decode(const std::string& input) {
|
|||||||
size_t cursor = sizeof(*header);
|
size_t cursor = sizeof(*header);
|
||||||
while (cursor < input.length()) {
|
while (cursor < input.length()) {
|
||||||
auto next_header = (struct header*)(input.data() + cursor);
|
auto next_header = (struct header*)(input.data() + cursor);
|
||||||
if (cursor + sizeof(*next_header) + htons(next_header->value_length) > input.length()) {
|
size_t sub_length = sizeof(*next_header) + htons(next_header->value_length);
|
||||||
return NULL;
|
if (cursor + sub_length > input.length()) {
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
std::unique_ptr<TLVNode> child(Decode(input.substr(cursor)));
|
std::unique_ptr<TLVNode> child(Decode(input.substr(cursor, sub_length)));
|
||||||
if (!child.get()) {
|
if (!child.get()) {
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
container->AppendChild(*child);
|
container->AppendChild(child.release());
|
||||||
cursor += sizeof(*next_header) + htons(next_header->value_length);
|
cursor += sub_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
return container.release();
|
return container.release();
|
||||||
} else {
|
} else {
|
||||||
// Scalar
|
// Scalar
|
||||||
return new TLVNode(htons(header->type), input.substr(sizeof(*header)));
|
return new TLVNode(htons(header->type), input.substr(sizeof(*header), htons(header->value_length)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TLVNode::AppendChild(const TLVNode& child) {
|
void TLVNode::AppendChild(TLVNode* child) {
|
||||||
assert(this->IsContainer());
|
assert(this->IsContainer());
|
||||||
children_.push_back(child);
|
children_.push_back(child);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TLVNode* TLVNode::FindChild(const uint16_t type) const {
|
||||||
|
assert(this->IsContainer());
|
||||||
|
for (auto child : children_) {
|
||||||
|
if (child->GetType() == type) {
|
||||||
|
return child;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
bool TLVNode::IsContainer() const {
|
bool TLVNode::IsContainer() const {
|
||||||
return type_ & 0x8000;
|
return type_ & 0x8000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint16_t TLVNode::GetType() const {
|
||||||
|
return type_;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& TLVNode::GetValue() const {
|
||||||
|
assert(!this->IsContainer());
|
||||||
|
return value_;
|
||||||
|
}
|
||||||
|
|||||||
8
tlv.h
8
tlv.h
@@ -7,16 +7,20 @@ class TLVNode {
|
|||||||
public:
|
public:
|
||||||
TLVNode(const uint16_t type);
|
TLVNode(const uint16_t type);
|
||||||
TLVNode(const uint16_t type, const std::string value);
|
TLVNode(const uint16_t type, const std::string value);
|
||||||
|
~TLVNode();
|
||||||
|
|
||||||
static TLVNode* Decode(const std::string& input);
|
static TLVNode* Decode(const std::string& input);
|
||||||
|
|
||||||
void AppendChild(const TLVNode& child);
|
void AppendChild(TLVNode* child);
|
||||||
|
|
||||||
|
TLVNode* FindChild(const uint16_t type) const;
|
||||||
void Encode(std::string* output) const;
|
void Encode(std::string* output) const;
|
||||||
bool IsContainer() const;
|
bool IsContainer() const;
|
||||||
|
uint16_t GetType() const;
|
||||||
|
const std::string& GetValue() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const uint16_t type_;
|
const uint16_t type_;
|
||||||
const std::string value_;
|
const std::string value_;
|
||||||
std::list<TLVNode> children_;
|
std::list<TLVNode*> children_;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user