summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Becker <jeff@i2p.rocks>2020-02-04 16:20:25 -0500
committerJeff Becker <jeff@i2p.rocks>2020-02-19 10:38:42 -0500
commit87fadc0d278ea9dcfa5b0d227f42fc61c76201d5 (patch)
tree9810f68b972556a980c400cb680617f46941c476
parent6a95874cfe16fe46bf1a5d9f74dd6425b1d5e3d8 (diff)
fix cryptography so that it works
-rwxr-xr-xricochet.pro2
-rwxr-xr-xsrc/protocol/AuthHiddenServiceChannel.cpp78
-rwxr-xr-xsrc/protocol/AuthHiddenServiceChannel.h5
-rwxr-xr-xsrc/utils/CryptoKey.cpp18
4 files changed, 57 insertions, 46 deletions
diff --git a/ricochet.pro b/ricochet.pro
index cc2af86..f0a4d61 100755
--- a/ricochet.pro
+++ b/ricochet.pro
@@ -36,7 +36,7 @@ lessThan(QT_MAJOR_VERSION,5)|lessThan(QT_MINOR_VERSION,1) {
TARGET = ricochet-refresh
TEMPLATE = app
QT += core gui network quick widgets
-CONFIG += c++11
+CONFIG += c++11 debug
VERSION = 1.1.4
diff --git a/src/protocol/AuthHiddenServiceChannel.cpp b/src/protocol/AuthHiddenServiceChannel.cpp
index 55ed4bb..df49af9 100755
--- a/src/protocol/AuthHiddenServiceChannel.cpp
+++ b/src/protocol/AuthHiddenServiceChannel.cpp
@@ -38,10 +38,13 @@
#include "utils/CryptoKey.h"
#include "utils/Useful.h"
#include <QMessageAuthenticationCode>
+
extern "C" {
#include "../lib/onion_ed25519_signature/sign.h"
}
+Q_LOGGING_CATEGORY(hs_auth, "ricochet.tor.hsauth");
+
using namespace Protocol;
namespace Protocol {
@@ -109,21 +112,21 @@ bool AuthHiddenServiceChannel::allowInboundChannelRequest(const Data::Control::O
if (connection()->direction() != Connection::ServerSide) {
// Hidden service authentication is only allowed from the client-side connection
- qDebug() << "Rejecting AuthHiddenServiceChannel from server side";
+ qCDebug(hs_auth) << "Rejecting AuthHiddenServiceChannel from server side";
result->set_common_error(ChannelResult::BadUsageError);
return false;
}
if (connection()->hasAuthenticated(Connection::HiddenServiceAuth)) {
// You can only authenticate a connection once
- qDebug() << "Rejecting AuthHiddenServiceChannel on authenticated connection";
+ qCDebug(hs_auth) << "Rejecting AuthHiddenServiceChannel on authenticated connection";
result->set_common_error(ChannelResult::BadUsageError);
return false;
}
if (connection()->findChannel<AuthHiddenServiceChannel>()) {
// Refuse if another channel already exists
- qDebug() << "Rejecting instance of AuthHiddenServiceChannel on a connection that already has one";
+ qCDebug(hs_auth) << "Rejecting instance of AuthHiddenServiceChannel on a connection that already has one";
result->set_common_error(ChannelResult::BadUsageError);
return false;
}
@@ -131,7 +134,7 @@ bool AuthHiddenServiceChannel::allowInboundChannelRequest(const Data::Control::O
// Store client cookie
std::string clientCookie = request->GetExtension(Data::AuthHiddenService::client_cookie);
if (clientCookie.size() != 16) {
- qDebug() << "Received OpenChannel for" << type() << "with no valid client_cookie";
+ qCDebug(hs_auth) << "Received OpenChannel for" << type() << "with no valid client_cookie";
result->set_common_error(ChannelResult::BadUsageError);
return false;
}
@@ -142,7 +145,7 @@ bool AuthHiddenServiceChannel::allowInboundChannelRequest(const Data::Control::O
if (d->serverCookie.isEmpty())
return false;
- qDebug() << "Accepted inbound AuthHiddenServiceChannel";
+ qCDebug(hs_auth) << "Accepted inbound AuthHiddenServiceChannel";
result->SetExtension(Data::AuthHiddenService::server_cookie, std::string(d->serverCookie.constData(), d->serverCookie.size()));
return true;
@@ -213,12 +216,14 @@ void AuthHiddenServiceChannel::sendAuthMessage()
// get the public key
//todo auth check here to see if the key is a v3 service id, to get the v3 public key
- QByteArray publicKey = d->privateKey.encodedPublicKey(CryptoKey::DER);
+ const auto publicKey = d->v3serviceID.getV3ServiceId();
if (publicKey.size() > 150) {
BUG() << "Unexpected size for encoded public key";
closeChannel();
return;
}
+ QByteArray pk(publicKey.c_str(), publicKey.size());
+ qCDebug(hs_auth) << "public key=" << pk;
// make signature from proof data's HMAC (keyed-hash message authentication code)
// proof data: clientHostname + serverHostname, stored in a byte array
@@ -230,15 +235,17 @@ void AuthHiddenServiceChannel::sendAuthMessage()
QByteArray signature;
//FIXME: d->privateKey is a CryptoKey instance with v3serviceID=""
//todo auth check here to see if the key is a v3 service id, to get the v3 public key
- QByteArray proofData = d->getProofData(d->privateKey.torServiceID());
- if (!proofData.isEmpty()) {
- // make a HMAC of the proof data
- // HMAC: https://en.m.wikipedia.org/wiki/HMAC
- // static QByteArray QMessageAuthenticationCode::hash(&message, &key, method)
- QByteArray proofHMAC = QMessageAuthenticationCode::hash(proofData, d->clientCookie + d->serverCookie,
- QCryptographicHash::Sha256);
- signature = d->privateKey.signSHA256(proofHMAC);
- }
+
+ // hash sha2-256 the pubkey 2 cookies and sign the hash
+ QCryptographicHash hash(QCryptographicHash::Sha256);
+ hash.addData(pk);
+ hash.addData(d->serverCookie);
+ hash.addData(d->clientCookie);
+ const auto digest = hash.result();
+ qCDebug(hs_auth) << "digest=" << digest;
+ signature = d->privateKey.signSHA256(digest);
+
+
if (signature.isEmpty()) {
BUG() << "Creating proof on AuthHiddenServiceChannel failed";
@@ -250,14 +257,14 @@ void AuthHiddenServiceChannel::sendAuthMessage()
// Proof is a subclass of google::protobuf::Message
// Proof is used as a storage to contain public key and signature for verification
QScopedPointer<Data::AuthHiddenService::Proof> proof(new Data::AuthHiddenService::Proof);
- proof->set_public_key(std::string(publicKey.constData(), publicKey.size()));
+ proof->set_public_key(publicKey);
proof->set_signature(std::string(signature.constData(), signature.size()));
Data::AuthHiddenService::Packet message;
message.set_allocated_proof(proof.take());
sendMessage(message);
- qDebug() << "AuthHiddenServiceChannel sent outbound authentication packet";
+ qCDebug(hs_auth) << "AuthHiddenServiceChannel sent outbound authentication packet";
}
/**
@@ -302,7 +309,7 @@ void AuthHiddenServiceChannel::receivePacket(const QByteArray &packet)
} else if (message.has_result()) {
handleResult(message.result());
} else {
- qWarning() << "Unrecognized message on" << type();
+ qCWarning(hs_auth) << "Unrecognized message on" << type();
closeChannel();
}
}
@@ -318,7 +325,7 @@ void AuthHiddenServiceChannel::handleProof(const Data::AuthHiddenService::Proof
Q_D(AuthHiddenServiceChannel);
if (direction() != Inbound) {
- qWarning() << "Received unexpected proof on outbound" << type();
+ qCWarning(hs_auth) << "Received unexpected proof on outbound" << type();
closeChannel();
return;
}
@@ -349,34 +356,31 @@ void AuthHiddenServiceChannel::handleProof(const Data::AuthHiddenService::Proof
}
else {
// Invalid
- qWarning() << "Received invalid signature (size" << signature.size() << ") on" << type();
+ qCWarning(hs_auth) << "Received invalid signature (size" << signature.size() << ") on" << type();
}
if (decoded) {
- // FIXME: parameter is a empty string
- QByteArray proofData = d->getProofData(publicKey.torServiceID());
- if (!proofData.isEmpty()) {
+
// form a message for signature
- QByteArray proofHMAC = QMessageAuthenticationCode::hash(proofData, d->clientCookie + d->serverCookie,
- QCryptographicHash::Sha256);
- // v2: RSA 1024 public key signature verification
+ QCryptographicHash hash(QCryptographicHash::Sha256);
+ hash.addData(publicKeyData);
+ hash.addData(d->serverCookie);
+ hash.addData(d->clientCookie);
+ const auto digest = hash.result();
+ qCDebug(hs_auth) << " pubkey=" << publicKeyData << " Sig=" << signature << " loaded=" << publicKey.isLoaded();
// v3: ED25519 public key signature verification
- verified = publicKey.verifySHA256(proofHMAC, signature);
- }
- else {
- qWarning() << "Proof data is empty" << type();
- }
+ verified = publicKey.verifySHA256(digest, signature);
}
else {
// failed to decode public key
- qWarning() << "Unable to parse public key from" << type();
+ qCWarning(hs_auth) << "Unable to parse public key from" << type();
}
if (!verified) {
- qWarning() << "Signature verification failed on" << type();
+ qCWarning(hs_auth) << "Signature verification failed on" << type();
result->set_accepted(false);
} else {
result->set_accepted(true);
- qDebug() << type() << "accepted inbound authentication for" << publicKey.torServiceID();
+ qCDebug(hs_auth) << type() << "accepted inbound authentication for" << publicKey.torServiceID();
}
if (result->accepted()) {
@@ -410,18 +414,18 @@ void AuthHiddenServiceChannel::handleResult(const Data::AuthHiddenService::Resul
Q_D(AuthHiddenServiceChannel);
if (direction() != Outbound) {
- qWarning() << "Received invalid message on AuthHiddenServiceChannel";
+ qCWarning(hs_auth) << "Received invalid message on AuthHiddenServiceChannel";
closeChannel();
return;
}
if (message.accepted()) {
- qDebug() << "AuthHiddenServiceChannel succeeded as" << (message.is_known_contact() ? "known" : "unknown") << "contact";
+ qCDebug(hs_auth) << "AuthHiddenServiceChannel succeeded as" << (message.is_known_contact() ? "known" : "unknown") << "contact";
d->accepted = true;
if (message.is_known_contact())
connection()->grantAuthentication(Connection::KnownToPeer);
} else {
- qWarning() << "AuthHiddenServiceChannel rejected";
+ qCWarning(hs_auth) << "AuthHiddenServiceChannel rejected";
d->accepted = false;
}
diff --git a/src/protocol/AuthHiddenServiceChannel.h b/src/protocol/AuthHiddenServiceChannel.h
index fc796f2..8bf1cd8 100755
--- a/src/protocol/AuthHiddenServiceChannel.h
+++ b/src/protocol/AuthHiddenServiceChannel.h
@@ -37,6 +37,11 @@
#include "utils/CryptoKey.h"
#include "AuthHiddenService.pb.h"
+
+#include <QLoggingCategory>
+
+Q_DECLARE_LOGGING_CATEGORY(hs_auth);
+
namespace Protocol
{
diff --git a/src/utils/CryptoKey.cpp b/src/utils/CryptoKey.cpp
index c4378ea..79e06b0 100755
--- a/src/utils/CryptoKey.cpp
+++ b/src/utils/CryptoKey.cpp
@@ -574,13 +574,14 @@ bool CryptoKey::verifySHA256(const QByteArray &digest, QByteArray signature) con
reinterpret_cast<uchar *>(signature.data()), signature.size(), d->key);
} else if (this->keyType == V3ServiceID) {
//call verifying function for v3 keys
- //todo auth check if this works: try getEncodedV3PublicKey and decoded
- result = ed25519_sign_open(reinterpret_cast<const uchar *>(digest.constData()), digest.size(),
- reinterpret_cast<const uchar *>(this->getEncodedV3PublicKey().c_str()),
- reinterpret_cast<const uchar *>(signature.constData()));
- } else {
+ result = ed25519_sign_open(reinterpret_cast<const uchar*>(digest.constData()), digest.size(),
+ reinterpret_cast<const uchar*>(v3publicKey.c_str()),
+ reinterpret_cast<const uchar*>(signature.constData())) != -1;
+ }
+ else {
return false;
}
+ qDebug() << "result=" << result;
return result == 1;
}
@@ -823,10 +824,11 @@ Base32DecodeSize(size_t sz)
std::string decode_base32(std::string encoded)
{
const size_t decode_len = Base32DecodeSize(encoded.size());
- std::shared_ptr<char[]> decoded = std::make_shared<char[]>(decode_len);
- if(base32_decode(decoded.get(), decode_len, encoded.c_str(), encoded.size()))
+ char * ptr = new char[decode_len];
+ if(base32_decode(ptr, decode_len, encoded.c_str(), encoded.size()))
{
- return decoded.get();
+ return ptr;
}
+ delete [] ptr;
return "";
}