<commit_before>/*************************************************************************/
/* hubic-backup - an fast and easy to use hubic backup CLI tool          */
/* Copyright (c) 2015 <NAME>.                                     */
/*                                                                       */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the       */
/* "Software"), to deal in the Software without restriction, including   */
/* without limitation the rights to use, copy, modify, merge, publish,   */
/* distribute, sublicense, and/or sell copies of the Software, and to    */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions:                                             */
/*                                                                       */
/* The above copyright notice and this permission notice shall be        */
/* included in all copies or substantial portions of the Software.       */
/*                                                                       */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
/*************************************************************************/

#include "crypto.h"
#include "common.h"
#include <cassert>
#include <openssl/evp.h>
#include <openssl/rand.h>
#pragma GCC diagnostic push 
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"

static const std::string cKeySaltFormat=
	"<KEY>"
	"EJnv+A!fy==l/zlfdLhK6pNx%*6/LCt4"
	"{}" // Md5(Key)
	"r!H-=6+h94je*Ggadh9-050K!A/cC66d"
	"Fv<+ujbdI1NrI4@1eadxAu1xAhrfjAF4"
	"DG%KDy37puA!wne8Pl2Nh*FpFfDj*1hA"
	"{}" // Md5(I.V.)
	"KM=bDoEvn%GNIaA*%I!66%<dcGD=wNBc"
	"=oj>-tO93zo56=B2z9E!Jprd<c@iFkIl"
	"/b8=m<aEuJLpr4C*bng6kOfB+tB!wOu0"
;


//- /////////////////////////////////////////////////////////////////////////////////////////////////////////

template<unsigned char SIZE>
class CTRandomBytes {
public:
	enum { LENGTH = SIZE };
	
public:
	CTRandomBytes();
	CTRandomBytes( const CTRandomBytes<SIZE> & src);
	CTRandomBytes( const void *);
	CTRandomBytes<SIZE> & operator=( const CTRandomBytes<SIZE> & src);
	~CTRandomBytes();
	
public:
	void generate();
	void set(const unsigned char* src);
	uint8_t operator[](std::size_t i) const { assert( i < LENGTH); return _key[i]; }
	
public:
	operator const unsigned char*() const { return _key; }
	operator unsigned char*() { return _key; }
	
private:
	unsigned char _key[LENGTH];
};

//- /////////////////////////////////////////////////////////////////////////////////////////////////////////

template<unsigned char SIZE>
inline CTRandomBytes<SIZE>::CTRandomBytes() { generate(); }

template<unsigned char SIZE>
inline CTRandomBytes<SIZE>::CTRandomBytes(const void * _p) {
	const unsigned char * p = (const unsigned char *)_p;
	if (p == NULL)
		generate();
	else
		for (int i=0; i<LENGTH; ++i) { _key[i] = p[i]; }
}

template<unsigned char SIZE>
inline CTRandomBytes<SIZE>::CTRandomBytes(const CTRandomBytes<SIZE> & src) {
	for (int i=0; i<LENGTH; ++i) { _key[i] = src._key[i]; }
}

template<unsigned char SIZE>
inline CTRandomBytes<SIZE> & CTRandomBytes<SIZE>::operator=(const CTRandomBytes<SIZE> & src) {
	if (this != &src)
		for (int i=0; i<LENGTH; ++i) { _key[i] = src._key[i]; }
	
	return *this;
}

template<unsigned char SIZE>
inline void CTRandomBytes<SIZE>::set(const unsigned char* src) {
	if (src)
		for (int i=0; i<LENGTH; ++i) { _key[i] = src[i]; }
}

template<unsigned char SIZE>
inline CTRandomBytes<SIZE>::~CTRandomBytes() {
}

template<unsigned char SIZE>
inline void CTRandomBytes<SIZE>::generate() {
	RAND_bytes(_key, LENGTH);
}

//- /////////////////////////////////////////////////////////////////////////////////////////////////////////

