mixed boob
This commit is contained in:
parent
922f801c96
commit
75495fc976
10 changed files with 281 additions and 22 deletions
|
@ -3,14 +3,18 @@
|
||||||
#define B64_IGNORE 0xFE
|
#define B64_IGNORE 0xFE
|
||||||
#define B64_PADDING 0xFF
|
#define B64_PADDING 0xFF
|
||||||
|
|
||||||
std::string sosc::cgc::base64_encode(const std::string& data) {
|
std::string sosc::cgc::base64_encode(const std::string& data, bool unix) {
|
||||||
return base64_encode(data.c_str(), data.length());
|
return base64_encode(data.c_str(), data.length());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string sosc::cgc::base64_encode(const void* raw, size_t length) {
|
std::string sosc::cgc::base64_encode
|
||||||
|
(const void* raw, size_t length, bool unix)
|
||||||
|
{
|
||||||
uint8_t* data = (uint8_t*)raw;
|
uint8_t* data = (uint8_t*)raw;
|
||||||
const std::string char_table
|
const std::string char_table
|
||||||
= "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
= (unix)
|
||||||
|
? "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
|
||||||
|
: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||||
|
|
||||||
std::string encoded;
|
std::string encoded;
|
||||||
for(size_t i = 0; i < length; i += 3) {
|
for(size_t i = 0; i < length; i += 3) {
|
||||||
|
@ -28,6 +32,7 @@ std::string sosc::cgc::base64_encode(const void* raw, size_t length) {
|
||||||
for(int j = 0; j < 4 - padding; ++j)
|
for(int j = 0; j < 4 - padding; ++j)
|
||||||
encoded += char_table[(index >> (6 * (3 - j))) & 0x3F];
|
encoded += char_table[(index >> (6 * (3 - j))) & 0x3F];
|
||||||
|
|
||||||
|
if(!unix)
|
||||||
for(int j = 0; j < padding; ++j)
|
for(int j = 0; j < padding; ++j)
|
||||||
encoded += '=';
|
encoded += '=';
|
||||||
}
|
}
|
||||||
|
@ -35,6 +40,21 @@ std::string sosc::cgc::base64_encode(const void* raw, size_t length) {
|
||||||
return encoded;
|
return encoded;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint8_t radix64_decode_char(char c) {
|
||||||
|
if(c >= '0' && c <= '9')
|
||||||
|
return c - '0' + 2;
|
||||||
|
else if(c >= 'A' && c <= 'Z')
|
||||||
|
return c - 'A' + 12;
|
||||||
|
else if(c >= 'a' && c <= 'z')
|
||||||
|
return c - 'a' + 38;
|
||||||
|
else if(c == '.')
|
||||||
|
return 0;
|
||||||
|
else if(c == '/')
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return B64_IGNORE;
|
||||||
|
}
|
||||||
|
|
||||||
static uint8_t base64_decode_char(char c) {
|
static uint8_t base64_decode_char(char c) {
|
||||||
if(c >= 'A' && c <= 'Z')
|
if(c >= 'A' && c <= 'Z')
|
||||||
return c - 'A';
|
return c - 'A';
|
||||||
|
@ -62,12 +82,13 @@ static void base64_decode_append(std::string* decoded, int data) {
|
||||||
*decoded += (char)data;
|
*decoded += (char)data;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string sosc::cgc::base64_decode(const std::string& data) {
|
std::string sosc::cgc::base64_decode(const std::string& data, bool unix) {
|
||||||
std::string decoded;
|
std::string decoded;
|
||||||
int index = 0, j = 0;
|
int index = 0, j = 0;
|
||||||
|
|
||||||
for(std::string::size_type i = 0; i < data.length(); ++i) {
|
for(std::string::size_type i = 0; i < data.length(); ++i) {
|
||||||
int sextet = base64_decode_char(data[i]);
|
int sextet = unix ? radix64_decode_char(data[i])
|
||||||
|
: base64_decode_char(data[i]);
|
||||||
|
|
||||||
if(sextet == B64_IGNORE || sextet == B64_PADDING) {
|
if(sextet == B64_IGNORE || sextet == B64_PADDING) {
|
||||||
if(sextet == B64_PADDING && i >= data.length() - 2 && j > 1)
|
if(sextet == B64_PADDING && i >= data.length() - 2 && j > 1)
|
||||||
|
|
|
@ -7,10 +7,10 @@
|
||||||
|
|
||||||
namespace sosc {
|
namespace sosc {
|
||||||
namespace cgc {
|
namespace cgc {
|
||||||
std::string base64_encode(const std::string& data);
|
std::string base64_encode(const std::string& data, bool unix = false);
|
||||||
std::string base64_encode(const void* raw, size_t length);
|
std::string base64_encode(const void* raw, size_t length, bool unix = false);
|
||||||
|
|
||||||
std::string base64_decode(const std::string& data);
|
std::string base64_decode(const std::string& data, bool unix = false);
|
||||||
}}
|
}}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
15
server/src/crypto/bcrypt.cpp
Normal file
15
server/src/crypto/bcrypt.cpp
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
#include "bcrypt.hpp"
|
||||||
|
|
||||||
|
std::string sosc::cgc::bcrypt_hash(const std::string& input) {
|
||||||
|
std::string salt = csprng::next_bytes(16),
|
||||||
|
input_t = input.substr(0, 72);
|
||||||
|
|
||||||
|
Blowfish bfish;
|
||||||
|
|
||||||
|
std::stringstream stream;
|
||||||
|
stream << "$2b$" << BCRYPT_COST << "$"
|
||||||
|
<< base64_encode(salt, true)
|
||||||
|
<< "b";
|
||||||
|
|
||||||
|
return stream.str();
|
||||||
|
}
|
18
server/src/crypto/bcrypt.hpp
Normal file
18
server/src/crypto/bcrypt.hpp
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
#ifndef SOSC_CRYPTO_BCRYPT_H
|
||||||
|
#define SOSC_CRYPTO_BCRYPT_H
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
#include "base64.hpp"
|
||||||
|
#include "bfish.hpp"
|
||||||
|
#include "../utils/csprng.hpp"
|
||||||
|
|
||||||
|
#define BCRYPT_COST 10
|
||||||
|
|
||||||
|
namespace sosc {
|
||||||
|
namespace cgc {
|
||||||
|
std::string bcrypt_hash(const std::string& input);
|
||||||
|
bool bcrypt_check(std::string input, std::string hash);
|
||||||
|
}}
|
||||||
|
|
||||||
|
#endif
|
|
@ -184,14 +184,48 @@ static const uint32_t init_sbox[4][256] = {
|
||||||
0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6}
|
0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void swap(uint32_t& a, uint32_t& b) {
|
||||||
|
uint32_t temp = a;
|
||||||
|
a = b;
|
||||||
|
b = temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pack_bytes
|
||||||
|
(const std::string& data, std::string::size_type i,
|
||||||
|
uint32_t& left, uint32_t& right)
|
||||||
|
{
|
||||||
|
left = right = 0;
|
||||||
|
for(int j = 0; j < 8; ++j) {
|
||||||
|
if(j < 4)
|
||||||
|
left = (left << 8) | (data[(i + j) % data.length()] & 0xFF);
|
||||||
|
else
|
||||||
|
right = (right << 8) | (data[(i + j) % data.length()] & 0xFF);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void unpack_bytes
|
||||||
|
(std::string& data, std::string::size_type i,
|
||||||
|
uint32_t left, uint32_t right)
|
||||||
|
{
|
||||||
|
for(int j = 0; j < 8; ++j) {
|
||||||
|
if(j < 4) {
|
||||||
|
data[i + (3 - j)] = left & 0xFF;
|
||||||
|
left >>= 8;
|
||||||
|
} else {
|
||||||
|
data[i + (7 - j + 4)] = right & 0xFF;
|
||||||
|
right >>= 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sosc::cgc::Blowfish::Blowfish(const std::string& key) {
|
sosc::cgc::Blowfish::Blowfish(const std::string& key) {
|
||||||
|
std::memcpy(this->parr, init_parr, sizeof(init_parr));
|
||||||
|
std::memcpy(this->sbox, init_sbox, sizeof(init_sbox));
|
||||||
|
|
||||||
this->SetKey(key.c_str(), key.length());
|
this->SetKey(key.c_str(), key.length());
|
||||||
}
|
}
|
||||||
|
|
||||||
void sosc::cgc::Blowfish::SetKey(const char* key, size_t length) {
|
void sosc::cgc::Blowfish::SetKey(const char* key, size_t length) {
|
||||||
std::memcpy(this->parr, init_parr, sizeof(init_parr));
|
|
||||||
std::memcpy(this->sbox, init_sbox, sizeof(init_sbox));
|
|
||||||
|
|
||||||
for(int i = 0; i < 18; ++i) {
|
for(int i = 0; i < 18; ++i) {
|
||||||
uint32_t data = 0;
|
uint32_t data = 0;
|
||||||
for(int j = 0; j < 4; ++j)
|
for(int j = 0; j < 4; ++j)
|
||||||
|
@ -216,19 +250,99 @@ void sosc::cgc::Blowfish::SetKey(const char* key, size_t length) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void sosc::cgc::Blowfish::SetEksKey
|
||||||
|
(const std::string& data, const std::string& key)
|
||||||
|
{
|
||||||
|
for(int i = 0; i < 18; ++i) {
|
||||||
|
uint32_t pack = 0;
|
||||||
|
for(int j = 0; j < 4; ++j)
|
||||||
|
pack = (pack << 8) | key[(i * 4 + j) % key.length()];
|
||||||
|
|
||||||
|
this->parr[i] ^= pack;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 0; i < 18; i += 2) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::string sosc::cgc::Blowfish::Encrypt(std::string data) const {
|
std::string sosc::cgc::Blowfish::Encrypt(std::string data) const {
|
||||||
size_t pad_length = data.size() % sizeof(uint64_t);
|
int pad_length = data.length() % sizeof(uint64_t);
|
||||||
pad_length = sizeof(uint64_t) - pad_length;
|
pad_length = sizeof(uint64_t) - pad_length;
|
||||||
|
|
||||||
for(size_t i = 0; i < pad_length; ++i)
|
for(int i = 0; i < pad_length; ++i)
|
||||||
data.push_back(0);
|
data.push_back(0);
|
||||||
|
|
||||||
for(int i = 0; i < data.size() / sizeof(uint64_t); ++i) {
|
for(std::string::size_type i = 0; i < data.size(); i += 8) {
|
||||||
uint32_t* left = &(((uint32_t*)data.data())[i * 2]);
|
uint32_t left, right;
|
||||||
uint32_t* right = &(((uint32_t*)data.data())[i * 2 + 1]);
|
|
||||||
|
|
||||||
EncryptBlock(left, right);
|
pack_bytes(data, i, left, right);
|
||||||
|
this->EncryptBlock(&left, &right);
|
||||||
|
unpack_bytes(data, i, left, right);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string sosc::cgc::Blowfish::Decrypt(std::string data) const {
|
||||||
|
if(data.length() % sizeof(uint64_t) != 0)
|
||||||
|
return "";
|
||||||
|
|
||||||
|
for(std::string::size_type i = 0; i < data.size(); i += 8) {
|
||||||
|
uint32_t left, right;
|
||||||
|
|
||||||
|
pack_bytes(data, i, left, right);
|
||||||
|
this->DecryptBlock(&left, &right);
|
||||||
|
unpack_bytes(data, i, left, right);
|
||||||
|
}
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
for(;; i++)
|
||||||
|
if(data[data.length() - i - 1] != 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
data.resize(data.length() - i);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sosc::cgc::Blowfish::EncryptBlock
|
||||||
|
(uint32_t* left, uint32_t* right) const
|
||||||
|
{
|
||||||
|
uint32_t left_t = *left,
|
||||||
|
right_t = *right;
|
||||||
|
|
||||||
|
for(int i = 0; i < 16; ++i) {
|
||||||
|
left_t ^= this->parr[i];
|
||||||
|
right_t ^= this->Feistel(left_t);
|
||||||
|
swap(left_t, right_t);
|
||||||
|
}
|
||||||
|
|
||||||
|
swap(left_t, right_t);
|
||||||
|
right_t ^= this->parr[16];
|
||||||
|
left_t ^= this->parr[17];
|
||||||
|
|
||||||
|
*left = left_t;
|
||||||
|
*right = right_t;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sosc::cgc::Blowfish::DecryptBlock
|
||||||
|
(uint32_t* left, uint32_t* right) const
|
||||||
|
{
|
||||||
|
uint32_t left_t = *left,
|
||||||
|
right_t = *right;
|
||||||
|
|
||||||
|
for(int i = 17; i > 1; --i) {
|
||||||
|
left_t ^= this->parr[i];
|
||||||
|
right_t ^= this->Feistel(left_t);
|
||||||
|
swap(left_t, right_t);
|
||||||
|
}
|
||||||
|
|
||||||
|
swap(left_t, right_t);
|
||||||
|
right_t ^= this->parr[1];
|
||||||
|
left_t ^= this->parr[0];
|
||||||
|
|
||||||
|
*left = left_t;
|
||||||
|
*right = right_t;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t sosc::cgc::Blowfish::Feistel(uint32_t input) const {
|
uint32_t sosc::cgc::Blowfish::Feistel(uint32_t input) const {
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include "bcrypt.hpp"
|
||||||
|
|
||||||
namespace sosc {
|
namespace sosc {
|
||||||
namespace cgc {
|
namespace cgc {
|
||||||
|
@ -11,9 +12,11 @@ public:
|
||||||
Blowfish(const std::string& key);
|
Blowfish(const std::string& key);
|
||||||
|
|
||||||
std::string Encrypt(std::string data) const;
|
std::string Encrypt(std::string data) const;
|
||||||
std::string Decrypt(const std::string& data) const;
|
std::string Decrypt(std::string data) const;
|
||||||
private:
|
private:
|
||||||
|
Blowfish();
|
||||||
void SetKey(const char* key, size_t length);
|
void SetKey(const char* key, size_t length);
|
||||||
|
void SetEksKey(const std::string& data, const std::string& key);
|
||||||
|
|
||||||
void EncryptBlock(uint32_t* left, uint32_t* right) const;
|
void EncryptBlock(uint32_t* left, uint32_t* right) const;
|
||||||
void DecryptBlock(uint32_t* left, uint32_t* right) const;
|
void DecryptBlock(uint32_t* left, uint32_t* right) const;
|
||||||
|
@ -21,6 +24,8 @@ private:
|
||||||
|
|
||||||
uint32_t parr[18];
|
uint32_t parr[18];
|
||||||
uint32_t sbox[4][256];
|
uint32_t sbox[4][256];
|
||||||
|
|
||||||
|
friend std::string sosc::cgc::bcrypt_hash(const std::string&);
|
||||||
};
|
};
|
||||||
}}
|
}}
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
#include "sock/tcpsock.hpp"
|
#include "sock/tcpsock.hpp"
|
||||||
#include "crypto/sha1.hpp"
|
#include "crypto/sha1.hpp"
|
||||||
#include "crypto/base64.hpp"
|
#include "crypto/base64.hpp"
|
||||||
|
#include "crypto/bfish.hpp"
|
||||||
|
#include "utils/csprng.hpp"
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
//auto sock = sosc::TcpClient();
|
//auto sock = sosc::TcpClient();
|
||||||
|
@ -32,5 +34,12 @@ int main(int argc, char **argv) {
|
||||||
|
|
||||||
//std::string a = sosc::cgc::sha1("test", true);
|
//std::string a = sosc::cgc::sha1("test", true);
|
||||||
|
|
||||||
|
sosc::cgc::Blowfish fish("");
|
||||||
|
|
||||||
|
std::string test = fish.Encrypt("imagine a test");
|
||||||
|
std::string testd = fish.Decrypt(test);
|
||||||
|
|
||||||
|
uint32_t teest = sosc::csprng::next<uint32_t>();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
58
server/src/utils/csprng.cpp
Normal file
58
server/src/utils/csprng.cpp
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
#include "csprng.hpp"
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
// TODO update win32 code to use csprng in advapi32.lib
|
||||||
|
// NOTE RUNNING ON WINDOWS IS INSECURE DO NOT DOD !!!
|
||||||
|
|
||||||
|
#include <ctime>
|
||||||
|
|
||||||
|
static struct __rng_ctx {
|
||||||
|
std::default_random_engine rng;
|
||||||
|
std::mutex rng_mtx;
|
||||||
|
|
||||||
|
__rng_ctx() : rng(time(NULL)) { }
|
||||||
|
} _rng_ctx;
|
||||||
|
|
||||||
|
std::string sosc::csprng::next_bytes(std::string::size_type count) {
|
||||||
|
_rng_ctx.rng_mtx.lock();
|
||||||
|
|
||||||
|
std::string rand_bytes;
|
||||||
|
for(std::string::size_type i = 0; i < count; ++i)
|
||||||
|
rand_bytes += (char)_rng_ctx.rng();
|
||||||
|
|
||||||
|
_rng_ctx.rng_mtx.unlock();
|
||||||
|
return rand_bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
static struct __rng_ctx {
|
||||||
|
std::ifstream urand;
|
||||||
|
std::mutex rng_mtx;
|
||||||
|
|
||||||
|
__rng_ctx() {
|
||||||
|
this->urand.open("/dev/urandom",
|
||||||
|
std::ifstream::in | std::ifstream::binary);
|
||||||
|
|
||||||
|
if(!this->urand.good())
|
||||||
|
throw "Could not establish csprng context.";
|
||||||
|
}
|
||||||
|
|
||||||
|
~__rng_ctx() {
|
||||||
|
this->urand.close();
|
||||||
|
}
|
||||||
|
} _rng_ctx;
|
||||||
|
|
||||||
|
std::string sosc::csprng::next_bytes(std::string::size_type count) {
|
||||||
|
_rng_ctx.rng_mtx.lock();
|
||||||
|
|
||||||
|
char* buffer = new char[count];
|
||||||
|
_rng_ctx.urand.read(buffer, count);
|
||||||
|
std::string rand_bytes(buffer, count);
|
||||||
|
delete[] buffer;
|
||||||
|
|
||||||
|
_rng_ctx.rng_mtx.unlock();
|
||||||
|
return rand_bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
19
server/src/utils/csprng.hpp
Normal file
19
server/src/utils/csprng.hpp
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
#ifndef SOSC_UTIL_CSPRNG_H
|
||||||
|
#define SOSC_UTIL_CSPRNG_H
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include <string>
|
||||||
|
#include <mutex>
|
||||||
|
#include <random>
|
||||||
|
|
||||||
|
namespace sosc {
|
||||||
|
namespace csprng {
|
||||||
|
std::string next_bytes(std::string::size_type count);
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
T next() {
|
||||||
|
return *((T*)(next_bytes(sizeof(T)).c_str()));
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in a new issue