/* vi: set tabstop=4 nocindent noautoindent: */

/**
暗号用ライブラリ  cipher.c

  ヘッダ 
	  #include "cipher.h"

 */





#include "cipher.h"




/**
Buffer  xlcrypt(Buffer str, Buffer salt)

	機能: crypt関数(DES)による passwdの多重（２回）ハッシュ値化．
		  saltの長さに応じて,パスワードを多重にハッシュ値化する．
		  saltの2Byte毎に一回ハッシュ値化を行う．

	引数: passwd	ハッシュ値化するパスワード．
		  salt 		saltキー．(文字列）

	戻り値: ハッシュ値されたパスワードストリング．saltキーは返さない．通常 11Byte.

 */
Buffer  xlcrypt(Buffer str, Buffer salt)
{
	int   i, len, lsalt;
	char* passwd;
	char  pass[LPASS+1];
	Buffer ret;

	memset(pass, 0, LPASS+1);
	len = Min((int)strlen((const char*)str.buf), LPASS);
	memcpy(pass, str.buf, len);

	lsalt = ((int)strlen((const char*)salt.buf)/2)*2;
	if (lsalt>=2) {
		passwd = (char*)crypt((const char*)pass, (const char*)salt.buf);
		if (strncmp((const char*)salt.buf, "$1$", 3)) {
			// DES
			for (i=2; i<lsalt; i=i+2) {
				passwd = (char*)crypt((const char*)(passwd+2), (const char*)(salt.buf+i));
			}
			ret = set_Buffer(passwd+2, -1);
		}
		else {
			// MD5
			ret = set_Buffer(passwd+12, -1);
		}
	}
	else {
		ret = init_Buffer();
	}

	return ret;
}





/**
void  setkey_byBase64(Buffer key)

	機能: Base64によってエンコードされた文字列をデコードし,それを
		  encrypt関数(DES)の暗号化キーとして設定する．キー長は通常
		  8Byte(64bit)だが,有効なものは最初の7Byte(56bit)である．

	引数: key	 暗号化のキー

	戻り値: なし．
*/
void  setkey_byBase64(Buffer key)
{
	Buffer tmpkey, deskey; 

	tmpkey = decode_base64_Buffer(key);
	deskey = to_bin64(tmpkey); 

	setkey((const char*)deskey.buf);
	free_Buffer(&tmpkey);
	free_Buffer(&deskey);
	return;
}
	



/**
void  setkey_byBuffer(Buffer key)

	機能: アスキー文字(8Byte)を用いて,encrypt関数(DES)の暗号化キー
		  を設定する．ただし,キーとして有もなものは最初の7Byteである．

	引数: key  -- 暗号化のキー

	戻り値: なし．
*/
void  setkey_byBuffer(Buffer key)
{
	Buffer deskey; 

	deskey = to_bin64(key); 
	setkey((const char*)deskey.buf);
	free_Buffer(&deskey);

	return;
}





/**
Buffer  encrypt_Buffer(Buffer buf, int mode)

	機能: バイナリデータの暗号化または復号化を行う(DES)．
		  この関数を呼ぶ前に, setkey_XXXX()関数で暗号化キーを設定しなければ
		  ならない．

	引数: buf   --  暗号化または復号化を行うデータ．
		  mode  --  0  暗号化
				--  1  復号化

	戻り値: 暗号化の場合 -- 暗号化されたデータ．
			復号化の場合 -- 復号化されたデータ．
*/
Buffer  encrypt_Buffer(Buffer buf, int mode)
{
	Buffer  str, cry;

	str = to_bin64(buf);
	encrypt((char*)str.buf, mode);
	cry = from_bin64(str);
	free_Buffer(&str);
	return  cry;
}




/**
Buffer  encrypt_Base64(Buffer str, int mode)

	機能: 文字列の暗号化または復号化を行う(DES)．暗号化または復号化される
		  文字列はBase64でエンコードされている．内部では一旦 Base64から
		  デコードされて処理がおこなわれ，再びエンコードされる．
		  この関数を呼ぶ前に, setkey_XXXX()関数で暗号化キーを設定しなければ
		  ならない．

	引数: str   --  暗号化または復号化を行う Base64文字列．
		  mode  --  0  暗号化
				--  1  復号化

	戻り値: 暗号化または復号化された文字列．Base64でエンコードされる．
*/
Buffer  encrypt_Base64(Buffer buf, int mode)
{
	Buffer dec, str, enc;

	dec = decode_base64_Buffer(buf);
	str = encrypt_Buffer(dec, mode);
	free_Buffer(&dec);

	enc = encode_base64_Buffer(str);
	free_Buffer(&str);
	return enc;
}






/**
Buffer  to_bin64(Buffer str)

	機能：Bit列を 0,1のバイト列(64Byte)に変換する (bin64形式に件関する)．
		  例えば、整数の 2は 0,0,0,0,0,.....,0,1,0 のバイト列(64Byte)になる．

	引数：str   バイト列に変換するビット列．

	戻り値：変換されたバイト列．1バイトの 0,1の列．bin64形式．
*/
Buffer  to_bin64(Buffer str)
{
	int	i, mi;
	Buffer ret;

	ret = make_Buffer(64);
	if (ret.buf==NULL) return ret;

	mi = Min(64, str.vldsz*8);
	for (i=0; i<mi; i++) ret.buf[i] = (uByte)getBit(str.buf, i);
	ret.vldsz = mi;
	return ret;
}





/**
Buffer  from_bin64(Buffer str)

	機能：0,1のバイト列(64Byte, bin64形式)を 8byteのビット列に変換する．

	引数：str   ビット列に変換するバイト列．64Byte. bin64形式．

	戻り値：変換されたビット列．8Byte.  64bit.
*/
Buffer  from_bin64(Buffer str)
{
	int	i;
	Buffer ret;
	
	ret = init_Buffer();
	if (str.vldsz!=64) return ret;

	ret = make_Buffer(8);
	if (ret.buf==NULL) return ret;

	for (i=0; i<64; i++) setBit(ret.buf, i, (int)str.buf[i]);
	ret.vldsz = 8;
	return  ret;
}





/**
void  dump_bin64(char* format, Buffer str)

	機能：bin64形式を標準エラー出力に表示する．

	引数：format  bin64の内容を表示する前に表示するタイトル．
		  str	 表示する bin64形式のバイト列

	戻り値：なし．
*/
void  dump_bin64(char* format, Buffer str)
{
	int  i;

	fprintf(stderr, format);
	for (i=0; i<str.vldsz; i++) fprintf(stderr, "%1d", str.buf[i]);
	fprintf(stderr, "\n");
}



