Starbound/attic/authentication/StarClientAuthentication.cpp
2025-03-21 22:23:30 +11:00

189 lines
6.2 KiB
C++

#include "StarClientAuthentication.hpp"
#include "StarAuthenticationKey.hpp"
#include "StarAuthenticationService.hpp"
#include "StarAuthenticationConnection.hpp"
#include "StarClock.hpp"
#include "StarLogging.hpp"
#include <ctime>
namespace Star {
namespace Auth {
ClientAuthentication::ClientAuthentication(shared_ptr<Key> const& rootKey) {
m_rootPublicKey = rootKey;
}
ClientAuthentication::~ClientAuthentication() {
}
/*
* {
* "envelopeKey"
* "envelopeBody" === { encrypted body
* "request": {
* "metadata": {
* "username"
* "password"
* }
* "signature"
* }
* "claim" : {
* "metadata: {
* "clientPublicKey": (client public key)
* "username": (username)
* "validFrom": (utctime)
* "validTo": (utctime)
* }
* "signature": (produced by signing the 'claim' with the client private key)
* }
* }
* }
*/
Variant ClientAuthentication::authsvrRequest(String const& username, String const& passwordHash, String const& authClaim, Key const& clientPrivateKey) {
Variant authClaimSignature = Variant::parse(authClaim);
if (!AuthenticationService::validateAuthSignature(*m_rootPublicKey, authClaimSignature))
throw StarException("Auth claim fail.");
Key authPublicKey(authClaimSignature.get("signedAuthKey").getString("authPublicKey"));
Variant requestMetadata = VariantMap{
make_pair("username", username),
make_pair("password", passwordHash)
};
Variant claimMetadata = VariantMap{
make_pair("clientPublicKey", clientPrivateKey.publicKey()),
make_pair("username", username),
make_pair("validFrom", Clock::currentTime() - 1LL * 1LL * 60LL * 60LL * 1000LL),
make_pair("validTo", Clock::currentTime() + 7LL * 24LL * 60LL * 60LL * 1000LL)
};
Variant requestMessage = VariantMap{
make_pair("request", VariantMap{
make_pair("metadata", requestMetadata),
make_pair("signature", clientPrivateKey.signMessage(requestMetadata.repr(0, true)))
}),
make_pair("claim", VariantMap{
make_pair("metadata", claimMetadata),
make_pair("signature", clientPrivateKey.signMessage(claimMetadata.repr(0, true)))
})
};
String envelopeKey = Auth::generateKey();
String requestEnvelopeBody = requestMessage.repr(0, true);
String envelopeBody = Auth::encryptMessage(requestEnvelopeBody, envelopeKey);
Variant requestEnvelope = VariantMap{
make_pair("envelopeBody", envelopeBody),
make_pair("envelopeKey", authPublicKey.encryptMessage(envelopeKey)),
make_pair("envelopeSignature", clientPrivateKey.signMessage(envelopeBody)),
};
return requestEnvelope;
}
/**
* Client claim format:
*
* {
* "signedClaim" : {
* "claim: {
* "clientPublicKey": (client public key)
* "username": (username)
* "validFrom": (utctime)
* "validTo": (utctime)
* },
* "signature": (produced by signing the 'claim' with the client private key)
* },
* "authSignature" : {
* "signature" : (produced by signing the 'signedClaim' with the auth private key)
* "signedAuthKey": {
* "authPublicKey": (auth public key)
* "validFrom": (utctime)
* "validTo": (utctime)
* }
* "signedAuthKeySignature": (produced by signing the auth public key with the root private key)
* }
* }
*/
Variant ClientAuthentication::authsvrResponse(String const& response, Key const& clientPrivateKey) {
Variant requestEnvelope = Variant::parse(response);
String envelopeKey = clientPrivateKey.decryptMessage(requestEnvelope.getString("envelopeKey"));
String requestEnvelopeBody = requestEnvelope.getString("envelopeBody");
String envelopeBody = Auth::decryptMessage(requestEnvelopeBody, envelopeKey);
String envelopeSignature = requestEnvelope.getString("envelopeSignature");
Variant authClaimSignature = Variant::parse(envelopeBody);
Key authPublicKey(authClaimSignature.get("authSignature").get("signedAuthKey").getString("authPublicKey"));
if (!authPublicKey.verifyMessage(requestEnvelopeBody, envelopeSignature))
throw StarException("Envelop signature fail");
return authClaimSignature;
}
String ClientAuthentication::serverRequest() {
return "";
}
bool ClientAuthentication::serverResponse(String const& response) {
//todo
_unused(response);
return true;
}
Variant ClientAuthentication::authsvrValidateRequest(Variant const& claim, String const& authClaim, Key const& clientPrivateKey) {
Variant authClaimSignature = Variant::parse(authClaim);
if (!AuthenticationService::validateAuthSignature(*m_rootPublicKey, authClaimSignature))
throw StarException("Auth claim fail.");
Key authPublicKey(authClaimSignature.get("signedAuthKey").getString("authPublicKey"));
Variant requestMessage = VariantMap{
{"request", VariantMap{
{"metadata", claim},
{"signature", clientPrivateKey.signMessage(claim.repr(0, true))}
}}
};
String envelopeKey = Auth::generateKey();
String requestEnvelopeBody = requestMessage.repr(0, true);
String envelopeBody = Auth::encryptMessage(requestEnvelopeBody, envelopeKey);
Variant requestEnvelope = VariantMap{
{"envelopeBody", envelopeBody},
{"envelopeKey", authPublicKey.encryptMessage(envelopeKey)},
{"envelopeSignature", clientPrivateKey.signMessage(envelopeBody)}
};
return requestEnvelope;
}
bool ClientAuthentication::authsvrValidateResponse(String const& response, Key const& clientPrivateKey) {
Variant requestEnvelope = Variant::parse(response);
String envelopeKey = clientPrivateKey.decryptMessage(requestEnvelope.getString("envelopeKey"));
String requestEnvelopeBody = requestEnvelope.getString("envelopeBody");
String envelopeBody = Auth::decryptMessage(requestEnvelopeBody, envelopeKey);
String envelopeSignature = requestEnvelope.getString("envelopeSignature");
Variant authClaimSignature = Variant::parse(envelopeBody);
Key authPublicKey(authClaimSignature.get("authSignature").get("signedAuthKey").getString("authPublicKey"));
if (!authPublicKey.verifyMessage(requestEnvelopeBody, envelopeSignature))
throw StarException("Envelop signature fail");
return authClaimSignature.getBool("result");
}
}
}