v1.4.4
This commit is contained in:
commit
9c94d113d3
10260 changed files with 1237388 additions and 0 deletions
353
attic/authentication/StarAuthenticationService.cpp
Normal file
353
attic/authentication/StarAuthenticationService.cpp
Normal file
|
@ -0,0 +1,353 @@
|
|||
#include "StarAuthenticationService.hpp"
|
||||
#include "StarAuthenticationKey.hpp"
|
||||
#include "StarClock.hpp"
|
||||
#include "StarLogging.hpp"
|
||||
#include "StarFile.hpp"
|
||||
#include <ctime>
|
||||
|
||||
namespace Star {
|
||||
namespace Auth {
|
||||
|
||||
AuthenticationService::AuthenticationService(DatabasePtr db) {
|
||||
m_db = db;
|
||||
|
||||
Variant config = Variant::parseJson(File::readFileString("auth.config"));
|
||||
|
||||
m_rootPublicKey.loadPublicKey(config.getString("rootPublicKey"));
|
||||
m_authPrivateKey.loadPrivateKey(config.getString("authPrivateKey"));
|
||||
|
||||
m_certificate = config.get("authCertificate");
|
||||
|
||||
String certMetadata = config.get("authCertificate").get("signedAuthKey").repr(0, true);
|
||||
String certSignature = config.get("authCertificate").get("rootSignedAuthKeySignature").toString();
|
||||
if (!m_rootPublicKey.verifyMessage(certMetadata, certSignature)) {
|
||||
throw CryptoException("Invalid Certificate");
|
||||
}
|
||||
}
|
||||
|
||||
AuthenticationService::~AuthenticationService() {
|
||||
}
|
||||
|
||||
/**
|
||||
* {
|
||||
* "signedAuthKey" : {
|
||||
* "authPublicKey": ...
|
||||
* "validFrom":...
|
||||
* "validTo":...
|
||||
* }
|
||||
* "rootSignedAuthKeySignature": (signature made with root privkey)
|
||||
* }
|
||||
*/
|
||||
Variant AuthenticationService::getCertificate() {
|
||||
return m_certificate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process Client Request
|
||||
*
|
||||
* request:
|
||||
* {
|
||||
* "envelopeSignature" (signed with client privkey)
|
||||
* "envelopeKey" (encyrpted with auth pubkey)
|
||||
* "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)
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* response:
|
||||
* {
|
||||
* "claim": {
|
||||
* "metadata: {
|
||||
* "clientPublicKey":...
|
||||
* "username":...
|
||||
* "validFrom":...
|
||||
* "validTo":...
|
||||
* }
|
||||
* "signature"
|
||||
* }
|
||||
* "authSignature": {
|
||||
* "signedAuthKey" : {
|
||||
* "authPublicKey": ...
|
||||
* "validFrom":...
|
||||
* "validTo":...
|
||||
* }
|
||||
* "rootSignedAuthKeySignature": (signature made with root privkey)
|
||||
* }
|
||||
* "signature": (signature of main message with authPrivateKey)
|
||||
* }
|
||||
*
|
||||
*/
|
||||
Variant AuthenticationService::authorizeClient(Variant const& request) {
|
||||
String envelopeSignature = request.getString("envelopeSignature");
|
||||
String envelopeBodyString = request.getString("envelopeBody");
|
||||
String envelopeKey = m_authPrivateKey.decryptMessage(request.getString("envelopeKey"));
|
||||
String envelopeBody = Star::Auth::decryptMessage(envelopeBodyString, envelopeKey);
|
||||
|
||||
Variant requestMessage = Variant::parse(envelopeBody);
|
||||
|
||||
Variant claim = requestMessage["claim"];
|
||||
|
||||
if (!validateClientInnerClaim(claim))
|
||||
throw StarException("Request claim fail.");
|
||||
|
||||
Key clientKey(claim["metadata"].getString("clientPublicKey"));
|
||||
|
||||
if (!clientKey.verifyMessage(envelopeBodyString, envelopeSignature))
|
||||
throw StarException("Request outer signature fail.");
|
||||
|
||||
String requestSignature = requestMessage["request"].getString("signature");
|
||||
auto requestMetadata = requestMessage["request"]["metadata"];
|
||||
if (!clientKey.verifyMessage(requestMetadata.repr(0, true), requestSignature))
|
||||
throw StarException("Request signature fail.");
|
||||
|
||||
int64_t validFrom = claim["metadata"].getInt("validFrom");
|
||||
int64_t validTo = claim["metadata"].getInt("validTo");
|
||||
|
||||
if (Clock::currentTime() - 1LL*25LL*60LL*60LL*1000LL > validFrom)
|
||||
throw StarException("Claim is too old.");
|
||||
|
||||
if (Clock::currentTime() < validFrom)
|
||||
throw StarException("Claim not yet valid");
|
||||
|
||||
if (Clock::currentTime()+ 8LL*24LL*60LL*60LL*1000LL < validTo)
|
||||
throw StarException("Claim is valid for too long.");
|
||||
|
||||
String username = requestMetadata.getString("username");
|
||||
String password = requestMetadata.getString("password");
|
||||
String claimUsername = claim["metadata"].getString("username");
|
||||
|
||||
if (username != claimUsername) {
|
||||
throw StarException("Username does not match claim.");
|
||||
}
|
||||
|
||||
if (!m_db->validateUserAndPassword(username, password)) {
|
||||
throw StarException("Unable to authenticate user");
|
||||
}
|
||||
|
||||
Variant responseMessage = VariantMap{
|
||||
{"claim", claim},
|
||||
{"authSignature", m_certificate},
|
||||
{"signature", m_authPrivateKey.signMessage(claim.repr(0, true))}
|
||||
};
|
||||
|
||||
String messageKey = Star::Auth::generateKey();
|
||||
String responseBodyString = responseMessage.repr(0, true);
|
||||
String responseEnvelopeBody = encryptMessage(responseBodyString, messageKey);
|
||||
Variant responseEnvelope = VariantMap{
|
||||
{"envelopeBody", responseEnvelopeBody},
|
||||
{"envelopeKey", clientKey.encryptMessage(messageKey)},
|
||||
{"envelopeSignature", m_authPrivateKey.signMessage(responseEnvelopeBody)}
|
||||
};
|
||||
return responseEnvelope;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process Client Request
|
||||
*
|
||||
* request:
|
||||
* {
|
||||
* "envelopeSignature" (signed with client privkey)
|
||||
* "envelopeKey" (encyrpted with auth pubkey)
|
||||
* "envelopeBody" === { crypted body
|
||||
* "request": {
|
||||
* "metadata": (claim)
|
||||
* "signature"
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* response:
|
||||
* {
|
||||
* "result": (bool)
|
||||
* "authSignature": {
|
||||
* "signedAuthKey" : {
|
||||
* "authPublicKey": ...
|
||||
* "validFrom":...
|
||||
* "validTo":...
|
||||
* }
|
||||
* "rootSignedAuthKeySignature": (signature made with root privkey)
|
||||
* }
|
||||
* }
|
||||
* // message is fullbody encrypted so the response is trust worthyish
|
||||
*
|
||||
*/
|
||||
Variant AuthenticationService::validateClient(Variant const& request) {
|
||||
bool valid = false;
|
||||
String clientPublicKey;
|
||||
try {
|
||||
String envelopeSignature = request.getString("envelopeSignature");
|
||||
String envelopeBodyString = request.getString("envelopeBody");
|
||||
String envelopeKey = m_authPrivateKey.decryptMessage(request.getString("envelopeKey"));
|
||||
String envelopeBody = Star::Auth::decryptMessage(envelopeBodyString, envelopeKey);
|
||||
|
||||
Variant requestMessage = Variant::parse(envelopeBody);
|
||||
|
||||
Variant claim = requestMessage["request"]["metadata"];
|
||||
|
||||
clientPublicKey = claim["claim"]["metadata"].getString("clientPublicKey");
|
||||
|
||||
if (!validateClientClaim(m_rootPublicKey, claim))
|
||||
throw StarException("Request claim fail.");
|
||||
|
||||
Key clientKey(clientPublicKey);
|
||||
|
||||
if (!clientKey.verifyMessage(envelopeBodyString, envelopeSignature))
|
||||
throw StarException("Request outer signature fail.");
|
||||
|
||||
String requestSignature = requestMessage["request"].getString("signature");
|
||||
auto requestMetadata = requestMessage["request"]["metadata"];
|
||||
if (!clientKey.verifyMessage(requestMetadata.repr(0, true), requestSignature))
|
||||
throw StarException("Request signature fail.");
|
||||
|
||||
String username = claim["claim"]["metadata"].getString("username");
|
||||
|
||||
if (!m_db->validateUser(username)) {
|
||||
throw StarException("Username is not valid.");
|
||||
}
|
||||
valid = true;
|
||||
}
|
||||
catch (std::exception const& e) {
|
||||
Logger::error("failure validating client claim %s", e.what());
|
||||
valid = false;
|
||||
}
|
||||
|
||||
Variant responseMessage = VariantMap{
|
||||
{"result", valid},
|
||||
{"authSignature", m_certificate}
|
||||
};
|
||||
|
||||
String messageKey = Star::Auth::generateKey();
|
||||
String responseBodyString = responseMessage.repr(0, true);
|
||||
String envelopeBody = encryptMessage(responseBodyString, messageKey);
|
||||
Key clientKey(clientPublicKey);
|
||||
Variant responseEnvelope = VariantMap{
|
||||
{"envelopeBody", envelopeBody},
|
||||
{"envelopeKey", clientKey.encryptMessage(messageKey)},
|
||||
{"envelopeSignature", m_authPrivateKey.signMessage(envelopeBody)}
|
||||
};
|
||||
return responseEnvelope;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* response:
|
||||
* {
|
||||
* "rootPublicKey" : string,
|
||||
* "authPrivateKey" : string,
|
||||
* "authCertificate" : {
|
||||
* "signedAuthKey" : {
|
||||
* "authPublicKey" : string,
|
||||
* "validFrom" : long,
|
||||
* "validTo" : long,
|
||||
* }
|
||||
* "rootSignedAuthKeySignature" : string,
|
||||
* }
|
||||
* }
|
||||
*
|
||||
*/
|
||||
Variant AuthenticationService::generateAuthenticationConfig(String const& rootPrivateKey, int64_t valid, int64_t expires) {
|
||||
// Load Root Key
|
||||
Star::Auth::Key rootKey(rootPrivateKey, true);
|
||||
// Generate new Authsvr Key
|
||||
Star::Auth::Key authKey(true);
|
||||
|
||||
Variant signedAuthKey = VariantMap{
|
||||
{"authPublicKey", authKey.publicKey()},
|
||||
{"validFrom", valid},
|
||||
{"validTo", expires}
|
||||
};
|
||||
|
||||
Variant config = VariantMap{
|
||||
{"rootPublicKey", rootKey.publicKey()},
|
||||
{"authPrivateKey", authKey.privateKey()},
|
||||
{"authCertificate", VariantMap{
|
||||
{"signedAuthKey", signedAuthKey},
|
||||
{"rootSignedAuthKeySignature", rootKey.signMessage(signedAuthKey.repr(0, true))}
|
||||
}}
|
||||
};
|
||||
|
||||
if (!validateAuthSignature(rootKey, config["authCertificate"]))
|
||||
throw StarException("Generation failed.");
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
bool AuthenticationService::validateAuthSignature(Key const& rootPublicKey, Variant const& authSignature) {
|
||||
auto signedAuthKey = authSignature.get("signedAuthKey");
|
||||
auto rootSignedAuthKeySignature = authSignature.getString("rootSignedAuthKeySignature");
|
||||
if (!rootPublicKey.verifyMessage(signedAuthKey.repr(0, true), rootSignedAuthKeySignature)) {
|
||||
Logger::error("failed to validate signedAuthKey with rootSignedAuthKeySignature");
|
||||
return false;
|
||||
}
|
||||
|
||||
auto authPublicKey = signedAuthKey.getString("authPublicKey");
|
||||
if (authPublicKey.empty()) {
|
||||
Logger::error("empty public key");
|
||||
return false;
|
||||
}
|
||||
auto signedAuthKeyValidFrom = signedAuthKey.getInt("validFrom");
|
||||
auto signedAuthKeyValidTo = signedAuthKey.getInt("validTo");
|
||||
|
||||
if ((signedAuthKeyValidFrom > Clock::currentTime()) || (signedAuthKeyValidTo < Clock::currentTime())) {
|
||||
Logger::error("timestamp fail %s %s %s", Clock::currentTime(), signedAuthKeyValidFrom, signedAuthKeyValidTo);
|
||||
return false;
|
||||
}
|
||||
|
||||
// implicit in use after this anyways
|
||||
// Key authPublicKey(signedAuthKey);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AuthenticationService::validateClientClaim(Key const& rootPublicKey, Variant const& claim) {
|
||||
if (!validateAuthSignature(rootPublicKey, claim.get("authSignature")))
|
||||
return false;
|
||||
|
||||
auto signedAuthKey = claim.get("authSignature").get("signedAuthKey").getString("authPublicKey");
|
||||
Key authPublicKey(signedAuthKey);
|
||||
|
||||
auto authSignature = claim.getString("signature");
|
||||
auto signedClaim = claim.get("claim");
|
||||
if (!authPublicKey.verifyMessage(signedClaim.repr(0, true), authSignature))
|
||||
return false;
|
||||
|
||||
if (!validateClientInnerClaim(signedClaim))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AuthenticationService::validateClientInnerClaim(Variant const& claim) {
|
||||
auto claimMetadata = claim.get("metadata");
|
||||
auto clientPublicKeyData = claimMetadata.getString("clientPublicKey");
|
||||
auto claimSignature = claim.getString("signature");
|
||||
Key clientPublicKey(clientPublicKeyData);
|
||||
if (!clientPublicKey.verifyMessage(claimMetadata.repr(0, true), claimSignature))
|
||||
return false;
|
||||
|
||||
auto validFrom = claimMetadata.getInt("validFrom");
|
||||
auto validTo = claimMetadata.getInt("validTo");
|
||||
|
||||
if ((validFrom > Clock::currentTime()) || (validTo < Clock::currentTime()))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue