v1.4.4
This commit is contained in:
commit
9c94d113d3
10260 changed files with 1237388 additions and 0 deletions
24
attic/authentication/CMakeLists.txt
Normal file
24
attic/authentication/CMakeLists.txt
Normal file
|
@ -0,0 +1,24 @@
|
|||
INCLUDE_DIRECTORIES (
|
||||
${STAR_CORE_INCLUDES}
|
||||
${STAR_AUTHENTICATION_INCLUDES}
|
||||
)
|
||||
|
||||
SET (authentication_HEADERS
|
||||
StarAuthenticationDatabaseFacade.hpp
|
||||
StarAuthenticationKey.hpp
|
||||
StarAuthenticationService.hpp
|
||||
StarAuthenticationConnection.hpp
|
||||
StarClientAuthentication.hpp
|
||||
StarServerAuthentication.hpp
|
||||
)
|
||||
|
||||
SET (authentication_SOURCES
|
||||
StarAuthenticationKey.cpp
|
||||
StarAuthenticationService.cpp
|
||||
StarAuthenticationConnection.cpp
|
||||
StarClientAuthentication.cpp
|
||||
StarServerAuthentication.cpp
|
||||
)
|
||||
|
||||
ADD_LIBRARY (star_authentication ${authentication_SOURCES} ${authentication_HEADERS})
|
||||
TARGET_LINK_LIBRARIES (star_authentication star)
|
65
attic/authentication/StarAuthenticationConnection.cpp
Normal file
65
attic/authentication/StarAuthenticationConnection.cpp
Normal file
|
@ -0,0 +1,65 @@
|
|||
#include "StarAuthenticationConnection.hpp"
|
||||
#include "StarClock.hpp"
|
||||
#include "StarTcp.hpp"
|
||||
|
||||
namespace Star {
|
||||
namespace Auth {
|
||||
|
||||
AuthenticationConnection::AuthenticationConnection(String const& authServer, int port) {
|
||||
m_authServer = authServer;
|
||||
m_port = port;
|
||||
}
|
||||
|
||||
String AuthenticationConnection::query(String const& request) {
|
||||
auto socket = TcpSocket::connectTo(HostAddress(m_authServer, m_port));
|
||||
socket->setNoDelay(true);
|
||||
socket->setSocketTimeout(AuthRequestTimeout);
|
||||
|
||||
String requestHeader = "POST /auth.sb HTTP/1.1\r\nHost: " + m_authServer + "\r\nContent-Type: application/json\r\nConnection: close\r\n\r\n";
|
||||
socket->writeFull(requestHeader.utf8Ptr(), requestHeader.utf8Size());
|
||||
socket->writeFull(request.utf8Ptr(), request.utf8Size());
|
||||
String requestFooter = "\r\n\r\n";
|
||||
socket->writeFull(requestFooter.utf8Ptr(), requestFooter.utf8Size());
|
||||
socket->flush();
|
||||
|
||||
int64_t deadline = Clock::currentTime() + AuthRequestTimeout;
|
||||
Buffer buffer(ResponseBufferCapacity);
|
||||
bool headerMode = true;
|
||||
int newlineCounter = 0;
|
||||
while (socket->isOpen()) {
|
||||
if (Clock::currentTime() >= deadline) {
|
||||
throw StarException("Timeout reading auth server response.");
|
||||
}
|
||||
char c;
|
||||
socket->readFull(&c, 1);
|
||||
throw StarException("Unexpected result from socket read.");
|
||||
if (c == '\r')
|
||||
continue;
|
||||
buffer.writeFull(&c, 1);
|
||||
if (buffer.pos() >= ResponseBufferCapacity) {
|
||||
throw StarException("Auth server response too long.");
|
||||
}
|
||||
if (c == '\n')
|
||||
newlineCounter++;
|
||||
else
|
||||
newlineCounter = 0;
|
||||
if (newlineCounter == 2) {
|
||||
if (headerMode) {
|
||||
String header = String(buffer.ptr(), buffer.pos());
|
||||
if (!header.beginsWith("HTTP/1.1 200 OK\n")) {
|
||||
throw StarException("Auth server invalid response.");
|
||||
}
|
||||
headerMode = false;
|
||||
buffer.clear();
|
||||
newlineCounter = 0;
|
||||
}
|
||||
else {
|
||||
return String(buffer.ptr(), buffer.pos() - 2); // remove trailing newlines, guaranteed to be there
|
||||
}
|
||||
}
|
||||
}
|
||||
throw StarException("Connection lost.");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
28
attic/authentication/StarAuthenticationConnection.hpp
Normal file
28
attic/authentication/StarAuthenticationConnection.hpp
Normal file
|
@ -0,0 +1,28 @@
|
|||
#ifndef _STAR_AUTHENTICATION_CONNECTION_HPP_
|
||||
#define _STAR_AUTHENTICATION_CONNECTION_HPP_
|
||||
|
||||
#include "StarVariant.hpp"
|
||||
|
||||
namespace Star {
|
||||
|
||||
namespace Auth {
|
||||
|
||||
static int const AuthRequestTimeout = 10*1000;
|
||||
static int const ResponseBufferCapacity = 15*1024;
|
||||
|
||||
class AuthenticationConnection {
|
||||
public:
|
||||
AuthenticationConnection(String const& authServer, int port);
|
||||
|
||||
String query(String const& request);
|
||||
|
||||
private:
|
||||
String m_authServer;
|
||||
int m_port;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
27
attic/authentication/StarAuthenticationDatabaseFacade.hpp
Normal file
27
attic/authentication/StarAuthenticationDatabaseFacade.hpp
Normal file
|
@ -0,0 +1,27 @@
|
|||
#ifndef _STAR_AUTHENTICATION_DATABASE_HPP_
|
||||
#define _STAR_AUTHENTICATION_DATABASE_HPP_
|
||||
|
||||
#include "StarException.hpp"
|
||||
#include "StarVariant.hpp"
|
||||
|
||||
namespace Star {
|
||||
|
||||
namespace Auth {
|
||||
|
||||
class Database {
|
||||
public:
|
||||
virtual ~Database() {}
|
||||
|
||||
virtual bool validateUser(String const& username) = 0;
|
||||
virtual bool validateUserAndPassword(String const& username, String const& passwordPreHashed) = 0;
|
||||
virtual bool setUserRecord(String const& username, String const& passwordPreHashed, bool active) = 0;
|
||||
virtual bool activateUserRecord(String const& username, bool active) = 0;
|
||||
virtual int usersCount() = 0;
|
||||
};
|
||||
typedef shared_ptr<Database> DatabasePtr;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
437
attic/authentication/StarAuthenticationKey.cpp
Normal file
437
attic/authentication/StarAuthenticationKey.cpp
Normal file
|
@ -0,0 +1,437 @@
|
|||
#include "StarAuthenticationKey.hpp"
|
||||
#include "StarClock.hpp"
|
||||
#include "StarEncode.hpp"
|
||||
#include "StarSha256.hpp"
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/des.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/buffer.h>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <cstring>
|
||||
#include <openssl/x509.h>
|
||||
#include <vector>
|
||||
#include "StarRandom.hpp"
|
||||
|
||||
namespace Star {
|
||||
|
||||
namespace Auth {
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, const Key &key) {
|
||||
return out << "Private Key :" << key.privateKey() << std::endl << " Public Key :" << key.publicKey() << std::endl;
|
||||
}
|
||||
|
||||
Key::Key() : m_key(NULL), m_mdCtx(NULL) {
|
||||
// ERR_load_crypto_strings will only load things once even if called multiple times
|
||||
ERR_load_crypto_strings();
|
||||
m_key = EVP_PKEY_new();
|
||||
if (m_key == NULL)
|
||||
throw CryptoException("Unable to Establish Key Container");
|
||||
m_mdCtx = EVP_MD_CTX_create();
|
||||
if (m_mdCtx == NULL) {
|
||||
EVP_PKEY_free(m_key);
|
||||
m_key = NULL;
|
||||
throw CryptoException("Unable to Establish EVP Message Digest Context");
|
||||
}
|
||||
}
|
||||
|
||||
Key::Key(bool generate) : Key() {
|
||||
if (generate) {
|
||||
regenerate();
|
||||
}
|
||||
}
|
||||
|
||||
Key::Key(String const& key, bool privateKey) : Key() {
|
||||
if (privateKey) {
|
||||
loadPrivateKey(key);
|
||||
} else {
|
||||
loadPublicKey(key);
|
||||
}
|
||||
}
|
||||
|
||||
Key::~Key() {
|
||||
if (m_key != NULL)
|
||||
EVP_PKEY_free(m_key);
|
||||
if (m_mdCtx != NULL)
|
||||
EVP_MD_CTX_destroy(m_mdCtx);
|
||||
// We could call ERR_free_strings but that would just mean the next Key
|
||||
// to be created would make ERR_load_crypto_strings actually process
|
||||
// so eliminate that thrashing by not calling ERR_free_strings
|
||||
}
|
||||
|
||||
void Key::regenerate() {
|
||||
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
|
||||
if (EVP_PKEY_keygen_init(ctx) <= 0)
|
||||
throw cryptoException(ctx, "Unable to initialize EVP Key Generator");
|
||||
if (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, KeySize) <= 0)
|
||||
throw cryptoException(ctx, "Unable to set EVP Key Generator size");
|
||||
if (EVP_PKEY_keygen(ctx, &m_key) <= 0)
|
||||
throw cryptoException(ctx, "Unable to generate new Client Key");
|
||||
EVP_PKEY_CTX_free(ctx);
|
||||
m_isPrivate = 1;
|
||||
}
|
||||
|
||||
CryptoException Key::cryptoException(BIO *bio, const char* errorString) const {
|
||||
unsigned long err = ERR_get_error();
|
||||
BIO_free_all(bio);
|
||||
if (errorString == nullptr) {
|
||||
errorString = ERR_error_string(err, NULL);
|
||||
}
|
||||
return CryptoException(ERR_error_string(err, NULL));
|
||||
}
|
||||
|
||||
CryptoException Key::cryptoException(EVP_PKEY_CTX *ctx, const char* errorString) const {
|
||||
unsigned long err = ERR_get_error();
|
||||
EVP_PKEY_CTX_free(ctx);
|
||||
if (errorString == nullptr) {
|
||||
errorString = ERR_error_string(err, NULL);
|
||||
}
|
||||
return CryptoException(errorString);
|
||||
}
|
||||
|
||||
void Key::loadPrivateKey(String const& key) {
|
||||
if (key.empty())
|
||||
throw StarException("Empty key.");
|
||||
BIO *bIn = BIO_push(
|
||||
BIO_new(BIO_f_base64()),
|
||||
BIO_new_mem_buf((void*) key.utf8Ptr(), key.utf8Size())
|
||||
);
|
||||
BIO_set_flags(bIn, BIO_FLAGS_BASE64_NO_NL);
|
||||
|
||||
RSA * rsa;
|
||||
if ((rsa = d2i_RSAPrivateKey_bio(bIn, NULL)) == 0)
|
||||
throw cryptoException(bIn);
|
||||
|
||||
EVP_PKEY_set1_RSA(m_key, rsa);
|
||||
BIO_free_all(bIn);
|
||||
m_isPrivate = 1;
|
||||
}
|
||||
|
||||
void Key::loadPublicKey(String const& key) {
|
||||
if (key.empty())
|
||||
throw StarException("Empty key.");
|
||||
BIO *bIn = BIO_push(
|
||||
BIO_new(BIO_f_base64()),
|
||||
BIO_new_mem_buf((void*) key.utf8Ptr(), key.utf8Size())
|
||||
);
|
||||
BIO_set_flags(bIn, BIO_FLAGS_BASE64_NO_NL);
|
||||
|
||||
RSA * rsa;
|
||||
if ((rsa = d2i_RSAPublicKey_bio(bIn, NULL)) == 0)
|
||||
throw cryptoException(bIn);
|
||||
|
||||
EVP_PKEY_set1_RSA(m_key, rsa);
|
||||
BIO_free_all(bIn);
|
||||
m_isPrivate = 0;
|
||||
}
|
||||
|
||||
String Key::publicKey() const {
|
||||
BIO *b64 = BIO_push(
|
||||
BIO_new(BIO_f_base64()),
|
||||
BIO_new(BIO_s_mem())
|
||||
);
|
||||
BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
|
||||
|
||||
i2d_RSAPublicKey_bio(b64, EVP_PKEY_get1_RSA(m_key));
|
||||
(void) BIO_flush(b64);
|
||||
|
||||
BUF_MEM *bPtr;
|
||||
BIO_get_mem_ptr(b64, &bPtr);
|
||||
String out(bPtr->data, bPtr->length);
|
||||
BIO_free_all(b64);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
String Key::privateKey() const {
|
||||
if (!m_isPrivate)
|
||||
throw CryptoException("Private Key not loaded.");
|
||||
BIO *b64 = BIO_push(
|
||||
BIO_new(BIO_f_base64()),
|
||||
BIO_new(BIO_s_mem())
|
||||
);
|
||||
BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
|
||||
|
||||
i2d_RSAPrivateKey_bio(b64, EVP_PKEY_get1_RSA(m_key));
|
||||
(void) BIO_flush(b64);
|
||||
|
||||
BUF_MEM *bPtr;
|
||||
BIO_get_mem_ptr(b64, &bPtr);
|
||||
String out(bPtr->data, bPtr->length);
|
||||
BIO_free_all(b64);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
String Key::encryptMessage(String const& message) const {
|
||||
size_t bufLen;
|
||||
unsigned char * buf;
|
||||
|
||||
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(m_key, NULL);
|
||||
if (EVP_PKEY_encrypt_init(ctx) != 1)
|
||||
throw cryptoException(ctx);
|
||||
|
||||
if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) != 1)
|
||||
throw cryptoException(ctx);
|
||||
|
||||
if (EVP_PKEY_encrypt(ctx, NULL, &bufLen, (unsigned char *) message.utf8Ptr(), message.utf8Size()) != 1)
|
||||
throw cryptoException(ctx);
|
||||
|
||||
buf = new unsigned char[bufLen];
|
||||
if (EVP_PKEY_encrypt(ctx, (unsigned char *) buf, &bufLen, (unsigned char *) message.utf8Ptr(), message.utf8Size()) <= 0) {
|
||||
delete[] buf;
|
||||
throw cryptoException(ctx);
|
||||
}
|
||||
EVP_PKEY_CTX_free(ctx);
|
||||
|
||||
String oString(base64Encode((char const*)buf, bufLen));
|
||||
delete[] buf;
|
||||
return oString;
|
||||
}
|
||||
|
||||
String Key::decryptMessage(String const& cryptText) const {
|
||||
ByteArray iString(base64Decode(cryptText));
|
||||
size_t bufLen;
|
||||
unsigned char * buf;
|
||||
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(m_key, NULL);
|
||||
if (EVP_PKEY_decrypt_init(ctx) <= 0)
|
||||
throw cryptoException(ctx);
|
||||
if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) <= 0)
|
||||
throw cryptoException(ctx);
|
||||
if (EVP_PKEY_decrypt(ctx, NULL, &bufLen, (unsigned char *) iString.ptr(), iString.size()) <= 0)
|
||||
throw cryptoException(ctx);
|
||||
buf = new unsigned char[bufLen];
|
||||
if (EVP_PKEY_decrypt(ctx, (unsigned char *) buf, &bufLen, (unsigned char *) iString.ptr(), iString.size()) != 1) {
|
||||
delete[] buf;
|
||||
throw cryptoException(ctx);
|
||||
}
|
||||
EVP_PKEY_CTX_free(ctx);
|
||||
String oString((const char *) buf, bufLen);
|
||||
delete[] buf;
|
||||
return oString;
|
||||
}
|
||||
|
||||
String Key::signMessage(String const& message) const {
|
||||
if (!m_isPrivate)
|
||||
throw CryptoException("Private Key not Loaded");
|
||||
size_t sigLen;
|
||||
unsigned char *sig;
|
||||
ByteArray shaMessage(sha256(ByteArray(message.utf8Ptr(), message.utf8Size())));
|
||||
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(m_key, NULL);
|
||||
if (EVP_PKEY_sign_init(ctx) <= 0)
|
||||
throw cryptoException(ctx);
|
||||
if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PSS_PADDING) <= 0)
|
||||
throw cryptoException(ctx);
|
||||
if (EVP_PKEY_CTX_set_signature_md(ctx, EVP_sha256()) <= 0)
|
||||
throw cryptoException(ctx);
|
||||
if (EVP_PKEY_sign(ctx, NULL, &sigLen, (unsigned char *) shaMessage.ptr(), shaMessage.size()) <= 0)
|
||||
throw cryptoException(ctx);
|
||||
if (!(sig = (unsigned char *) OPENSSL_malloc(sigLen)))
|
||||
throw cryptoException(ctx);
|
||||
if (EVP_PKEY_sign(ctx, sig, &sigLen, (unsigned char *) shaMessage.ptr(), shaMessage.size()) <= 0)
|
||||
throw cryptoException(ctx);
|
||||
EVP_PKEY_CTX_free(ctx);
|
||||
String oString(base64Encode((const char *)sig, sigLen));
|
||||
OPENSSL_free(sig);
|
||||
return oString;
|
||||
}
|
||||
|
||||
bool Key::verifyMessage(String const& message, String const& signature) const {
|
||||
ByteArray shaMessage(sha256(ByteArray(message.utf8Ptr(), message.utf8Size())));
|
||||
ByteArray rawSignature(base64Decode(signature));
|
||||
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(m_key, NULL);
|
||||
if (EVP_PKEY_verify_init(ctx) <= 0)
|
||||
throw cryptoException(ctx);
|
||||
if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PSS_PADDING) <= 0)
|
||||
throw cryptoException(ctx);
|
||||
if (EVP_PKEY_CTX_set_signature_md(ctx, EVP_sha256()) <= 0)
|
||||
throw cryptoException(ctx);
|
||||
int rv = EVP_PKEY_verify(ctx, (unsigned char *) rawSignature.ptr(), rawSignature.size(), (unsigned char *) shaMessage.ptr(), shaMessage.size());
|
||||
if (rv < 0)
|
||||
throw cryptoException(ctx);
|
||||
EVP_PKEY_CTX_free(ctx);
|
||||
return rv == 1;
|
||||
}
|
||||
|
||||
void initializeKeyLogic() {
|
||||
// intitial initialization of DES_random_key and friends scans the whole heap.
|
||||
// do it as early as possible.
|
||||
generateKey();
|
||||
}
|
||||
|
||||
String generateKey() {
|
||||
// Init desKey to week key to avoid valgrind warning
|
||||
DES_cblock desKey = {0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01};
|
||||
ByteArray key = ByteArray::withReserve(24);
|
||||
|
||||
if (DES_random_key(&desKey) == 0)
|
||||
throw CryptoException("RNG could not generate a secure key");
|
||||
key.append((const char *) desKey, 8);
|
||||
if (DES_random_key(&desKey) == 0)
|
||||
throw CryptoException("RNG could not generate a secure key");
|
||||
key.append((const char *) desKey, 8);
|
||||
if (DES_random_key(&desKey) == 0)
|
||||
throw CryptoException("RNG could not generate a secure key");
|
||||
key.append((const char *) desKey, 8);
|
||||
return base64Encode(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypts a Message
|
||||
* @param message Message to Encrypt
|
||||
* @param key Base64 encoded 24 byte key
|
||||
* @return Base64 Encoded String containing encrypted message
|
||||
*/
|
||||
String encryptMessage(String const& message, String const& key) {
|
||||
DES_cblock desKey;
|
||||
DES_cblock ivec;
|
||||
DES_key_schedule desSchedule1;
|
||||
DES_key_schedule desSchedule2;
|
||||
DES_key_schedule desSchedule3;
|
||||
int n = 0;
|
||||
|
||||
/* Prepare the key for use with DES_cfb64_encrypt */
|
||||
ByteArray iKey(base64Decode(key));
|
||||
if (iKey.size() != 24)
|
||||
throw StarException("Key size mismatch.");
|
||||
|
||||
std::memcpy(desKey, iKey.ptr(), 8);
|
||||
DES_set_odd_parity(&desKey);
|
||||
DES_set_key_checked(&desKey, &desSchedule1);
|
||||
std::memcpy(desKey, iKey.ptr() + 8, 8);
|
||||
DES_set_odd_parity(&desKey);
|
||||
DES_set_key_checked(&desKey, &desSchedule2);
|
||||
std::memcpy(desKey, iKey.ptr() + 16, 8);
|
||||
DES_set_odd_parity(&desKey);
|
||||
DES_set_key_checked(&desKey, &desSchedule3);
|
||||
|
||||
std::memcpy(ivec, iKey.ptr() + 12, 8);
|
||||
|
||||
/* Encryption occurs here */
|
||||
unsigned char * buf = new unsigned char[message.utf8Size()];
|
||||
DES_ede3_cfb64_encrypt((unsigned char *) message.utf8Ptr(), buf, message.utf8Size(), &desSchedule1, &desSchedule2, &desSchedule3, &ivec, &n, DES_ENCRYPT);
|
||||
String output(base64Encode((const char*)buf, message.utf8Size()));
|
||||
delete[] buf;
|
||||
return output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts a Message
|
||||
* @param message Base64 Encoded DES3 encrypted message
|
||||
* @param key Base64 encoded 24 byte key
|
||||
* @return String containing decrypted message
|
||||
*/
|
||||
String decryptMessage(String const& message, String const& key) {
|
||||
DES_cblock desKey;
|
||||
DES_cblock ivec;
|
||||
DES_key_schedule desSchedule1;
|
||||
DES_key_schedule desSchedule2;
|
||||
DES_key_schedule desSchedule3;
|
||||
int n = 0;
|
||||
|
||||
ByteArray iMessage(base64Decode(message));
|
||||
|
||||
/* Prepare the key for use with DES_cfb64_encrypt */
|
||||
ByteArray iKey(base64Decode(key));
|
||||
if (iKey.size() != 24)
|
||||
throw StarException("Key size mismatch.");
|
||||
|
||||
std::memcpy(desKey, iKey.ptr(), 8);
|
||||
DES_set_odd_parity(&desKey);
|
||||
DES_set_key_checked(&desKey, &desSchedule1);
|
||||
std::memcpy(desKey, iKey.ptr() + 8, 8);
|
||||
DES_set_odd_parity(&desKey);
|
||||
DES_set_key_checked(&desKey, &desSchedule2);
|
||||
std::memcpy(desKey, iKey.ptr() + 16, 8);
|
||||
DES_set_odd_parity(&desKey);
|
||||
DES_set_key_checked(&desKey, &desSchedule3);
|
||||
|
||||
std::memcpy(ivec, iKey.ptr() + 12, 8);
|
||||
|
||||
/* Encryption occurs here */
|
||||
unsigned char * buf = new unsigned char[message.utf8Size()];
|
||||
DES_ede3_cfb64_encrypt((unsigned char *) iMessage.ptr(), buf, iMessage.size(), &desSchedule1, &desSchedule2, &desSchedule3, &ivec, &n, DES_DECRYPT);
|
||||
String output((const char *) buf, iMessage.size());
|
||||
delete[] buf;
|
||||
return output;
|
||||
}
|
||||
|
||||
String preHashPassword(String const& username, String const& password) {
|
||||
String passPreHash = username + ":" + password + ":starbound";
|
||||
return base64Encode(sha256(passPreHash.utf8Ptr(), passPreHash.utf8Size()));
|
||||
}
|
||||
|
||||
double const bcrypt_goal_duration = 0.032;
|
||||
double const bcrypt_max_validate_duration = 0.5;
|
||||
double const bcrypt_max_generation_duration = 5.0;
|
||||
int const bcrypt_minimal_rounds = 100;
|
||||
|
||||
String bcrypt(String const& message, String const& salt, int& rounds) {
|
||||
rounds = 0;
|
||||
|
||||
auto startTime = Clock::currentTime();
|
||||
|
||||
ByteArray saltBuffer(salt.utf8Ptr(), salt.utf8Size());
|
||||
ByteArray messageBuffer(sha256(ByteArray(message.utf8Ptr(), message.utf8Size())));
|
||||
ByteArray roundBuffer;
|
||||
|
||||
while ((rounds < bcrypt_minimal_rounds) || (Clock::secondsSince(startTime) < bcrypt_goal_duration)) {
|
||||
roundBuffer.resize(0);
|
||||
roundBuffer.writeFrom(messageBuffer.ptr(), 0, messageBuffer.size());
|
||||
roundBuffer.writeFrom(saltBuffer.ptr(), messageBuffer.size(), saltBuffer.size());
|
||||
sha256(roundBuffer, messageBuffer);
|
||||
rounds++;
|
||||
}
|
||||
return base64Encode(messageBuffer);
|
||||
}
|
||||
|
||||
String bcryptWithRounds(String const& message, String const& salt, int rounds) {
|
||||
if (rounds < bcrypt_minimal_rounds)
|
||||
throw StarException("Not enough rounds for bcrypt.");
|
||||
ByteArray saltBuffer(salt.utf8Ptr(), salt.utf8Size());
|
||||
ByteArray messageBuffer(sha256(ByteArray(message.utf8Ptr(), message.utf8Size())));
|
||||
ByteArray roundBuffer;
|
||||
|
||||
auto startTime = Clock::currentTime();
|
||||
|
||||
while (rounds > 0) {
|
||||
if (Clock::secondsSince(startTime) > bcrypt_max_generation_duration)
|
||||
throw StarException("Timeout generating bcrypt.");
|
||||
roundBuffer.resize(0);
|
||||
roundBuffer.writeFrom(messageBuffer.ptr(), 0, messageBuffer.size());
|
||||
roundBuffer.writeFrom(saltBuffer.ptr(), messageBuffer.size(), saltBuffer.size());
|
||||
sha256(roundBuffer, messageBuffer);
|
||||
rounds--;
|
||||
}
|
||||
return base64Encode(messageBuffer);
|
||||
}
|
||||
|
||||
bool bcryptValidate(String const& message, String const& salt, String const& hash, int rounds) {
|
||||
if (rounds < bcrypt_minimal_rounds)
|
||||
return false;
|
||||
ByteArray saltBuffer(salt.utf8Ptr(), salt.utf8Size());
|
||||
ByteArray messageBuffer(sha256(ByteArray(message.utf8Ptr(), message.utf8Size())));
|
||||
ByteArray roundBuffer;
|
||||
|
||||
auto startTime = Clock::currentTime();
|
||||
|
||||
while (rounds > 0) {
|
||||
if (Clock::secondsSince(startTime) > bcrypt_max_validate_duration)
|
||||
return false;
|
||||
roundBuffer.resize(0);
|
||||
roundBuffer.writeFrom(messageBuffer.ptr(), 0, messageBuffer.size());
|
||||
roundBuffer.writeFrom(saltBuffer.ptr(), messageBuffer.size(), saltBuffer.size());
|
||||
sha256(roundBuffer, messageBuffer);
|
||||
rounds--;
|
||||
}
|
||||
return base64Encode(messageBuffer) == hash;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
68
attic/authentication/StarAuthenticationKey.hpp
Normal file
68
attic/authentication/StarAuthenticationKey.hpp
Normal file
|
@ -0,0 +1,68 @@
|
|||
#ifndef _STAR_AUTHENTICATION_KEY_HPP_
|
||||
#define _STAR_AUTHENTICATION_KEY_HPP_
|
||||
|
||||
#include "StarException.hpp"
|
||||
#include "StarVariant.hpp"
|
||||
#include <openssl/evp.h>
|
||||
#include <string>
|
||||
|
||||
namespace Star {
|
||||
|
||||
namespace Auth {
|
||||
|
||||
STAR_EXCEPTION(CryptoException, StarException);
|
||||
STAR_EXCEPTION(AuthException, StarException);
|
||||
|
||||
class Key {
|
||||
public:
|
||||
Key();
|
||||
Key(bool generate);
|
||||
Key(String const& key, bool privateKey = false);
|
||||
|
||||
~Key();
|
||||
void regenerate();
|
||||
void loadPrivateKey(String const& key);
|
||||
void loadPublicKey(String const& key);
|
||||
bool isPrivateKey() const {
|
||||
return m_isPrivate;
|
||||
}
|
||||
String publicKey() const;
|
||||
String privateKey() const;
|
||||
String encryptMessage(String const& message) const;
|
||||
String decryptMessage(String const& message) const;
|
||||
String signMessage(String const& message) const;
|
||||
bool verifyMessage(String const& message, String const& signature) const;
|
||||
|
||||
private:
|
||||
static int const KeySize = 4096;
|
||||
|
||||
// Deleted copy constructor / assignment operator.
|
||||
Key(Key const& that);
|
||||
Key& operator=(Key const&);
|
||||
|
||||
bool m_isPrivate;
|
||||
EVP_PKEY * m_key;
|
||||
EVP_MD_CTX * m_mdCtx;
|
||||
|
||||
friend std::ostream &operator<<(std::ostream &cout, const Key &key);
|
||||
|
||||
CryptoException cryptoException(EVP_PKEY_CTX *ctx, const char* errorString = nullptr) const;
|
||||
CryptoException cryptoException(BIO *bio, const char* errorString = nullptr) const;
|
||||
};
|
||||
|
||||
void initializeKeyLogic();
|
||||
String generateKey();
|
||||
String encryptMessage(String const& message, String const& key);
|
||||
String decryptMessage(String const& message, String const& key);
|
||||
|
||||
String preHashPassword(String const& username, String const& password);
|
||||
|
||||
String bcrypt(String const& message, String const& salt, int& rounds);
|
||||
String bcryptWithRounds(String const& message, String const& salt, int rounds);
|
||||
bool bcryptValidate(String const& message, String const& salt, String const& hash, int rounds);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
37
attic/authentication/StarAuthenticationService.hpp
Normal file
37
attic/authentication/StarAuthenticationService.hpp
Normal file
|
@ -0,0 +1,37 @@
|
|||
#ifndef _STAR_AUTHENTICATION_SERVICE_HPP_
|
||||
#define _STAR_AUTHENTICATION_SERVICE_HPP_
|
||||
|
||||
#include "StarAuthenticationDatabaseFacade.hpp"
|
||||
#include "StarAuthenticationKey.hpp"
|
||||
#include "StarVariant.hpp"
|
||||
#include "StarVariantExtra.hpp"
|
||||
|
||||
namespace Star {
|
||||
namespace Auth {
|
||||
|
||||
class AuthenticationService {
|
||||
public:
|
||||
static Variant generateAuthenticationConfig(String const& rootPrivateKey, int64_t valid, int64_t expires);
|
||||
static bool validateAuthSignature(Key const& rootPublicKey, Variant const& authSignature);
|
||||
static bool validateClientClaim(Key const& rootPublicKey, Variant const& claim);
|
||||
static bool validateClientInnerClaim(Variant const& claim);
|
||||
|
||||
AuthenticationService(DatabasePtr db);
|
||||
~AuthenticationService();
|
||||
|
||||
Variant getCertificate();
|
||||
Variant authorizeClient(Variant const& request);
|
||||
Variant validateClient(Variant const& request);
|
||||
|
||||
private:
|
||||
Key m_authPrivateKey;
|
||||
Key m_rootPublicKey;
|
||||
DatabasePtr m_db;
|
||||
Variant m_certificate;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
189
attic/authentication/StarClientAuthentication.cpp
Normal file
189
attic/authentication/StarClientAuthentication.cpp
Normal file
|
@ -0,0 +1,189 @@
|
|||
#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");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
71
attic/authentication/StarClientAuthentication.hpp
Normal file
71
attic/authentication/StarClientAuthentication.hpp
Normal file
|
@ -0,0 +1,71 @@
|
|||
#ifndef _STAR_CLIENT_AUTHENTICATION_HPP_
|
||||
#define _STAR_CLIENT_AUTHENTICATION_HPP_
|
||||
|
||||
#include "StarAuthenticationKey.hpp"
|
||||
#include "StarException.hpp"
|
||||
#include "StarVariant.hpp"
|
||||
#include <string>
|
||||
|
||||
namespace Star {
|
||||
|
||||
namespace Auth {
|
||||
|
||||
/*
|
||||
|
||||
<AuthSignature>=
|
||||
{
|
||||
"signedAuthKey" : {
|
||||
"authPublicKey": ...
|
||||
"validFrom":...
|
||||
"validTo":...
|
||||
}
|
||||
"rootSignedAuthKeySignature": <signature made with root privkey>
|
||||
}
|
||||
|
||||
<ClientClaim>=
|
||||
{
|
||||
"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>
|
||||
}
|
||||
|
||||
|
||||
*/
|
||||
|
||||
class ClientAuthentication {
|
||||
public:
|
||||
ClientAuthentication(shared_ptr<Key> const& rootKey);
|
||||
~ClientAuthentication();
|
||||
|
||||
Variant authsvrRequest(String const& username, String const& passwordHash, String const& authClaim, Key const& clientPrivateKey);
|
||||
Variant authsvrResponse(String const& response, Key const& clientPrivateKey);
|
||||
String serverRequest();
|
||||
bool serverResponse(String const& response);
|
||||
|
||||
Variant authsvrValidateRequest(Variant const& claim, String const& authClaim, Key const& clientPrivateKey);
|
||||
bool authsvrValidateResponse(String const& response, Key const& clientPrivateKey);
|
||||
|
||||
private:
|
||||
shared_ptr<Key> m_rootPublicKey;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
37
attic/authentication/StarServerAuthentication.cpp
Normal file
37
attic/authentication/StarServerAuthentication.cpp
Normal file
|
@ -0,0 +1,37 @@
|
|||
#include "StarServerAuthentication.hpp"
|
||||
#include "StarAuthenticationKey.hpp"
|
||||
#include <ctime>
|
||||
|
||||
|
||||
namespace Star {
|
||||
namespace Auth {
|
||||
|
||||
ServerAuthentication::ServerAuthentication(String const& rootPublicKey) {
|
||||
m_rootPublicKey.loadPublicKey(rootPublicKey);
|
||||
}
|
||||
|
||||
ServerAuthentication::~ServerAuthentication() {}
|
||||
|
||||
String ServerAuthentication::authsvrRequest(String const& username, String const& password, String const& hostname, int port, String const& authCertificate) {
|
||||
//le todo
|
||||
_unused(username);
|
||||
_unused(password);
|
||||
_unused(hostname);
|
||||
_unused(port);
|
||||
_unused(authCertificate);
|
||||
return String();
|
||||
}
|
||||
|
||||
bool ServerAuthentication::authsvrResponse(String const& response) {
|
||||
_unused(response);
|
||||
return false;
|
||||
}
|
||||
|
||||
String ServerAuthentication::clientRequest(String const& request) {
|
||||
_unused(request);
|
||||
return String();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
32
attic/authentication/StarServerAuthentication.hpp
Normal file
32
attic/authentication/StarServerAuthentication.hpp
Normal file
|
@ -0,0 +1,32 @@
|
|||
#ifndef _STAR_SERVER_AUTHENTICATION_HPP_
|
||||
#define _STAR_SERVER_AUTHENTICATION_HPP_
|
||||
|
||||
#include "StarAuthenticationKey.hpp"
|
||||
#include "StarVariant.hpp"
|
||||
#include <string>
|
||||
|
||||
namespace Star {
|
||||
|
||||
namespace Auth {
|
||||
|
||||
class ServerAuthentication {
|
||||
public:
|
||||
ServerAuthentication(String const& rootPublicKey);
|
||||
~ServerAuthentication();
|
||||
String authsvrRequest(String const& username, String const& password, String const& hostname, int port, String const& authCertificate);
|
||||
bool authsvrResponse(String const& response);
|
||||
String clientRequest(String const& request);
|
||||
|
||||
private:
|
||||
Auth::Key m_serverPrivateKey;
|
||||
Auth::Key m_authPublicKey;
|
||||
Auth::Key m_rootPublicKey;
|
||||
Variant m_authCertificate;
|
||||
Variant m_serverCertificate;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Add table
Add a link
Reference in a new issue