typedef CTRandomBytes<8> CSalt;
typedef CTRandomBytes<EVP_MAX_KEY_LENGTH> CKey;
typedef CTRandomBytes<EVP_MAX_IV_LENGTH > CInitialValue;

//- /////////////////////////////////////////////////////////////////////////////////////////////////////////

class CCryptoContextImpl
:	public CCryptoContext
{
public:
	CCryptoContextImpl() {}
	virtual ~CCryptoContextImpl() {}
	bool init( const std::string & pwd, bool salted = true);
	
public:
	const CSalt         & salt() const { return _salt; }
	const CKey          & key () const { return _key; }
	const CInitialValue & iv  () const { return _iv; }

private:
	CSalt         _salt;
	CKey          _key;
	CInitialValue _iv;

};
//- /////////////////////////////////////////////////////////////////////////////////////////////////////////

NMD5::CDigest getCryptoKey(const std::string & pwd)
{
	CCryptoContextImpl c;
	c.init( pwd, false );
	return NMD5::computeMd5(
		fmt::format(cKeySaltFormat,
			NMD5::computeMd5(c.key(), CKey::LENGTH).hex(),
			NMD5::computeMd5(c.iv(), CInitialValue::LENGTH).hex()
		)
	);
}

//- /////////////////////////////////////////////////////////////////////////////////////////////////////////

