/* $Id: gpasswd.cpp,v 1.15 2004/01/02 03:54:01 fesnel Exp $ */
/*******************************************************************************
 *   This program is part of a library used by the Archimedes email client     * 
 *                                                                             *
 *   Copyright : (C) 1995-1998 Gennady B. Sorokopud (gena@NetVision.net.il)    *
 *               (C) 1995 Ugen. J. S. Antsilevich (ugen@latte.worldbank.org)   *
 *               (C) 1998-2004 by the Archimedes Project                       *
 *                   http://sourceforge.net/projects/archimedes                *
 *                                                                             *
 *             --------------------------------------------                    *
 *                                                                             *
 *   This program is free software; you can redistribute it and/or modify      *
 *   it under the terms of the GNU Library General Public License as published *
 *   by the Free Software Foundation; either version 2 of the License, or      *
 *   (at your option) any later version.                                       *
 *                                                                             *
 *   This program is distributed in the hope that it will be useful,           *
 *   but WITHOUT ANY WARRANTY, without even the implied warranty of            *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
 *   GNU Library General Public License for more details.                      *
 *                                                                             *
 *   You should have received a copy of the GNU Library General Public License *
 *   along with this program; if not, write to the Free Software               *
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston MA 02111-1307, USA.  *
 *                                                                             *
 ******************************************************************************/

//#define GPASSWD_TEST
//#define GPASSWD_USE_MHASH

#include <fmail.h>

#ifdef USE_GPASSWD

#include "gpasswd.h"

#ifdef GPASSWD_USE_MHASH
#include <mhash.h>
#endif

gPasswd::gPasswd() {
	keysize = GPASSWD_KEYSIZE;
	td = MCRYPT_FAILED;
	key = NULL;
	IV = NULL;
	passphrase[0] = '\0';
}

void gPasswd::init(string pass) {

	if (!key)
		key = new char[keysize+1];	

	setKey(pass);

	td = mcrypt_module_open("twofish", NULL, "cfb", NULL);
	if(td == MCRYPT_FAILED) {
		cerr << "mcrypt_module_open failed...\n";
		return;
	}

	if (!IV)
		IV = new char[mcrypt_enc_get_iv_size(td)];

	srand(0);	/* initialise rand() each time init is called */
	for(i = 0; i < mcrypt_enc_get_iv_size(td); i++) 
		IV[i] = rand();

	// test mcrypt:
	i = mcrypt_generic_init(td, key, keysize, IV);
	if(i < 0) {
		mcrypt_perror(i);
		return;
	}
	mcrypt_generic_end(td);
}

void gPasswd::setKey(string pass) {
	strncpy(passphrase, pass.c_str(), GPASSWD_MAX_PASSPHRASE_LEN);
	passphrase[GPASSWD_MAX_PASSPHRASE_LEN] = '\0';

	/* Generate the key using the passphrase */
#ifdef GPASSWD_USE_MHASH
	mhash_keygen (KEYGEN_MCRYPT, MHASH_MD5, key, keysize, NULL,
	    0, passphrase, strlen(passphrase));
#else
	strncpy(key, passphrase, keysize);
	key[keysize] = '\0';
#endif
	
	return;
}

string gPasswd::encrypt(string password) {
	char * s_un = new char[password.size() + 1];
	string s_en;

	strcpy(s_un, password.c_str());
	// cerr << "encrypt: s_un = (" << s_un << ") " <<  endl;

	td = mcrypt_module_open("twofish", NULL, "cfb", NULL);
	mcrypt_generic_init(td, key, keysize, IV);
	mcrypt_generic(td, s_un, strlen(s_un));
	mcrypt_generic_end(td);
	s_en = string(s_un);
	// cerr << "encrypt: s_en = (" << s_en  << ") " << endl;
	delete [] s_un;

	return s_en;
}

string gPasswd::decrypt(string password) {
	char * s_en = new char[password.size() + 1];
	string s_un;

	strcpy(s_en, password.c_str());
	// cerr << "decrypt(" << s_en << ")" << endl;
	td = mcrypt_module_open("twofish", NULL, "cfb", NULL);
	mcrypt_generic_init(td, key, keysize, IV);
	mdecrypt_generic(td, s_en, strlen(s_en));
	mcrypt_generic_end(td);
	s_un = string(s_en);
	// cerr << "decrypt: s_un =(" << s_un << ")" << endl;
	delete [] s_en;

	return s_un;
}

gPasswd::~gPasswd() {
	if (IV)
		delete [] IV;
	if (key)
		delete [] key;
}


#endif

#ifdef GPASSWD_TEST

int main(int argc, char * argv[]) {

	ifstream ifs;
	ofstream ofs;
	string s_en, s_un, key, pass;
	gPasswd Passwd;

	cout << "enter key" << endl;
	cin >> key;

	Passwd.init(key);

	cout << "enter pass" << endl;
	cin >> pass;

	s_en = Passwd.encrypt(pass);
	cout << "encrypted: \"" << s_en << "\"" <<  endl;

	s_un = Passwd.decrypt(s_en);
	cout << "decrypted: \"" << s_un << "\"" <<  endl;

	cout << "Testing File I/O\n";

	ofs.open("test", ios::bin);
	ofs << s_en << endl;
	ofs.close();

	ifs.open("test", ios::bin);
	ifs >> s_en;
	ifs.close();

	cout << "encrypted: \"" << s_en << "\"" <<  endl;
	s_un = Passwd.decrypt(s_en);
	cout << "decrypted: \"" << s_un << "\"" <<  endl;

	return 0;
}
#endif






