mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-01 01:07:51 -04:00
remove explicit algorithm parameter (make config variable only), add key length variable
This commit is contained in:
parent
e51ecacdee
commit
62f45b292c
@ -42,11 +42,6 @@ usage() {
|
||||
|
||||
<< "Options:\n\n"
|
||||
|
||||
<< " -a algorithm\n"
|
||||
<< " Specifies the particular encryption algorithm to use. Available\n"
|
||||
<< " algorithm names are defined by OpenSSL. If this is unspecified a\n"
|
||||
<< " default algorithm is selected.\n\n"
|
||||
|
||||
<< " -p \"password\"\n"
|
||||
<< " Specifies the password to use for encryption. There are no\n"
|
||||
<< " restrictions on the password length or contents, but longer passwords\n"
|
||||
@ -58,9 +53,8 @@ int
|
||||
main(int argc, char *argv[]) {
|
||||
extern char *optarg;
|
||||
extern int optind;
|
||||
const char *optstr = "a:p:h";
|
||||
const char *optstr = "p:h";
|
||||
|
||||
string algorithm;
|
||||
string password;
|
||||
bool got_password = false;
|
||||
|
||||
@ -68,10 +62,6 @@ main(int argc, char *argv[]) {
|
||||
|
||||
while (flag != EOF) {
|
||||
switch (flag) {
|
||||
case 'a':
|
||||
algorithm = optarg;
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
password = optarg;
|
||||
got_password = true;
|
||||
@ -129,7 +119,7 @@ main(int argc, char *argv[]) {
|
||||
|
||||
bool fail = false;
|
||||
{
|
||||
OEncryptStream encrypt(&write_stream, false, password, algorithm);
|
||||
OEncryptStream encrypt(&write_stream, false, password);
|
||||
|
||||
int ch = read_stream.get();
|
||||
while (!read_stream.eof() && !read_stream.fail()) {
|
||||
|
@ -79,6 +79,32 @@ config_express.GetDouble("max-dt", -1.0);
|
||||
const double sleep_precision =
|
||||
config_express.GetDouble("sleep-precision", 0.01);
|
||||
|
||||
// This defines the OpenSSL encryption algorithm which is used to
|
||||
// encrypt any streams created by the current runtime. The default is
|
||||
// Blowfish; the complete set of available algorithms is defined by
|
||||
// the current version of OpenSSL. This value is used only to control
|
||||
// encryption; the correct algorithm will automatically be selected on
|
||||
// decryption.
|
||||
const string encryption_algorithm =
|
||||
config_express.GetString("encryption-algorithm", "bf-cbc");
|
||||
|
||||
// This defines the key length, in bits, for the selected encryption
|
||||
// algorithm. Some algorithms have a variable key length. Specifying
|
||||
// a value of 0 here means to use the default key length for the
|
||||
// algorithm as defined by OpenSSL.
|
||||
const int encryption_key_length =
|
||||
config_express.GetInt("encryption-key-length", 0);
|
||||
|
||||
// This defines the number of times the password is hashed to generate
|
||||
// a key when encrypting. Its purpose is to make it computationally
|
||||
// more expensive for an attacker to search the key space
|
||||
// exhaustively. This should be a multiple of 1,000 and should not
|
||||
// exceed about 65 million. This value is used only to control
|
||||
// encryption; the correct count will automatically be selected on
|
||||
// decryption.
|
||||
const int encryption_iteration_count =
|
||||
config_express.GetInt("encryption-iteration-count", 100000);
|
||||
|
||||
// Set this true to use the VirtualFileSystem mechanism for loading
|
||||
// models, etc. Since the VirtualFileSystem maps to the same as the
|
||||
// actual file system by default, there is probably no reason to set
|
||||
|
@ -56,6 +56,10 @@ extern const double clock_degrade_factor;
|
||||
extern const double max_dt;
|
||||
extern const double sleep_precision;
|
||||
|
||||
extern const string encryption_algorithm;
|
||||
extern const int encryption_key_length;
|
||||
extern const int encryption_iteration_count;
|
||||
|
||||
extern EXPCL_PANDAEXPRESS const bool use_vfs;
|
||||
|
||||
extern EXPCL_PANDAEXPRESS const bool collect_tcp;
|
||||
|
@ -77,11 +77,10 @@ OEncryptStream() : ostream(&_buf) {
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE OEncryptStream::
|
||||
OEncryptStream(ostream *dest, bool owns_dest, const string &password,
|
||||
const string &encryption_algorithm) :
|
||||
OEncryptStream(ostream *dest, bool owns_dest, const string &password) :
|
||||
ostream(&_buf)
|
||||
{
|
||||
open(dest, owns_dest, password, encryption_algorithm);
|
||||
open(dest, owns_dest, password);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -90,10 +89,9 @@ OEncryptStream(ostream *dest, bool owns_dest, const string &password,
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE OEncryptStream &OEncryptStream::
|
||||
open(ostream *dest, bool owns_dest, const string &password,
|
||||
const string &encryption_algorithm) {
|
||||
open(ostream *dest, bool owns_dest, const string &password) {
|
||||
clear((ios_iostate)0);
|
||||
_buf.open_write(dest, owns_dest, password, encryption_algorithm);
|
||||
_buf.open_write(dest, owns_dest, password);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -22,16 +22,14 @@
|
||||
// Function: encrypt_string
|
||||
// Access: Published
|
||||
// Description: Encrypts the indicated source string using the given
|
||||
// password and algorithm (or empty string for the
|
||||
// default algorithm). Returns the encrypted string.
|
||||
// password. Returns the encrypted string.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
string
|
||||
encrypt_string(const string &source, const string &password,
|
||||
const string &algorithm) {
|
||||
encrypt_string(const string &source, const string &password) {
|
||||
ostringstream output;
|
||||
|
||||
{
|
||||
OEncryptStream encrypt(&output, false, password, algorithm);
|
||||
OEncryptStream encrypt(&output, false, password);
|
||||
encrypt.write(source.data(), source.length());
|
||||
}
|
||||
|
||||
|
@ -67,12 +67,10 @@ class EXPCL_PANDAEXPRESS OEncryptStream : public ostream {
|
||||
public:
|
||||
INLINE OEncryptStream();
|
||||
INLINE OEncryptStream(ostream *dest, bool owns_dest,
|
||||
const string &password,
|
||||
const string &encryption_algorithm = "");
|
||||
const string &password);
|
||||
|
||||
INLINE OEncryptStream &open(ostream *dest, bool owns_dest,
|
||||
const string &password,
|
||||
const string &encryption_algorithm = "");
|
||||
const string &password);
|
||||
INLINE OEncryptStream &close();
|
||||
|
||||
private:
|
||||
@ -80,8 +78,7 @@ private:
|
||||
};
|
||||
|
||||
BEGIN_PUBLISH
|
||||
string encrypt_string(const string &source, const string &password,
|
||||
const string &algorithm = "");
|
||||
string encrypt_string(const string &source, const string &password);
|
||||
string decrypt_string(const string &source, const string &password);
|
||||
END_PUBLISH
|
||||
|
||||
|
@ -30,6 +30,10 @@
|
||||
typedef int streamsize;
|
||||
#endif /* HAVE_STREAMSIZE */
|
||||
|
||||
// The iteration count is scaled by this factor for writing to the
|
||||
// stream.
|
||||
static const int iteration_count_factor = 1000;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EncryptStreamBuf::Constructor
|
||||
// Access: Public
|
||||
@ -88,6 +92,8 @@ open_read(istream *source, bool owns_source, const string &password) {
|
||||
// Now read the header information.
|
||||
StreamReader sr(_source, false);
|
||||
int nid = sr.get_uint16();
|
||||
int key_length = sr.get_uint16();
|
||||
int count = sr.get_uint16();
|
||||
|
||||
const EVP_CIPHER *cipher = EVP_get_cipherbynid(nid);
|
||||
|
||||
@ -98,25 +104,39 @@ open_read(istream *source, bool owns_source, const string &password) {
|
||||
}
|
||||
|
||||
express_cat.debug()
|
||||
<< "Using decryption algorithm " << OBJ_nid2sn(nid) << "\n";
|
||||
<< "Using decryption algorithm " << OBJ_nid2sn(nid) << " with key length "
|
||||
<< key_length * 8 << " bits.\n";
|
||||
|
||||
int iv_length = EVP_CIPHER_iv_length(cipher);
|
||||
int key_length = EVP_CIPHER_key_length(cipher);
|
||||
_read_block_size = EVP_CIPHER_block_size(cipher);
|
||||
|
||||
string iv = sr.extract_bytes(iv_length);
|
||||
|
||||
unsigned char *key = (unsigned char *)alloca(key_length);
|
||||
// Initialize the context
|
||||
int result;
|
||||
result = EVP_DecryptInit(&_read_ctx, cipher, NULL, (unsigned char *)iv.data());
|
||||
nassertv(result > 0);
|
||||
|
||||
result = EVP_CIPHER_CTX_set_key_length(&_read_ctx, key_length);
|
||||
if (result <= 0) {
|
||||
express_cat.error()
|
||||
<< "Invalid key length " << key_length * 8 << " bits for algorithm "
|
||||
<< OBJ_nid2sn(nid) << "\n";
|
||||
EVP_CIPHER_CTX_cleanup(&_read_ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
// Hash the supplied password into a key of the appropriate length.
|
||||
int result;
|
||||
unsigned char *key = (unsigned char *)alloca(key_length);
|
||||
result =
|
||||
PKCS5_PBKDF2_HMAC_SHA1((const char *)password.data(), password.length(),
|
||||
(unsigned char *)iv.data(), iv.length(), 1,
|
||||
(unsigned char *)iv.data(), iv.length(),
|
||||
count * iteration_count_factor,
|
||||
key_length, key);
|
||||
nassertv(result > 0);
|
||||
|
||||
result = EVP_DecryptInit(&_read_ctx, cipher, key, (unsigned char *)iv.data());
|
||||
// Store the key within the context.
|
||||
result = EVP_DecryptInit(&_read_ctx, NULL, key, NULL);
|
||||
nassertv(result > 0);
|
||||
|
||||
_read_valid = true;
|
||||
@ -157,8 +177,7 @@ close_read() {
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void EncryptStreamBuf::
|
||||
open_write(ostream *dest, bool owns_dest, const string &password,
|
||||
const string &encryption_algorithm) {
|
||||
open_write(ostream *dest, bool owns_dest, const string &password) {
|
||||
OpenSSL_add_all_algorithms();
|
||||
|
||||
close_write();
|
||||
@ -166,14 +185,8 @@ open_write(ostream *dest, bool owns_dest, const string &password,
|
||||
_owns_dest = owns_dest;
|
||||
_write_valid = false;
|
||||
|
||||
const EVP_CIPHER *cipher;
|
||||
if (encryption_algorithm.empty()) {
|
||||
// Blowfish is the default algorithm.
|
||||
cipher = EVP_bf_cbc();
|
||||
|
||||
} else {
|
||||
cipher = EVP_get_cipherbyname(encryption_algorithm.c_str());
|
||||
}
|
||||
const EVP_CIPHER *cipher =
|
||||
EVP_get_cipherbyname(encryption_algorithm.c_str());
|
||||
|
||||
if (cipher == NULL) {
|
||||
express_cat.error()
|
||||
@ -182,36 +195,62 @@ open_write(ostream *dest, bool owns_dest, const string &password,
|
||||
};
|
||||
|
||||
int nid = EVP_CIPHER_nid(cipher);
|
||||
express_cat.debug()
|
||||
<< "Using encryption algorithm " << OBJ_nid2sn(nid) << "\n";
|
||||
|
||||
int key_length = EVP_CIPHER_key_length(cipher);
|
||||
int iv_length = EVP_CIPHER_iv_length(cipher);
|
||||
_write_block_size = EVP_CIPHER_block_size(cipher);
|
||||
|
||||
unsigned char *key = (unsigned char *)alloca(key_length);
|
||||
unsigned char *iv = (unsigned char *)alloca(iv_length);
|
||||
|
||||
// Generate a random IV. It doesn't need to be cryptographically
|
||||
// secure, just unique.
|
||||
RAND_pseudo_bytes(iv, iv_length);
|
||||
|
||||
// Hash the supplied password into a key of the appropriate length.
|
||||
int result;
|
||||
result = EVP_EncryptInit(&_write_ctx, cipher, NULL, iv);
|
||||
nassertv(result > 0);
|
||||
|
||||
// Store the appropriate key length in the context.
|
||||
int key_length = (encryption_key_length + 7) / 8;
|
||||
if (key_length == 0) {
|
||||
key_length = EVP_CIPHER_CTX_key_length(cipher);
|
||||
}
|
||||
result = EVP_CIPHER_CTX_set_key_length(&_write_ctx, key_length);
|
||||
if (result <= 0) {
|
||||
express_cat.error()
|
||||
<< "Invalid key length " << key_length * 8 << " bits for algorithm "
|
||||
<< OBJ_nid2sn(nid) << "\n";
|
||||
EVP_CIPHER_CTX_cleanup(&_write_ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
express_cat.debug()
|
||||
<< "Using encryption algorithm " << OBJ_nid2sn(nid) << " with key length "
|
||||
<< key_length * 8 << " bits.\n";
|
||||
|
||||
// Hash the supplied password into a key of the appropriate length.
|
||||
int count = encryption_iteration_count / iteration_count_factor;
|
||||
unsigned char *key = (unsigned char *)alloca(key_length);
|
||||
result =
|
||||
PKCS5_PBKDF2_HMAC_SHA1((const char *)password.data(), password.length(),
|
||||
iv, iv_length, 1, key_length, key);
|
||||
iv, iv_length, count * iteration_count_factor,
|
||||
key_length, key);
|
||||
nassertv(result > 0);
|
||||
|
||||
result = EVP_EncryptInit(&_write_ctx, cipher, key, iv);
|
||||
// Store the key in the context.
|
||||
result = EVP_EncryptInit(&_write_ctx, NULL, key, NULL);
|
||||
nassertv(result > 0);
|
||||
|
||||
_write_valid = true;
|
||||
|
||||
// Now write the header information to the stream.
|
||||
StreamWriter sw(_dest);
|
||||
nassertv((PN_uint16)nid == nid);
|
||||
sw.add_uint16(nid);
|
||||
nassertv((PN_uint16)key_length == key_length);
|
||||
sw.add_uint16(key_length);
|
||||
nassertv((PN_uint16)count == count);
|
||||
sw.add_uint16(count);
|
||||
sw.append_data(iv, iv_length);
|
||||
|
||||
_write_valid = true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
@ -39,8 +39,7 @@ public:
|
||||
void open_read(istream *source, bool owns_source, const string &password);
|
||||
void close_read();
|
||||
|
||||
void open_write(ostream *dest, bool owns_dest, const string &password,
|
||||
const string &encryption_algorithm);
|
||||
void open_write(ostream *dest, bool owns_dest, const string &password);
|
||||
void close_write();
|
||||
|
||||
protected:
|
||||
|
@ -84,12 +84,11 @@ get_scale_factor() const {
|
||||
// encryption.
|
||||
//
|
||||
// When true, subfiles will be encrypted with the
|
||||
// password and algorithm specified by
|
||||
// set_encryption_password() and
|
||||
// set_encryption_algorithm(). It is possible to apply
|
||||
// a different password or algorithm to different files,
|
||||
// but you must call flush() or repack() before changing
|
||||
// these properties.
|
||||
// password specified by set_encryption_password(). It
|
||||
// is possible to apply a different password to
|
||||
// different files, but you must call flush() or
|
||||
// repack() before changing these properties, and the
|
||||
// resulting file can't be mounted via VFS.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void Multifile::
|
||||
set_encryption_flag(bool flag) {
|
||||
@ -141,36 +140,6 @@ get_encryption_password() const {
|
||||
return _encryption_password;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Multifile::set_encryption_algorithm
|
||||
// Access: Published
|
||||
// Description: Specifies the algorithm that will be used to encrypt
|
||||
// subfiles subsequently added to the multifile, if the
|
||||
// encryption flag is also set true (see
|
||||
// set_encryption_flag()).
|
||||
//
|
||||
// The empty string, which is the initial value for this
|
||||
// parameter, implies the default encryption algorithm.
|
||||
// The complete list of available encryption algorithms
|
||||
// is defined by OpenSSL.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void Multifile::
|
||||
set_encryption_algorithm(const string &algorithm) {
|
||||
_encryption_algorithm = algorithm;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Multifile::get_encryption_algorithm
|
||||
// Access: Published
|
||||
// Description: Returns the algorithm that will be used to encrypt
|
||||
// subfiles subsequently added to the multifile. See
|
||||
// set_encryption_algorithm().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const string &Multifile::
|
||||
get_encryption_algorithm() const {
|
||||
return _encryption_algorithm;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Multifile::read_subfile
|
||||
// Access: Published
|
||||
|
@ -1574,8 +1574,7 @@ write_data(ostream &write, istream *read, streampos fpos,
|
||||
if ((_flags & SF_encrypted) != 0) {
|
||||
// Write it encrypted.
|
||||
putter = new OEncryptStream(putter, delete_putter,
|
||||
multifile->_encryption_password,
|
||||
multifile->_encryption_algorithm);
|
||||
multifile->_encryption_password);
|
||||
delete_putter = true;
|
||||
|
||||
// Also write the encrypt_header to the beginning of the
|
||||
|
@ -59,8 +59,6 @@ PUBLISHED:
|
||||
INLINE bool get_encryption_flag() const;
|
||||
INLINE void set_encryption_password(const string &password);
|
||||
INLINE const string &get_encryption_password() const;
|
||||
INLINE void set_encryption_algorithm(const string &algorithm);
|
||||
INLINE const string &get_encryption_algorithm() const;
|
||||
|
||||
string add_subfile(const string &subfile_name, const Filename &filename,
|
||||
int compression_level);
|
||||
@ -167,7 +165,6 @@ private:
|
||||
|
||||
bool _encryption_flag;
|
||||
string _encryption_password;
|
||||
string _encryption_algorithm;
|
||||
|
||||
ifstream _read_file;
|
||||
ofstream _write_file;
|
||||
|
Loading…
x
Reference in New Issue
Block a user