bool CCryptoContextImpl::init( const std::string & pass, bool salted)
{
	static std::mutex _m;
	std::lock_guard<std::mutex> lock(_m);
	
	static bool _initialized(false);
	if (!_initialized) {
		_initialized = true;
		OpenSSL_add_all_algorithms();
	}
	
	const EVP_CIPHER *cipher;
	cipher = EVP_aes_256_cbc(); //EVP_get_cipherbyname("aes-256-cbc");<commit_msg>Fix aes-256 key length on linux<commit_after>/*************************************************************************/
/* hubic-backup - an fast and easy to use hubic backup CLI tool          */
/* Copyright (c) 2015 <NAME>.                                     */
/*                                                                       */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the       */
/* "Software"), to deal in the Software without restriction, including   */
/* without limitation the rights to use, copy, modify, merge, publish,   */
/* distribute, sublicense, and/or sell copies of the Software, and to    */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions:                                             */
/*                                                                       */
/* The above copyright notice and this permission notice shall be        */
/* included in all copies or substantial portions of the Software.       */
/*                                                                       */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
/*************************************************************************/

#include "crypto.h"
#include "common.h"
#include <cassert>
#include <openssl/evp.h>
#include <openssl/rand.h>
#pragma GCC diagnostic push 
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"

static const std::string cKeySaltFormat=
	"g-D0>5F3uxj+Mytq-eHhppabbtmLkqI1"
	"EJnv+A!fy==l/zlfdLhK6pNx%*6/LCt4"
	"{}" // Md5(Key)
	"r!H-=6+h94je*Ggadh9-050K!A/cC66d"
	"Fv<+ujbdI1NrI4@1eadxAu1xAhrfjAF4"
	"DG%KDy37puA!wne8Pl2Nh*FpFfDj*1hA"
	"{}" // Md5(I.V.)
	"KM=bDoEvn%GNIaA*%I!66%<dcGD=wNBc"
	"=oj>-tO93zo56=B2z9E!Jprd<c@iFkIl"
	"/b8=m<aEuJLpr4C*bng6kOfB+tB!wOu0"
;


//- /////////////////////////////////////////////////////////////////////////////////////////////////////////

template<unsigned char SIZE>
class CTRandomBytes {
public:
	enum { LENGTH = SIZE };
	
public:
	CTRandomBytes();
	CTRandomBytes( const CTRandomBytes<SIZE> & src);
	CTRandomBytes( const void *);
	CTRandomBytes<SIZE> & operator=( const CTRandomBytes<SIZE> & src);
	~CTRandomBytes();
	
public:
	void generate();
	void set(const unsigned char* src);
	uint8_t operator[](std::size_t i) const { assert( i < LENGTH); return _key[i]; }
	std::string hex() const;
	
public:
	operator const unsigned char*() const { return _key; }
	operator unsigned char*() { return _key; }
	
private:
	unsigned char _key[LENGTH];
};

//- /////////////////////////////////////////////////////////////////////////////////////////////////////////

template<unsigned char SIZE>
inline std::string CTRandomBytes<SIZE>::hex() const
{
	std::string res;
	for (int i=0; i<LENGTH; ++i)
		res += fmt::format("{:02x}", static_cast<int>(_key[i]));
	return res;
}

template<unsigned char SIZE>
inline CTRandomBytes<SIZE>::CTRandomBytes() { generate(); }

template<unsigned char SIZE>
inline CTRandomBytes<SIZE>::CTRandomBytes(const void * _p) {
	const unsigned char * p = (const unsigned char *)_p;
	if (p == NULL)
		generate();
	else
		for (int i=0; i<LENGTH; ++i) { _key[i] = p[i]; }
}

template<unsigned char SIZE>
inline CTRandomBytes<SIZE>::CTRandomBytes(const CTRandomBytes<SIZE> & src) {
	for (int i=0; i<LENGTH; ++i) { _key[i] = src._key[i]; }
}

template<unsigned char SIZE>
inline CTRandomBytes<SIZE> & CTRandomBytes<SIZE>::operator=(const CTRandomBytes<SIZE> & src) {
	if (this != &src)
		for (int i=0; i<LENGTH; ++i) { _key[i] = src._key[i]; }
	
	return *this;
}

template<unsigned char SIZE>
inline void CTRandomBytes<SIZE>::set(const unsigned char* src) {
	if (src)
		for (int i=0; i<LENGTH; ++i) { _key[i] = src[i]; }
}

template<unsigned char SIZE>
inline CTRandomBytes<SIZE>::~CTRandomBytes() {
}

template<unsigned char SIZE>
inline void CTRandomBytes<SIZE>::generate() {
	RAND_bytes(_key, LENGTH);
}

//- /////////////////////////////////////////////////////////////////////////////////////////////////////////

typedef CTRandomBytes< 8> CSalt;
typedef CTRandomBytes<32> CKey;
typedef CTRandomBytes<16> CInitialValue;

//- /////////////////////////////////////////////////////////////////////////////////////////////////////////

class CCryptoContextImpl
:	public CCryptoContext
{
public:
	CCryptoContextImpl() {}
	virtual ~CCryptoContextImpl() {}
	bool init( const std::string & pwd, bool salted = true);
	
public:
	const CSalt         & salt() const { return _salt; }
	const CKey          & key () const { return _key; }
	const CInitialValue & iv  () const { return _iv; }

private:
	CSalt         _salt;
	CKey          _key;
	CInitialValue _iv;

};
//- /////////////////////////////////////////////////////////////////////////////////////////////////////////

NMD5::CDigest getCryptoKey(const std::string & pwd)
{
	CCryptoContextImpl c;
	c.init( pwd, false );
	return NMD5::computeMd5(
		fmt::format(cKeySaltFormat,
			c.key().hex(),
			c.iv().hex()
		)
	);
}

//- /////////////////////////////////////////////////////////////////////////////////////////////////////////

bool CCryptoContextImpl::init( const std::string & pass, bool salted)
{
	static std::mutex _m;
	std::lock_guard<std::mutex> lock(_m);
	
	static bool _initialized(false);
	if (!_initialized) {
		_initialized = true;
		OpenSSL_add_all_algorithms();
	}
	
	const EVP_CIPHER *cipher;
	cipher = EVP_aes_256_cbc(); //EVP_get_cipherbyname("aes-256-cbc");
{'fraction_non_alphanumeric': 0.24925588910621652, 'fraction_numerical': 0.010885279360489837, 'mean_word_length': 2.1723765848394927, 'pattern_counts': {'":': 0, '<': 84, '<?xml version=': 0, '>': 68, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 24, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2588147', 'n_tokens_mistral': 3669, 'n_tokens_neox': 3435, 'n_words': 945}