使用Crypto++加解密类库实现密码管理系统

       Crypto++是一个免费的加解密类库,集成了很多的加解密算法,如des, aes, rsa等基础加密算法。本文主要谈一下本人最近实现的一个密码管理器,编译环境是32位Ubuntu,主要实现了多用户系统,可以创建用户、创建完成之后将密码经过HMAC存入用户文件、用户登录后需要对用户文件进行完整性检测保证外部修改、添加删除修改查看密码记录、记录以(域名、aes加密后密码、前两者结合的HMAC)形式存入文件。


程序架构

        由于管理器采用终端显示设计,就是说不同的代码段会不停地被调用。如果程序设计得不好的话,容易造成函数的嵌套调用,甚至栈空间无法释放,内存泄露等问题。为了避免这个问题,使用函数指针来规划整一个程序,有点像回调函数的感觉。整个管理器在运行时维护一个函数指针,每一次的函数调用都由这个指针来指定,而且保证每一个函数都执行完毕,避免函数变量占用栈空间。

typedef void (*func)();     

        以上代码定义了一个指针类型func,该指针类型可以指向一个返回值为void、0个参数的函数。因此,定义的功能函数中,都需要保证符合这一指针类型。

整体流程:

使用Crypto++加解密类库实现密码管理系统_第1张图片  

int main(){

	printWelcome();

	processor();      // run the procession

	return 0;
}
func iter_func = main_page;

// the processor interface
void  processor(){

	while( iter_func != NULL){
		(*iter_func)();
	}
	//quit
	cout <<  "bye!\n" << endl;
}

使用Crypto++加解密类库实现密码管理系统_第2张图片


使用Crypto++进行HMAC运算

HMAC只能用来进行校验,不能用来加密,因此可以用来做密码验证的作用,类似于md5。

// check hmac of a domain with its password
string check_hmac(string infor, string key){
	string mac, encoder;
	string derived;
	HexDecoder  decoder (new StringSink(derived));
	decoder.Put((const byte*)key.data(), key.size());
	decoder.MessageEnd();
	try{
		HMAC hmac((const byte*)derived.data(), derived.size());
		StringSource(infor, true, new HashFilter(hmac, new StringSink(mac)));
	}catch(const CryptoPP::Exception& e){
		cerr << e.what() << endl;
		exit(1);
	}
	encoder.clear();
	StringSource(mac, true, new HexEncoder(new StringSink(encoder)));
	return encoder;     //return HMAC
}

使用crypto++进行AES加解密

AES算法有较强的安全性,可以用来做密码的加密。当需要查询密码时,可以采用解密方式解出来。

string aes_decrypt(string password, string key){
	// decrypt the password
	string recovered;
	string derived; 
	HexDecoder decoder(new StringSink(derived));
	decoder.Put( (byte*)key.data(),key.size() );
	decoder.MessageEnd();
	

	string cipher;
	HexDecoder decoder2(new StringSink(cipher));
	decoder2.Put( (byte*)password.data(), password.size() );
	decoder2.MessageEnd();
	try{
		CFB_Mode< AES >::Decryption d;
		d.SetKeyWithIV((byte*)derived.data(), derived.size(),iv);
		StringSource s(cipher, true, new StreamTransformationFilter(d,new StringSink(recovered)));
	}catch(const CryptoPP::Exception& e){
		cerr << e.what() << endl;
		exit(1);
	}
	return recovered;
}

string aes_encrypt(string password, string key){
	//to do 
	string cipher, encoded;

	string derived; 
	HexDecoder decoder(new StringSink(derived));
	decoder.Put((byte*)key.data(), key.size() );
	decoder.MessageEnd();		
   	 try{
	        CFB_Mode< AES >::Encryption e;
		e.SetKeyWithIV((byte*)derived.data(), derived.size(), iv);
		StringSource(password, true, new StreamTransformationFilter(e, new StringSink(cipher)) ); 
	}catch(const CryptoPP::Exception& e){
		cerr << e.what() << endl;
		exit(1);
	}
   	encoded.clear();
	StringSource(cipher, true,new HexEncoder(new StringSink(encoded)) ); 
	return encoded;
}

整体实现

完整代码放在https://github.com/Jreffery/PasswordManager,有兴趣的朋友可以看一下。

你可能感兴趣的:(日常开发)